Πέμπτη, 20 Ιουλίου 2017

Αναθεώρηση 16 (Έκδοση 8.9)

Μια αναθεώρηση, και ένα ωραίο παράδειγμα. Εδώ θα περάσουμε ονόματα πόλεων σε ένα μη ισορροπημένο δένδρο. Θέλουμε να δείξουμε τις πόλεις σε αλφαβητική σειρά, με αύξουσα και με φθίνουσα σειρα.
Στο δεύτερο πιο προχωρημένο πρόγραμμα, δημιουργούμε ένα αντικείμενο που κρατάει τις ρουτίνες που μοιάζουν με αυτές του πρώτου παραδείγματος. Επιπλέον μέσο ενός γεγονότος ανακατευθύνουμε την έξοδο από αυτό, κατά την ανάγνωση του!
Το παρακάτω μπήκε από την αναθεώρηση 17, και έτσι η Κέρκυρα έρχεται μετά την Καστοριά. Ο διακόπτης "+txt" κάνει τις συγκρίσεις αλφαριθμητικών να γίνονται ως κείμενο και όχι ως δυαδικές τιμές. Ως δυαδικές τιμές το έ έχει μικρότερη τιμή από το α, ενώ ως κείμενο το α είναι μικρότερο από το έ.
Θέσε Διακόπτες "+txt"
\\ Για την έκδοση 8.9 αναθεώρηση 16
\\ απλό δένδρο (μη ισορροπημένο)
\\ κάθε κόμβος μπορεί να έχει μια τιμή και να δείχνει σε δυο κόμβους
\\ κάθε κόμβος είναι ένας πίνακας τριών στοιχείων
\\ το μεσαίο στοιχείο είναι το αλφαριθμητικό
\\ το πρώτο και το τρίτο (το 0 και το 2), έχουν ή κενό πίνακα ή κόμβο, δηλαδή πίνακα με τρια στοιχεία)
\\ Χρησιμοποιείται η νέα παραλλαγή της Προσθήκης για δείκτες σε πίνακες
\\ Η δομή ξεκινάει από έναν δείκτη, την δομή_δένδρου
\\ Επειδή γίνεται χρήση ρουτινών, χωρίς χρήση μπλοκ κώδικα κατά τις κλήσεις....
\\ έχουμε μεγάλο όριο αναδρομής, το οποίο μπορούμε να το ορίσουμε:
\\ στις ρουτίνες δίνουμε μόνο δείκτες προς πίνακες, και ενώ περνούν με τιμή...
\\ δουλεύουν σαν να είναι με αναφορά.
\\ Στη Μ2000 σε ένα δείκτη δεν μπορούμε να βάλουμε οτιδήποτε, αλλά έναν δείκτη αντικειμένου
\\ Αντικείμενα είναι οι δείκτες σε πίνακα, οι καταστάσεις (λίστες με κλειδιά), και οι σωροί (ειδικές στοίβες)
Όριο.Αναδρομής 50000
δομή_δένδρου=(,)
Τύπωσε Τύπος$(δομή_δένδρου)
Βάλε_Ένα(δομή_δένδρου,"Πρέβεζα")
Βάλε_Ένα(δομή_δένδρου,"Αθήνα")
Βάλε_Ένα(δομή_δένδρου,"Κέρκυρα")
Βάλε_Ένα(δομή_δένδρου,"Πάργα")
Βάλε_Ένα(δομή_δένδρου,"Καστοριά")
Βάλε_Ένα(δομή_δένδρου,"Χανιά")
Βάλε_Ένα(δομή_δένδρου,"Πάτρα")
Βάλε_Ένα(δομή_δένδρου,"Βόλος")
Τύπωσε_Όλα(δομή_δένδρου)
Τύπωσε "........Αλλιώς.........."
Τύπωσε_Όλα_Αλλιώς(δομή_δένδρου)
Ρουτίνα Βάλε_Ένα(εδώ, τι$)
      Αν μήκος(εδώ)=0 τότε Προσθήκη εδώ, ((,),τι$,(,)) : Έξοδος Ρουτίνας
      Αν τι$<Πίνακας$(εδώ,1) Τότε Βάλε_Ένα( Πίνακας(εδώ,0), τι$) : Έξοδος Ρουτίνας
      Βάλε_Ένα(Πίνακας(εδώ,2), τι$)
