Πέμπτη, 14 Ιουνίου 2018

Νέο "Μικρό Εγχειρίδιο της Μ2000"

Εδώ θα βρείτε την νέα έκδοση του μικρού εγχειριδίου της Μ2000 σε μορφή PDF (μπορεί να ανοιχτεί ως κείμενο σε LibreOffice Writer), με ημερομηνία στο εξώφυλλο 16-6-2018.  (άλλαξε από 15-6-2018)

Η προηγούμενη έκδοση ήταν από τον Μάϊο του 2017. Σε αυτήν την έκδοση έγινε μια αναδιοργάνωση, και προστέθηκε το κεφάλαιο 8 "Γραφικά 2Δ".


Σταδιακά θα εμπλουτίζεται. Ο σύνδεσμος στο αρχείο υπάρχει μόνιμα δεξιά στους συνδέσμους στις Προτεινόμενες Σελίδες.

Σάββατο, 9 Ιουνίου 2018

Ουρά με δείκτες (Queue with pointers)

Το πρόγραμμα γράφτηκε αρχικά με αγγλικές εντολές και μετά έγινε μετατροπή με ελληνικές. Όμως διατηρήθηκαν τα ονόματα των αναγνωριστικών με λατινικούς χαρακτήρες.(Προστέθηκε και ο κώδικας με όλα τα αναγνωριστικά στα ελληνικά).
Το πρόγραμμα δείχνει πως φτιάχνουμε μια δυναμική λίστα τύπου ουράς, όπου 'εχουμε πρόσβαση πάντα σε μια κορυφή, και μπορούμε να την πετάξουμε, μέχρι να αδειάσει η ουρά, ή μπορούμε να κόψουμε την ουρά σε δυο, μη την αρχική και μια δεύτερη, ή να ενώσουμε μια ουρά σε μια άλλη (στο τέλος της).
Δεν χρησιμοποιούμε πίνακες. Κάθε στοιχείο της ουράς είναι μια ομάδα που έχει ένα δείκτη σε μια άλλη ομάδα ή είναι μηδενικός. Αυτό που χρησιμοποιούμε για ασφάλεια είναι το μήκος της ουράς που υπάρχει σε κάθε στοιχείο, και δεν χρειάζεται να γνωρίζουμε αν έχουμε ή όχι μηδενικό δείκτη, αφού μας το λέει άμεσα το "μήκος", πχ αν το μήκος είναι 1 τότε δεν έχουμε "συνέχεια" μέσα από τον δείκτη για ομάδα.
Εδώ να επισημάνω ότι ο τελεστής -> δίνει ένα δείκτη σε μια ομάδα, αλλα'επειδή έχουμε δυο ειδών δείκτες, έναν που αντιστοιχεί σε επώνυμες ομάδες, και έναν άλλο που αντιστοιχεί σε ανώνυμες ομάδες, εδώ μας ενδιαφέρει το δεύτερο και για το λόγο αυτό μετά το -> η ομάδα που μας ενδιαφέρει να πάρουμε ένα δείκτη γίνεται ανώνυμη με παρενθέσεις () (ουσιαστικά αντίγραφο της επώνυμης, ως κλειστή ομάδα- και πάλι το κλειστή ομάδα είναι ορολογία της Μ2000 και δηλώνει την ανώνυμη ομάδα όπου τα μέλη της είναι κλειστά, και δεν μπορούν να χρησιμοποιηθούν). Μια κλειστή ομάδα χρησιμοποιείται αφού την ανοίξει ο διερμηνευτής, που σημαίνει να την "τοποθετήσει" σε θέαση, στο συγκεκριμένο σημείο του κώδικα που θέλουμε να διαβάσουμε ή να αλλάξουμε σε αυτήν κάτι.
Ως βελτίωση για το πρόγραμμα, μπαινει η άσκηση στο πώς να βγάλουμε εκτός τις αναδρομικές κλήσεις, στις μεθόδους SliceQueue και MergeQueue.
Στο τέλος ακολουθεί η αγγλική έκδοση των εντολών της Μ2000.



\\ Η γενική κλάση QueueClass
\\ δίνει ό,τι χρειάζεται για να προσθέτουμε στη κορυφή
\\ να πετάμε από την κορυφή
\\ να  μετακινούμε από ένα σημείο και κάτω της ουράς σε μια νέα ουρά
\\ να προσθέτουμε στο τέλος μιας ουράς μια άλλη ουρά
\\ σε κάθε περίπτωση η ουρά δίνει άμεσα το μέγεθός της
\\ Για κάθε στοιχείο της ουράς υπάρχει το NextClass ως δείκτης του επόμενου στοιχείου
\\ όπως και το length, ως το μήκος (ο αριθμός στοιχείων) από το σημείο αυτό και κάτω
\\ Η κλάση Queue δεν ασχολείται με το τι μεταφέρει το κάθε στοιχείο
\\ Όταν φτιάχνουμε ένα στοιχείο της φροντίζουμε να περνάμε μια άλλη κλάση που δίνει
\\ ένα αντικείμενο όπως το θέλουμε, με τα στοιχεία που θέλουμε (εδώ το λέμε items)
\\ αλλά και με ένα τμήμα ResetClass όπου το καλεί η QueueClass για να καθαρίσει τα στοιχεία,
\\ αυτού που φέρει ως απαίτηση όταν η ουρά είναι άδεια.
\\ Η ουρά ξεκινάει με ένα τουλάχιστον στοιχείο. Αλλά μπορεί να αδειάσει, είτε γιατί την κόψαμε από το πρώτο στοιχείο
\\ είτε γιατί την αδειάσαμε με συνεχόμενα την DropTop, είτε γιατί περάσαμε όλα τα στοιχεία της στην ουρά μιας άλλης ουράς!

Κλάση QueueClass {
      Ομάδα NextClass
      Ιδιότητα Length {Αξία}=1
      Τμήμα NewTop (nTop) {
                  nTop.NextClass->(Αυτό)
                  old=.[Length]+1
                  Αυτό=Ntop
                  .[Length]<=old
            }
      Τμήμα ClearAll {
            .[length]<=0
            Δες {.ResetClass}
            .NextClass->0&
      }
      Τμήμα MergeQueue (&Q1 ) {
                  Αν .[Length]=0 Τότε {
                        Αυτό=Q1
                  } Αλλιώς {
                        Q2->(Q1)
                        Κάλεσε Κενή .MoveDeep(.[Length], Q2)
                  }
                 Q1.ClearAll
      }
      Συνάρτηση MoveDeep (level, Q) {
                    Αν level>1 Τότε {
                         m->.Nextclass
                         .[length]+=m=>MoveDeep(level-1, Q)
                  } Αλλιώς {
                        .NextClass->Q
                         .[length]+=Q=>Length
                         =Q=>Length
                  }
            }
      Συνάρτηση SliceQueue (level) {
              Αν level>.[Length] Τότε {
                    Λάθος "Can't Slice"
            } Αλλιώς {
                  Z=.SliceQueueDeep(Level)
                  =Ομάδα(Z)
            }
      }
      Συνάρτηση SliceQueueDeep (level) {
              Αν level>1 Τότε {
                   m->.Nextclass
                   z=m=>SliceQueueDeep(level-1)
                   ->(z)
                   .[length]-=z=>length
            } Αλλιώς {
                  ->(Αυτό)
                  .NextClass->0&
                   .[length]<=0
                   Δες { .ResetClass }
            }
      }
      Τμήμα DropTop {
                 Αν .[Length]>0 Τότε {
                       old=.[Length]-1
                       Δες {
                              Αυτό=Ομάδα(.NextClass)
                        }
                        .[Length]<=old
                        Αν .[Length]==0 Τότε {
                             Δες { .ResetClass }
                        }
                  }  Αλλιώς Λάθος "Nothing to Drop"
            }
Κλάση:
     \\ οτιδήποτε μετά τξμ ετικέτα Κλάση:  δεν θα  υπάρχει στη τελική ομάδα
     \\ εδώ έχουμε το τμήμα που καλούμε κατά την κατασκευή της ομαας
      Τμήμα QueueClass (extend) {
            .NextClass->0&
            Αυτό=extend
      }
}