Τέλος Ρουτίνας
Ρουτίνα Τύπωσε_Όλα(εδώ)
      Αν μήκος(εδώ)=0 τότε Έξοδος Ρουτίνας
      Τύπωσε_Όλα(Πίνακας(εδώ,0))
      Τύπωσε Πίνακας$(εδώ,1)
      Τύπωσε_Όλα(Πίνακας(εδώ,2))
Τέλος Ρουτίνας
Ρουτίνα Τύπωσε_Όλα_Αλλιώς(εδώ)
      Αν μήκος(εδώ)=0 τότε Έξοδος Ρουτίνας
      Τύπωσε_Όλα_Αλλιώς(Πίνακας(εδώ,2))
      Τύπωσε Πίνακας$(εδώ,1)
      Τύπωσε_Όλα_Αλλιώς(Πίνακας(εδώ,0))
Τέλος Ρουτίνας


Και η δεύτερη εκδοχή με αντικείμενο και ανακατεύθυνση εξαγωγής με χρήση γεγονότος.Χρησιμοποιούμε γενικό Γεγονός (καθολικό), αλλά όπως και όλες οι γενικές στη Μ2000, είναι προσωρινές, μέχρι να τερματίσει αυτό που τις έφτιαξε, και επίσης το τοπικό έρχεται πρώτο στην προτίμηση του διερμηνευτή, δηλαδή οι γενικές σκιάζονται!
Στα γεγονότα δηλώνουμε μια "υπογραφή" με μια διάβασε για το τι περιμένει στη κλήση γεγονότας, ενώ τα ονόματα στην περιγραφή απλά λένε στο διερμηενυτή κάτι για το τύπο (αν δεν δηλώνεται επακριβώς πάντα, πχ το κάτι$ είναι φανερό ότι είναι αλφαριθμητικό, ενώ ένα κάτι_άλλο θα μπορούσε να ήταν δείκτης, ή μια λάμδα συνάρτηση, θα φανεί όμως στον αποδέκτη....). Στην υπογραφή βάζουμε και με πέρασμα με αναφορά με το & στην αρχή του ονόματος.
Κάθε Γεγονός έχει μια λίστα συναρτήσεων, ακόμα και ίδιων, που καλεί με τη σειρά (multicast). Με την νέο βάζουμε νέα συνάρτηση, με την πέτα πετάμε αυτή που ζητάμε, με τη Καθαρό πετάμε όλες τις συναρτήσεις και μπαίνει σε κράτηση, με τη Κράτησε το γεγονός αγνοεί την κλήση ενώ την λίστα των παραμέτρων την εκτελεί (απλά δεν συνεχίζει σε κλήση), με το Άφησε αφήνουμε το γεγονός να εκτελεί.

Εδώ φαίνονται τρια διαφορετικά περάσματα συναρτήσεων. Απλή συνάρτηση όπως η Τ(). Συνάρτηση από αντικείμενο, για να καταγράψουμε πόσες φορές "ζητήθηκε". Μάλιστα αυτές τις δυο τις έχουμε μαζί στην αρχή. Και τέλος μπορούμε να χρησιμοποιήσουμε την κλήση προς τα πίσω. Η κλήση προς τα πίσω γίνεται μέσω μιας ψεύτικης συνάρτησης. Αυτή η συνάρτηση εκτελείται σαν να είναι το τμήμα που την περιέχει, και έχει θέαση σε ότι έχει το τμήμα. Η συνάρτηση Οκν$()  (οκνηρή αποτίμηση), με την παραλλαγή αυτή που βλέπουμε εδώ (με αναφορά συνάρτησης), παράγει μια ανώνυμη συνάρτηση που όταν τρέχει μεταφέρεται στο περιβάλλον του τμήματος. Έτσι γεμίζουμε τον πίνακα Εδώ$()

Παρατηρούμε ότι με το Γεγονός, έχουμε ένα αντικείμενο με πολλές χρήσεις, χωρίς να προσθέσουμε σε αυτό κώδικα.