\\ Έχουμε άλλη μια κλάση που θα τη δώσουμε στην παραπάνω κλάση
\\Η Items δεν γνωρίζει που θα μπει, αλλά παρέχει μια ResetClass
\\ για να δημιουργεί  την κενή ομάδα τύπου items
Κλάση Items {
\\ X and Y are read only properties
      Ιδιότητα X {Αξία}=0
      Ιδιότητα Y {Αξία}=0
      Τμήμα ResetClass {
            .[X]<=0
            .[Y]<=0
      }     
Κλάση:
      Τμήμα Items (.[X], .[Y]) {}
}
\\ Τώρα φτιάχνουμε μια ομάδα  QueueClass μαζί με μια Items
\\ αυτός είναι ο απλός τρόπος να συχγωνεύσουμε δυο αντικείμενα
M=QueueClass(items(10, 20))
Τύπωσε M.X, M.Y ' 10, 20
\\ Τώρα αλλάζουμε το Μ βάζοντας στη κορυφή το νέο και από κάτω
\\ στην ουρά ότι υπήρχε
M.NewTop QueueClass(Items(15, 25))
Τύπωσε "New Item"
Τύπωσε M.X, M.Y ' 15, 25
\\ μπορούμε να δούμε τι υπάρχει ακριβώς στο προηγούμενο
\\ με χρήση του δείκτη NextClass
Τύπωσε M.NextClass=>X, M.NextClass=>Y ' 10, 20
\\ Βάζουμε και τρίτο Items, πάλι με επέκταση QueueClass
M.NewTop QueueClass(Items(50, 100))
Τύπωσε "New Item"
\\ Και πάλι κοιτάμε τα στοιχεία στη κορυφή και αμέσως μετά
Τύπωσε M.X, M.Y ' 50,100
Τύπωσε M.NextClass=>X, M.NextClass=>Y ' 15, 25
Τύπωσε "M.NextClass Length";M.NextClass=>Length
Τύπωσε "M length=";M.Length
\\ Τώρα θα φτιάξουμε ένα κομμάτι της Μ ως Ζ και θα ορίσουμε από ποιο σημείο θα κόψουμε
\\ μπορούμε από το 1 ή το 2 ή το 2
\\ εδώ κόβουμε από το 2 άρα το 1 θα μείναι στο Μ
Z=M.SliceQueue(2)
Τύπωσε "M Length="; M.Length, "Top Item X="; M.X
Τύπωσε "Z Length="; Z.Length, "Top Item X="; Z.X
\\ εδώ μπορούμε να επιλέξουμε αν θέλουμε να μεταφέρουμε τα στοιχεία του Μ
\\ στο τέλος του Ζ  και να αδειάσοιυμε εντελώς το Μ
Σημ 1 :
Z.MergeQueue &M
\\ ή να κάνουμε το ανάποδο, να επιλέξουμε  να μεταφέρουμε τα στοιχεία του Ζ
\\ στο Μ και να αδειάσουμε το Ζ
Σημ 2 : M.MergeQueue &Z
Τύπωσε "M Length="; M.Length, "Top Item X="; M.X
Τύπωσε "Z Length="; Z.Length, "Top Item X="; Z.X
\\ Ότι και να κάνουμε θα αδειάσουμε και το Μ και το Ζ
Δες {
      Τύπωσε "Drop Item M"
      Τύπωσε M.X, M.Y
      M.DropTop
      Τύπωσε "M length=";M.Length
      Κυκλικά
}
Δες {
      Τύπωσε "Drop Item Z"
      Τύπωσε Z.X, Z.Y
      Z.DropTop
      Τύπωσε "Z length=";Z.Length
      Κυκλικά
}


Εδώ όλα στα ελληνικά και οι μεταβλητές:


\\ Η γενική κλάση ΜιαΟυρά
\\ δίνει ό,τι χρειάζεται για να προσθέτουμε στη κορυφή
\\ να πετάμε από την κορυφή
\\ να  μετακινούμε από ένα σημείο και κάτω της ουράς σε μια νέα ουρά
\\ να προσθέτουμε στο τέλος μιας ουράς μια άλλη ουρά
\\ σε κάθε περίπτωση η ουρά δίνει άμεσα το μέγεθός της
\\ Για κάθε στοιχείο της ουράς υπάρχει το ΕπόμενηΟμάδα ως δείκτης του επόμενου στοιχείου
\\ όπως και το ΜήκοςΟυράς, ως το μήκος (ο αριθμός στοιχείων) από το σημείο αυτό και κάτω
\\ Η κλάση ΜιαΟυρά δεν ασχολείται με το τι μεταφέρει το κάθε στοιχείο
\\ Όταν φτιάχνουμε ένα στοιχείο της φροντίζουμε να περνάμε μια άλλη κλάση που δίνει
\\ ένα αντικείμενο όπως το θέλουμε, με τα στοιχεία που θέλουμε (εδώ το λέμε Περιεχόμενο)
\\ αλλά και με ένα τμήμα ΚαθάρισεΟμάδα όπου το καλεί η ΜιαΟυρά για να καθαρίσει τα στοιχεία,
\\ αυτού που φέρει ως απαίτηση όταν η ουρά είναι άδεια.
\\ Η ουρά ξεκινάει με ένα τουλάχιστον στοιχείο. Αλλά μπορεί να αδειάσει, είτε γιατί την κόψαμε από το πρώτο στοιχείο
\\ είτε γιατί την αδειάσαμε με συνεχόμενα την ΠέταΚορυφή, είτε γιατί περάσαμε όλα τα στοιχεία της στην ουρά μιας άλλης ουράς!

Κλάση ΜιαΟυρά {
      Ομάδα ΕπόμενηΟμάδα
      Ιδιότητα ΜήκοςΟυράς {Αξία}=1
      Τμήμα ΝέαΚορυφή (Κορυφή) {
                  Κορυφή.ΕπόμενηΟμάδα->(Αυτό)
                  παλιό=.[ΜήκοςΟυράς]+1
                  Αυτό=Κορυφή
                  .[ΜήκοςΟυράς]<=παλιό
            }
      Τμήμα ΚαθάρισεΌλα {
            .[ΜήκοςΟυράς]<=0
            Δες {.ΚαθάρισεΟμάδα}
            .ΕπόμενηΟμάδα->0&
      }
      Τμήμα ΈνωσεΟυρά (&κ1 ) {
                  Αν .[ΜήκοςΟυράς]=0 Τότε {
                        Αυτό=κ1
                  } Αλλιώς {
                        κ2->(κ1)
                        Κάλεσε Κενή .ΣτοΒάθος(.[ΜήκοςΟυράς], κ2)
                  }
                 κ1.ΚαθάρισεΌλα
      }
      Συνάρτηση ΣτοΒάθος (Βάθος, κ) {
                    Αν Βάθος>1 Τότε {
                         μ->.ΕπόμενηΟμάδα
                         .[ΜήκοςΟυράς]+=μ=>ΣτοΒάθος(Βάθος-1, κ)
                  } Αλλιώς {
                        .ΕπόμενηΟμάδα->κ
                         .[ΜήκοςΟυράς]+=κ=>ΜήκοςΟυράς
                         =κ=>ΜήκοςΟυράς
                  }
            }
      Συνάρτηση ΚόψεΟυρά (Βάθος) {
              Αν Βάθος>.[ΜήκοςΟυράς] Τότε {
                    Λάθος "Δεν μπορώ να κόψω"
            } Αλλιώς {
                  Ζ=.ΚόψεΟυράΒάθος(Βάθος)
                  =Ομάδα(Ζ)
            }
      }
      Συνάρτηση ΚόψεΟυράΒάθος (Βάθος) {
              Αν Βάθος>1 Τότε {
                   μ->.ΕπόμενηΟμάδα
                   ζ=μ=>ΚόψεΟυράΒάθος(Βάθος-1)
                   ->(ζ)
                   .[ΜήκοςΟυράς]-=ζ=>ΜήκοςΟυράς
            } Αλλιώς {
                  ->(Αυτό)
                  .ΕπόμενηΟμάδα->0&
                   .[ΜήκοςΟυράς]<=0
                   Δες { .ΚαθάρισεΟμάδα }
            }
      }
      Τμήμα ΠέταΚορυφή {
                 Αν .[ΜήκοςΟυράς]>0 Τότε {
                       παλιό=.[ΜήκοςΟυράς]-1
                       Δες {
                              Αυτό=Ομάδα(.ΕπόμενηΟμάδα)
                        }
                        .[ΜήκοςΟυράς]<=παλιό
                        Αν .[ΜήκοςΟυράς]==0 Τότε {
                             Δες { .ΚαθάρισεΟμάδα }
                        }
                  }  Αλλιώς Λάθος "Τίποτα για να πετάξω"
            }
Κλάση:
     \\ οτιδήποτε μετά την ετικέτα Κλάση:  δεν θα  υπάρχει στη τελική ομάδα
     \\ εδώ έχουμε το τμήμα που καλούμε κατά την κατασκευή της ομαας
      Τμήμα ΜιαΟυρά (επέκταση) {
            .ΕπόμενηΟμάδα->0&
            Αυτό=επέκταση
      }
}