\\ Παράδειγμα με χρήση γεγονότος
Όριο.Αναδρομής 50000
Γενικό Γεγονός ΚάνεΚάτι {
      Διάβασε κάτι$
}
Κλάση Άλφα {
Ιδιωτικό:
      δομή_δένδρου=(,)
Δημόσιο:
      Τμήμα Καθάρισε {
            \\ χρήση τελείας στην αρχή και <= για εκχώρηση
            .δομή_δένδρου<=(,)
      }
      Τμήμα Βάλε_Ένα {
            Αν Ταύτιση("Γ") Τότε {
                  Βάλε_Ένα(.δομή_δένδρου, γράμμα$)
            } Αλλιώς.Αν Ταύτιση("Π") Τότε {
                  Διάβασε Π
                  Κ=Κάθε(Π)
                  Ενώ Κ {
                        Βάλε_Ένα(.δομή_δένδρου, Πίνακας$(Κ))
                  }
            }
            Ρουτίνα Βάλε_Ένα(εδώ, τι$)
                  Αν μήκος(εδώ)=0 τότε Προσθήκη εδώ, ((,),τι$,(,)) : Έξοδος Ρουτίνας
                  Αν τι$<Πίνακας$(εδώ,1) Τότε Βάλε_Ένα( Πίνακας(εδώ,0), τι$) : Έξοδος Ρουτίνας
                  Βάλε_Ένα(Πίνακας(εδώ,2), τι$)
            Τέλος Ρουτίνας
      }
      Τμήμα Τύπωσε_Όλα {
            Τύπωσε_Όλα(.δομή_δένδρου)
            Ρουτίνα Τύπωσε_Όλα(εδώ)
                  Αν μήκος(εδώ)=0 τότε Έξοδος Ρουτίνας
                  Τύπωσε_Όλα(Πίνακας(εδώ,0))
                  Κάλεσε Γεγονός ΚάνεΚάτι Πίνακας$(εδώ,1)
                  Τύπωσε_Όλα(Πίνακας(εδώ,2))
            Τέλος Ρουτίνας
      }
      Τμήμα Τύπωσε_Όλα_Αλλιώς {
            Τύπωσε_Όλα_Αλλιώς(.δομή_δένδρου)
            Ρουτίνα Τύπωσε_Όλα_Αλλιώς(εδώ)
                  Αν μήκος(εδώ)=0 τότε Έξοδος Ρουτίνας
                  Τύπωσε_Όλα_Αλλιώς(Πίνακας(εδώ,2))
                  Κάλεσε Γεγονός ΚάνεΚάτι Πίνακας$(εδώ,1)
                  Τύπωσε_Όλα_Αλλιώς(Πίνακας(εδώ,0))
            Τέλος Ρουτίνας
      }
}
Μ=Αλφα()
Συνάρτηση Τ {
      Τύπωσε γράμμα$
}
Ομάδα Μέτρησε {
      μετρητής
      Συνάρτηση Ένα {
            πέτα
            .μετρητής++
      }
}
Γεγονός ΚάνεΚάτι Νέο Τ(), Μέτρησε.Ένα()
Για Μ {
      .Βάλε_Ένα "Πρέβεζα"
      .Βάλε_Ένα "Αθήνα"
      .Βάλε_Ένα "Κέρκυρα"
      .Βάλε_Ένα "Πάργα"
      \\ εδώ δίνουμε πίνακα με λέξεις
      \\ για μια λέξη θέλει ("λέξη",)   (το κόμμα πριν την παρένθεση)
      .Βάλε_Ένα ("Καστοριά","Χανιά", "Πάτρα","Βόλος")
      .Τύπωσε_Όλα
      Γεγονός ΚάνεΚάτι Πέτα Μέτρησε.Ένα()
      Τύπωσε "........Αλλιώς.........."     
      .Τύπωσε_Όλα_Αλλιώς
}
Τύπωσε "σύνολο=";Μέτρησε.μετρητής
Γεγονός ΚάνεΚάτι Καθαρό \\ κάνει συνάμα και Κράτησε δηλαδή αγνοεί τις κλήσεις
\\ και κάτι πιο δύσκολο.
\\ θέλουμε να διατρέξουμε το δένδρο από αυτό το τμήμα, πχ να βάλουμε σε πίνακα τα στοιχεία
Πίνακας Βάση 1, Εδώ$(Μέτρησε.μετρητής)
αρ=1
Συνάρτηση Ψεύτικη {
      \\ αυτό είναι μέρος του τμήματος
      Διάβασε Εδώ$(αρ)
      αρ++
}
Γεγονός ΚάνεΚάτι Νέο Οκν$(&Ψεύτικη())
Γεγονός ΚάνεΚάτι Άφησε \\ τώρα το αφήνουμε να πάρει κλήσεις
Μ.Τύπωσε_Όλα
Γεγονός ΚάνεΚάτι Κράτησε
Μ.Καθάρισε   ' τώρα έχει αδειάσει ο πίνακας
\\ Τώρα έχουμε έναν πίνακα με πόλες, ταξινομημένο!
Τύπωσε "[Πόλεις]"
Για ι=1 έως Μέτρησε.μετρητής {
      Τύπωσε Εδώ$(ι)
}