\\ Έχουμε άλλη μια κλάση που θα τη δώσουμε στην παραπάνω κλάση
\\ ΟΙ κλάσεις είναι συναρτήσεις που επιστρέφουν Ομάδες.
\\Η Περιεχόμενο δεν γνωρίζει που θα μπει, αλλά παρέχει μια ΚαθάρισεΟμάδα
\\ για να δημιουργεί  την κενή ομάδα τύπου Περιεχόμενο
Κλάση Περιεχόμενο {
\\ οι Χ και Υ είναι ιδιότητες μόνο για ανάγνωση
\\ εσωτερικά γράφονται στις .[Χ] και .[Υ] που είναι ιδιωτικές στην ομάδα.
      Ιδιότητα Χ {Αξία}=0
      Ιδιότητα Υ {Αξία}=0
      Τμήμα ΚαθάρισεΟμάδα {
            .[Χ]<=0
            .[Υ]<=0
      }     
Κλάση:
      Τμήμα Περιεχόμενο (.[Χ], .[Υ]) {}
}
\\ Τώρα φτιάχνουμε μια ομάδα  ΜιαΟυρά μαζί με μια Περιεχόμενο
\\ αυτός είναι ο απλός τρόπος να συχγωνεύσουμε δυο αντικείμενα
Μ=ΜιαΟυρά(Περιεχόμενο(10, 20))
Τύπωσε Μ.Χ, Μ.Υ ' 10, 20
\\ Τώρα αλλάζουμε το Μ βάζοντας στη κορυφή το νέο και από κάτω
\\ στην ουρά ότι υπήρχε
Μ.ΝέαΚορυφή ΜιαΟυρά(Περιεχόμενο(15, 25))
Τύπωσε "Νέο Περιεχόμενο"
Τύπωσε Μ.Χ, Μ.Υ ' 15, 25
\\ μπορούμε να δούμε τι υπάρχει ακριβώς στο προηγούμενο
\\ με χρήση του δείκτη NextClass
Τύπωσε Μ.ΕπόμενηΟμάδα=>Χ, Μ.ΕπόμενηΟμάδα=>Υ ' 10, 20
\\ Βάζουμε και τρίτο Περιεχόμενο, πάλι με επέκταση ΜιαΟυρά
Μ.ΝέαΚορυφή ΜιαΟυρά(Περιεχόμενο(50, 100))
Τύπωσε "Νέο Περιεχόμενο"
\\ Και πάλι κοιτάμε τα στοιχεία στη κορυφή και αμέσως μετά
Τύπωσε Μ.Χ, Μ.Υ ' 50,100
Τύπωσε Μ.ΕπόμενηΟμάδα=>Χ, Μ.ΕπόμενηΟμάδα=>Υ ' 15, 25
Τύπωσε "Μ.ΕπόμενηΟμάδα ΜήκοςΟυράς";Μ.ΕπόμενηΟμάδα=>ΜήκοςΟυράς
Τύπωσε "Μ ΜήκοςΟυράς=";Μ.ΜήκοςΟυράς
\\ Τώρα θα φτιάξουμε ένα κομμάτι της Μ ως Ζ και θα ορίσουμε από ποιο σημείο θα κόψουμε
\\ μπορούμε από το 1 ή το 2 ή το 2
\\ εδώ κόβουμε από το 2 άρα το 1 θα μείναι στο Μ
Ζ=Μ.ΚόψεΟυρά(2)
Τύπωσε "Μ ΜήκοςΟυράς="; Μ.ΜήκοςΟυράς, "Περιεχόμενο Κορυφής Χ="; Μ.Χ
Τύπωσε "Ζ ΜήκοςΟυράς="; Ζ.ΜήκοςΟυράς, "Περιεχόμενο Κορυφής Χ="; Ζ.Χ
\\ εδώ μπορούμε να επιλέξουμε αν θέλουμε να μεταφέρουμε τα στοιχεία του Μ
\\ στο τέλος του Ζ  και να αδειάσοιυμε εντελώς το Μ
Σημ 1 :
Ζ.ΈνωσεΟυρά &Μ
\\ ή να κάνουμε το ανάποδο, να επιλέξουμε  να μεταφέρουμε τα στοιχεία του Ζ
\\ στο Μ και να αδειάσουμε το Ζ
Σημ 2 : Μ.ΈνωσεΟυρά &Ζ
Τύπωσε "Μ ΜήκοςΟυράς="; Μ.ΜήκοςΟυράς, "Περιεχόμενο Κορυφής Χ="; Μ.Χ
Τύπωσε "Ζ ΜήκοςΟυράς="; Ζ.ΜήκοςΟυράς, "Περιεχόμενο Κορυφής Χ="; Ζ.Χ
\\ Ότι και να κάνουμε θα αδειάσουμε και το Μ και το Ζ
Δες {
      Τύπωσε "Πέτα Στοιχείο στο Μ"
      Τύπωσε Μ.Χ, Μ.Υ
      Μ.ΠέταΚορυφή
      Τύπωσε "Μ ΜήκοςΟυράς=";Μ.ΜήκοςΟυράς
      Κυκλικά
}
Δες {
      Τύπωσε "Πέτα Στοιχείο στο Ζ"
      Τύπωσε Ζ.Χ, Ζ.Υ
      Ζ.ΠέταΚορυφή
      Τύπωσε "Ζ ΜήκοςΟυράς=";Ζ.ΜήκοςΟυράς
      Κυκλικά
}








Και η αγγλική έκδοση:

\\ this is a generic class for Queue
Class QueueClass {
      Group NextClass
      Property Length {value}=1
      Module NewTop (nTop) {
                  nTop.NextClass->(This)
                  old=.[Length]+1
                  This=Ntop
                  .[Length]<=old
            }
      Module ClearAll {
            .[length]<=0
            Try {.ResetClass}
            .NextClass->0&
      }
      Module MergeQueue (&Q1 ) {
                  if .[Length]=0 then {
                        This=Q1
                  } else {
                        Q2->(Q1)
                        call void .MoveDeep(.[Length], Q2)
                  }
                 Q1.ClearAll
      }
      Function MoveDeep (level, Q) {
                    if level>1 then {
                         m->.Nextclass
                         .[length]+=m=>MoveDeep(level-1, Q)
                  } else {
                        .NextClass->Q
                         .[length]+=Q=>Length
                         =Q=>Length
                  }
            }
      Function SliceQueue (level) {
              if level>.[Length] then {
                    Error "Can't Slice"
            } else {
                  Z=.SliceQueueDeep(Level)
                  =Group(Z)
            }
      }
      Function SliceQueueDeep (level) {
              if level>1 then {
                   m->.Nextclass
                   z=m=>SliceQueueDeep(level-1)
                   ->(z)
                   .[length]-=z=>length
            } else {
                  ->(this)
                  .NextClass->0&
                   .[length]<=0
                   Try { .ResetClass }
            }
      }
      Module DropTop {
                 If .[Length]>0 then {
                       old=.[Length]-1
                       Try {
                              This=Group(.NextClass)
                        }
                        .[Length]<=old
                        if .[Length]==0 then {
                             Try { .ResetClass }
                        }
                  }  Else Error "Nothing to Drop"
            }
Class:
     \\ anything after Class: are not  included to final list of group members
      Module QueueClass (extend) {
            .NextClass->0&
            This=extend
      }
}

\\ This is the items class which feed the QueueClass
\\ we have to use a ResetClass if we want to make an empty Items class
Class Items {
\\ X and Y are read only properties
      Property X {value}=0
      Property Y {value}=0
      Module ResetClass {
            .[X]<=0
            .[Y]<=0
      }     
Class:
      Module Items (.[X], .[Y]) {}
}
M=QueueClass(items(10, 20))
Print M.X, M.Y ' 10, 20
M.NewTop QueueClass(Items(15, 25))
Print "New Item"
Print M.X, M.Y ' 15, 25

Print M.NextClass=>X, M.NextClass=>Y ' 10, 20
M.NewTop QueueClass(Items(50, 100))
Print "New Item"
Print M.X, M.Y ' 50,100
Print M.NextClass=>X, M.NextClass=>Y ' 15, 25
Print "M.NextClass Length";M.NextClass=>Length
Print "M length=";M.Length

Def CopyPointer(X)=Group(X)
\\ WE CAN SLICE THE QUEUE TO 1 OR 2 OR 3 ITEM
Z=M.SliceQueue(2)
Print "M Length="; M.Length, "Top Item X="; M.X
Print "Z Length="; Z.Length, "Top Item X="; Z.X
Rem 1 :
Z.MergeQueue &M
Rem 2 : M.MergeQueue &Z
Print "M Length="; M.Length, "Top Item X="; M.X
Print "Z Length="; Z.Length, "Top Item X="; Z.X
Try {
      Print "Drop Item M"
      Print M.X, M.Y
      M.DropTop
      Print "M length=";M.Length
      loop
}
Try {
      Print "Drop Item Z"
      Print Z.X, Z.Y
      Z.DropTop
      Print "Z length=";Z.Length
      loop
}

Χρήση Υπερκλάσης και Γεγονότων για παραγωγή ομάδων με σειριακό αριθμό!

Και αυτό το παράδειγμα έχει γραφτεί στο νέο μικρό εγχειρίδιο που ετοιμάζω.
Η κλάση ΝέαΟμαδα δημιουργεί μια κλάση που κληρονομεί την υπερκλάση ένα. Στη Μ2000 μια ομάδα μπορεί να έχει μια υπερκλάση, και μια υπερκλάση δεν μπορεί να έχει άλλη. Μπορούμε όμως να δημιουργήσουμε ομάδες από άλλες ομάδες, έτσι κατά μια έννοια η κληρονομικότητα γίνεται λόγω "Συγχώνευσης" ομάδων. Η διαφορά με την υπερκλάση είναι ότι αφήνει ένα σύνδεσμο σε αυτή,  ένα δείκτη, και η Για Υπερκλάση {} καλεί στοιχεία της υπερκλάσης, και έτσι όσες ομάδες έχουν συνδεθεί με την υπερκλάση έχουν πρόσβαση σε κοινές ιδιότητες. Μια υπερκλάση μπορεί να έχει μοανδικά στοιχεία που δεν τα δίνει στις υποκλάσεος αλλά αυτές μπορούν να τα προσεγγίσουν. Εδώ η μεταβλητή "αρχικός" είναι μοναδική και κρατάει τον επόμενο αριθμό σειράς.
Καλώντας την κλάση δέκα φορές με πέρασμα με τιμή της Δύο, ο δείκτης της υπερκλάσης αντιγράφεται, όπως επίσης και η λίστα συνδεδεμένων γεγονότων. Έτσι δημουργούμε στο τελικό προιόν της συνάρτησης κλάσης, μια ομάδα με υπερκλάση και με λίστα γεγονότων (εδώ έχουμε ένα μόνο γεγονός το "αριθμός_σειράς".
Από το πίνακα Α(10) με δέκα στοιχεία από 0 έως 9, δημιουργούμε δυο άλλες ομάδες ως αποτέλεσμα της συνάρτησης Παραγωγή(). Αυτή η συνάρτηση αρχικά σώνει τον αριθμό σειράς, μετά παράγει έναν άλλο και τον γράφει έτσι ώστε να βγει ένα αντίγραφο που θα επιστραφεί από τη συνάρτηση με τον νέο αριθμό σειράς και μετά επαναφέρουμε τον παλιό αριθμό σειράς. Κάθε φορά χειριζόμαστε την ιδιωτική μεταβλητή, πίσω από την ιδιότητα ΣειριακόςΑριθμός, η οποία είναι μόνο για ανάγνωση (αλλά παίρνει την τιμή από την ιδιωτική [ΣειριακόςΑριθμός].
Στο τέλος από το τελευταίο παραγώμενο κάνουμε επίσης μια παραγωγή, το ΜΜ3. Και αυτό θα πάρει το κανονικό αριθμό σειράς (εδώ 13). Σε κάθε περίπτωση, το γεγονός της παραγωγής του επόμενου αριθμού σειράς θα εξυπηρετηθεί και θα φανεί σαν ενημέρωση στην κονσόλα με την Τύπωσε.

Η συναρτηση Δύο_αριθμός_σειράς είναι μια "ψεύτικη" συνάρτηση. Όταν κληθεί από το σύστημα των γεγονότων, θα αλλαχθεί το όνομά της με το όνομα του τμήματος όπου βρίσκεται (πχ αν το πρόγραμμα βρίσκεται στο Α θα μπει ως όνομα το Α) έτσι κάθε μεταβλητή του Α θα είναι θεατή στη κλήση αυτή.
Με τον ίδιο τρόπο γίνονται και οι κλήσεις γεγονότων στο σύστημα των παραθύρων της Μ2000.



\\ Θέλουμε η υπερκλάση να κρατάει τον μοναδικό επόμενο αριθμό σειράς
Υπερκλάση Ένα {
      Γεγονός "αριθμός_σειράς"
      Μοναδικό:
            αρχικός=1&
      Δημοσιο:
            Συνάρτηση Επόμενος {
                  Για Υπερκλάση {
                        =.αρχικός
                        Κάλεσε Γεγονός "αριθμός_σειράς", .αρχικός
                        .αρχικός++
                  }
            }      
}
\\ Θέλουμε μια κλάση να παίρνει την υπερκλάση και να δημιουργεί
\\ μια νέα ομάδα, με κατάλληλο αριθμό σειράς
\\ και με δυνατότητα παραγωγής αντιγράφου με τον επόμενο αριθμό σειράς
Κλάση ΝεαΟμάδα {
      Ιδιότητα ΣειριακόςΑριθμός { Αξία }=0
      Συνάρτηση Παραγωγή {
            Παλιός=.[ΣειριακόςΑριθμός]
            .[ΣειριακόςΑριθμός]<=.Επόμενος()
            =Αυτό
            .[ΣειριακόςΑριθμός]<=Παλιός
      }
Κλάση:
      Τμήμα ΝεαΟμάδα (Ομαδα1) {
              Αυτό=Ομάδα1
             .[ΣειριακόςΑριθμός]<=Ομάδα1.Επόμενος()
      }
}
\\ Παράλληλα θέλουμε όταν παράγεται ένας αριθμός σειράς να φαίνεται
\\ μέσα από την κλήση ενός γεγονότος.
\\ Η υπερκλάση δεν μπορεί να συνδεθεί άμεσα με εξυπηρετητές γεγονότων
\\ μπορεί όμως μια ομάδα να πάρει την υπερκλάση και να συνδεθεί με εξυπηρέτηση γεγονότων
Ομάδα ΜεΓεγονότα Δύο=Ένα
Συνάρτηση Δύο_αριθμός_σειράς {
      Τύπωσε "Νέος αριθμός σειράς", Αριθμός
}
\\ Ο τελεστής << κάνει την Κλάση ΝέαΟμάδα() να εκτελείται για κάθε στοιχείο του Α()
\\ Έτσι παράγεται για κάθε στοιχείο ένας νέος σειριακός αριθμός και ένα γεγονός μας το λέει!
Πίνακας Α(10)<<ΝεαΟμαδα(Δύο)
\\ Μπορούμε να διαβάσουμε το σειριακό αριθμό με τη χρήση της ιδιότητας για ανάγνωση μόνο
Για ι=0 έως 9 {
      Τύπωσε Α(ι).ΣειριακόςΑριθμός
}
\\ Κάθε στοιχείο μπορεί να παράγει ένα ίδιο με τον επόμενο αριθμό σειράς!
\\ τώρα παράγουμε ένα αντίγραφο με νέο αριθμό σειράς το 11
ΜΜ=Α(3).Παραγωγή()
Τύπωσε ΜΜ.ΣειριακόςΑριθμός ' δίνει 11
ΜΜ2=Α(6).Παραγωγή()
Τύπωσε ΜΜ2.ΣειριακόςΑριθμός ' δίνει 12
\\ Τώρα θα παράγουμε από το ΜΜ2 που έχει παραχθεί από το Α(6)
ΜΜ3=ΜΜ.Παραγωγή()
Τύπωσε ΜΜ3.ΣειριακόςΑριθμός ' δίνει 13