Πέμπτη 3 Μαρτίου 2016

Αναθεώρηση 177 (Σημαντική)

Σε αυτήν την αναθεώρηση διόρθωσα σφάλματα με το κώδικα για τα Γεγονότα και τροποποίησα το κώδικα για να είναι πιο γρήγορος στις κλήσεις, και επίσης να δέχεται κλήση γεγονότος μέσα σε ρουτίνα που κλήθηκε από κλήση γεγονότος ( αυτό λέγεται φωλιασμένη κλήση γεγονότος ή  nested raise event).

Παρακάτω είναι δυο παραδείγματα που έχουν την ίδια έξοδο, αλλά στο παράδειγμα 1 έχουμε το γεγονός Inform ως γενικό και το καλούμε μέσα στην OnSpaceHandler() που καλείται από το OnSpaceBar γεγονός (δυο συνεχόμενα δηλαδή, το δεύτερο είναι γενικό)
Στο άλλο παράδειγμα περνάμε με αναφορά το τοπικό γεγονός και το καλούμε πάλι μέσα από την OnSpaceHandler(). Η διαφορά είναι ότι έχουμε μια παράμετρο ακόμα, την αναφορά στο τοπικό γεγονός.
Και στα δύο παραδείγματα, όταν καλούν τα αντικείμενα τύπου γεγονότα τις συναρτήσεις διεκπεραίωσης (ή χειρισμού), τότε αυτές τρέχουν μέσα στο αντικείμενό τους Info και ενημερώνουν τις μεταβλητές του, οι οποίες είναι ιδιωτικές. Δηλαδή δεν μπορούν να αλλαχτούν παρά μόνο από συναρτήσεις/τμήματα που θα καλέσουμε (άρα δημόσια).

Παράδειγμα 1


Event OnSpaceBar {
      Read t, a$, b
}
Group Info {
Private:
      counter, complete
Public:
      Event WorkEnd { }
      Function Print {
            read a$
            print a$
            .counter++
      }
      Function WorkEnd {
            .complete++
      }
      Module TotalPrint {
            Print "Total Lines:", .counter
            Print "Complete Works:", .complete
      }
}
Global Event Inform {
      read a$
}
Event Inform New Info.Print()
Event Info.WorkEnd New Info.WorkEnd()


Function OnSpaceHandler {
      Read thr, t$, kk
      Thread thr execute data t$, kk
      call event Inform "ok....................."
}
Event OnSpaceBar New OnSpaceHandler()


Thread {
      Static a$, payload, t
      If t=0 Then {
            call event Inform "no job......yet"
            If Not Empty Then {
                  Event OnSpaceBar Hold
                  Read a$, payload
                  t=payload
            }
       } Else {
            call event Inform format$("working {0:2}%",(payload-t)/payload*100)
             t--
             If t<1 Then Event OnSpaceBar Release : Call Event Info.WorkEnd
       }      
} As theThread Interval 50
Main.Task 50 {
      select case inkey$
      case ""
            call event Inform "wait...."
      case " "
            Call Event OnSpaceBar, theThread, "hello", 30
      else
            break
      end select
}
Threads Erase
Info.TotalPrint



Παράδειγμα 2


Event OnSpaceBar {
      Read &Ev, t, a$, b
}
Event Inform {
      read a$
}
Group Info {
Private:
      counter, complete
Public:
      Event WorkEnd { }
      Function Print {
            read a$
            print a$
            .counter++
      }
      Function WorkEnd {
            .complete++
      }
      Module TotalPrint {
            Print "Total Lines:", .counter
            Print "Complete Works:", .complete
      }
}
Event Inform New Info.Print()
Event Info.WorkEnd New Info.WorkEnd()


Function OnSpaceHandler {
      Read &inf, thr, t$, kk
      Thread thr execute data t$, kk
      call event Inf "ok....................."
}
Event OnSpaceBar New OnSpaceHandler()


Thread {
      Static a$, payload, t
      If t=0 Then {
            call event Inform "no job......yet"
            If Not Empty Then {
                  Event OnSpaceBar Hold
                  Read a$, payload
                  t=payload
            }
       } Else {
            call event Inform format$("working {0:2}%",(payload-t)/payload*100)
             t--
             If t<1 Then Event OnSpaceBar Release : Call Event Info.WorkEnd
       }      
} As theThread Interval 50
Main.Task 50 {
      select case inkey$
      case ""
            call event Inform "wait...."
      case " "
            Call Event OnSpaceBar, &inform, theThread, "hello", 30
      else
            break
      end select
}
Threads Erase
Info.TotalPrint



Και εδώ με ελληνικές εντολές το παράδειγμα 2, έχω διατηρήσει τα αναγνωριστικά μεταβλητώ/συναρτήσεων κ.ο.κ με τα αγγλικά

Γεγονός OnSpaceBar {
      Διάβασε &Ev, t, a$, b
}
Γεγονός Inform {
      Διάβασε a$
}
Ομάδα Info {
Ιδιωτικό:
      counter, complete
Δημόσιο:
      Γεγονός WorkEnd { }
      Συνάρτηση Print {
            Διάβασε a$
            Τύπωσε a$
            .counter++
      }
      Συνάρτηση WorkEnd {
            .complete++
      }
      Τμήμα TotalPrint {
            Τύπωσε "Total Lines:", .counter
            Τύπωσε "Complete Works:", .complete
      }
}
Γεγονός Inform Νέο Info.Print()
Γεγονός Info.WorkEnd Νέο Info.WorkEnd()


Συνάρτηση OnSpaceHandler {
      Διάβασε &inf, thr, t$, kk
      Νήμα thr Εκτέλεση Σειρά t$, kk
      Κάλεσε Γεγονός Inf "ok....................."
}
Γεγονός OnSpaceBar Νέο OnSpaceHandler()


Νήμα {
      Στατικές a$, payload, t
      Αν t=0 Τότε {
            Κάλεσε Γεγονός Inform "no job......yet"
            Αν Όχι Κενό Τότε {
                  Γεγονός OnSpaceBar Κράτησε
                  Διάβασε a$, payload
                  t=payload
            }
       } Αλλιώς {
            Κάλεσε Γεγονός Inform Μορφή$("working {0:2}%",(payload-t)/payload*100)
             t--
             Αν t<1 Τότε Γεγονός OnSpaceBar Άφησε : Κάλεσε Γεγονός Info.WorkEnd
       }      
} Ως theThread Κάθε 50
Κύριο.Έργο 50 {
      Επίλεξε Με inkey$
      Με ""
            Κάλεσε Γεγονός Inform "wait...."
      Με " "
            Κάλεσε Γεγονός OnSpaceBar, &inform, theThread, "hello", 30
      Αλλιώς
            Διέκοψε
      Τέλος Επιλογής
}
Νήματα Σβήσε
Info.TotalPrint




Τετάρτη 2 Μαρτίου 2016

Νήματα και Γεγονότα μαζί!

Θέλουν ακόμα δουλειά τα Γεγονότα, για να δουλεύουν σε όλες τις περιπτώσεις. Να ένα πρόγραμμα με εντολές στα αγγλικά, με νήματα και με γγονότα.



Event OnSpaceBar {
      Read t, a$, b
}
Class Inform1 {
Private:
      total, complete
Public:
      Event AddOne { }
      Event Print {
            Read what$
      }
      Function Any {
                  Read a$
                      .total++
                     Print a$
            }    
      Function AddNow {
            .complete++
      }
      Module Init {
           Event .Print new .Any()
           Event .AddOne new .AddNow()
      }
      Module PrintHelp {
            Call Event .Print
      }
      Module AddHelp {
            Call Event .AddOne
      }
      Module TotalPrint {
            Print "Total Lines:", .total
            Print "Complete Works:", .complete
      }
}
Global Group Inform=Inform1()
\\ fix references when we have an instance
Inform.init
Function OnSpaceHandler {
      Read thr, t$, kk
      Thread thr execute data t$, kk
      \\ we need the global here
      Inform.PrintHelp "ok"
}
Event OnSpaceBar New OnSpaceHandler()


Thread {
      Static a$, payload, t
      If t=0 Then {
            Inform.PrintHelp "no job......yet"
            If Not Empty Then {
                  Event OnSpaceBar Hold
                  Read a$, payload
                  t=payload
            }
       } Else {
             Inform.PrintHelp format$("working {0:2}%",(payload-t)/payload*100)
             t--
             If t<1 Then Event OnSpaceBar Release : Inform.AddHelp
       }      
} As theThread Interval 50

Main.Task 50 {
      select case inkey$
      case ""
            Inform.PrintHelp "wait...."
      case " "
            Call Event OnSpaceBar, theThread, "hello", 30
      else
            break
      end select
}
Threads Erase
Inform.TotalPrint

Αναθεώρηση 176 (Σημαντική)

Υπήρχε ένα λάθος που έγινε από αβλεψία στην αναθεώρηση 175 και μετά από έλεγχο (εκτέλεση όλων των προγραμμάτων του εγχειριδίου) βρέθηκε και διορθώθηκε!
ανέβηκε και στο Git

Παραδείγματα με Γεγονότα και Αντικείμενα (ανανέωση)

Ακόμα ανιχνεύω τις δυνατότητες των Γεγονότων όπως τα έφτιαξα στη Μ2000.

Σε αυτό το παράδειγμα δημιουργούμε ένα αντικείμενο Άλφα και ένα Βήτα. Μετά δημιουργούμε το Δέλτα και Έψιλον από το Βήτα, και μετά τα τρία τελευταία αναβαθμίζονται κατά τάξη Άλφα. Δηλαδή δεν μπαίνει η ομάδα άλφα στο καθένα αλλά δημιουργείται η δομή της μέσα στα τρία αντικείμενα, και αν βρεθούν όμοια πεδία τότε έχουμε αλλαγή τιμής, και για το λόγο αυτό θα χρησιμοποιούμε την λέξη Συγχώνευση, και την διαδικασία αυτή ως Συγχώνευση του Άλφα στο Βήτα, στο Δέλτα και στο Έψιλον.

Αν κάνουμε πρώτα συγχώνευση του Άλφα στο Βήτα και μετά κάνουμε δημιουργίες του Δέλτα και Έψιλον, τότε το πρόγραμμα θα τρέξει, με την μόνη διαφορά πως η όλαμαζί που αλλάζει τιμή θα είναι στο Έψιλον! Πάντως μέχρι να δω γιατί γίνεται αυτό...ας το αποφεύγουμε, αν και το πρόγραμμα βγαίνει, αφού το όλαμαζί το ζητάμε μέσω γεγονότος και μας επιστρέφει σωστά σε οποιοδήποτε από τα Βήτα, Δέλτα, Έψιλον με την Όλαμαζί(&Αλφα), όπου το &Αλφα σημαίνει πέρασμα με αναφορά του γεγονότος στη συνάρτηση Όλαμαζί() που έχουν και τα τρία αντικείμενα Βήτα, Δέλτα και Έψιλον.

Στην Ομάδα άλφα έχω το όλαμαζι ιδιωτικό. Μπορώ να τη διαβάσω με την δημόσια συνάρτηση ΤιΈχω(). Έχω φτιάξει δυο γεγονότα, δημόσια, το Κ και το Μ. Το Κ δηλώνει ότι θα διαβάζει το Μ και το Ποιος$. Αυτό θα το κάνει και για τις δικές μας συναρτήσεις που θα του δώσουμε, αλλά εκεί θα βάλουμε τη δική μας διάβασε όπως θέλουμε. Το Κ όμως έχει μια δική του Συνάρτηση, όπως και το Μ, χωρίς όνομα! Σε αυτές αντιγράφεται  η Διάβασε που περιέχεται στο κάθε Γεγονός. Όμως και οι δύο συναρτήσεις, αν και δεν έχουν όνομα, θα πάρουν πρόσκαιρα το Α(). Αυτές οι συναρτήσεις δεν μπορούν να αφαιρεθούν από την κλήση γεγονότος.(το raise event εδώ λέγεται Κάλεσε Γεγονός).
Η λειτουργία του Γεγονότος απαιτεί να έχουν γραφτεί σε αυτό συναρτήσεις (όχι αλφαριθμητικές ή ακεραίων), που δεν επιστρέφουν τιμή. Όταν καλέσουμε το γεγονός με κάποιες παραμέτρους τότε θα κληθεί κάθε γραμμένη συνάρτηση με τις ίδιες παραμέτρους.(αυτό λέγεται multicast, εξαγωγή μηνύματος/τιμών προς πολλούς παραλήπτες).

Γράφουμε νέες συναρτήσεις με την Γεγονός όνομα_γεγονότος Νέο συναρτησηΑ()  [,συνάρτησηΟτιδήποτε()]. Μπορούμε να γράψουμε δυο ή περισσότερες φορές μια συνάρτηση. Μπορούμε να αφαιρέσουμε μια συνάρτηση (αν την έχουμε γράψει δυο φορές θα αφαιρεθεί μία), με την εντολή  Γεγονός όνομα_γεγονότος Πέτα συναρτησηΑ()  [,συνάρτησηΟτιδήποτε()].
Μπορούμε να καθαρίσουμε το γεγονός, και ταυτόχρονα το απενεργοποιούμε. Αυτό σημαίνει ότι αν κληθεί δεν θα απαντήσει, και θα σβήσει τα δεδομένα που του δίνουμε.
Η πρώτη καθαρίζει και κάνει κράτηση, η επόμενη το αφήνει ελεύθερο, και η τελευταία το κρατάει (έτσι οι Κάλεσε Γεγονός δεν ανταποκρίνονται)
Γεγονός Άλφα Καθαρό


Γεγονός Άλφα Άφησε


Γεγονός Άλφα Κράτησε

Η εντολή Κάλεσε Γεγονός παίρνει τα δεδομένα ως έχουν στο σωρό  (έχουν μπει πριν καλέσουμε το γεγονός) ή κατά τη κλήση, αλλά όπως και να έχει μετά δεν θα υπάρχουν ακόμα και αν δεν έχει τίποτα γραμμένο για να εκτελεστεί με την Κάλεσε Γεγονός (Δείτε το δεύτερο παράδειγμα παρακάτω)

Ομάδα Άλφα {
Ιδιωτικό:
      όλαμαζί=100
Δημόσιο:
      Γεγονός Κ {
            Διάβασε Μ, Ποιός$
            Συνάρτηση {
                  Τύπωσε Ποιός$, Μ, .όλαμαζί
                  .ολαμαζί++
            }
      }
      Γεγονός Πάρε_Όλαμαζί {
            Διάβασε
            Συνάρτηση {
                Μ= .ολαμαζί
            }
       }
      Συνάρτηση ΤιΈχω {
            =.Όλαμαζί
      }
}
Ομάδα Βήτα {
      χ=0, ψ=100, ονομα$
      Συνάρτηση Για_Κ {
            Διάβασε α, β$
            ++
            Τύπωσε α, β$, , "η δική μου "+.ονομα$
      }
      Συνάρτηση Όλαμαζί {
            Διάβασε &ποιο
            τοπική κ
            Κάλεσε Γεγονός Ποιο.Πάρε_Όλαμαζί,
            =κ
      }
}
Βήτα= Άλφα
\\ δημιουργία αντικειμένου με αντιγραφή
Στη Δέλτα=Βήτα
\\ δημιουργία αντικειμένου μέσω σωρού
Βάλε Βήτα
Διάβασε Έψιλον
Βήτα.Όνομα$="Βήτα"
Δέλτα.Όνομα$="Δέλτα"
// όταν δημιουργείται η Έψιλον από σωρό ειναι σαν γενική
// Το βλέπουμε με το Λίστα αυτό. Αν δεν βάλουμε το <= θα φτιαχτεί μια τοπική, που θα σκιάζει αυτή της Έψιλον, αλλά μόνο σε αυτό το τμήμα. Έτσι στην ανάγνωση της .όνομα$, στη συνάρτηση Για_Κ του Έψιλον θα βγαίνει η πραγματική Όνομα$ που θα είναι κενή.
Έψιλον.Όνομα$<="Έψιλον"
\\ Προσθέτω δυο χειριστές γεγονότων
\\ (παίρνει όσους θέλουμε, και σε άλλη γραμμή)
Γεγονός Άλφα.Κ νέο Βήτα.Για_Κ(), Δέλτα.Για_Κ(), Εψιλον.Για_Κ()
Τύπωσε Βήτα.Όλαμαζί(&Αλφα), Βήτα.ΤιΈχω(), "Βητα"
Τύπωσε Δέλτα.Όλαμαζί(&Αλφα), Δέλτα.ΤιΈχω(), "Δέλτα"
Τύπωσε Έψιλον.Όλαμαζί(&Αλφα), Έψιλον.ΤιΈχω(), "Έψιλον"
//Βήτα.Κ=Άλφα.Κ
\\ Διάλεξε περίπτωση 1 ή 2
Περίπτωση=2
\\ και οι δύο περιπτώσεις έχουν το ίδιο αποτέλεσμα!
Αν Περίπτωση=1 Τότε {
\\ Καλώ το γεγονός από την Άλφα
      Για Άλφα {
            Κάλεσε Γεγονός , 200, "οκ1"
            Κάλεσε Γεγονός , 300, "οκ2"
            Κάλεσε Γεγονός , 400, "οκ3"
      }
} Αλλιώς {
\\ Καλώ το γεγονός από τη Βήτα
      Για Βήτα {
            Κάλεσε Γεγονός , 200, "οκ1"
            Κάλεσε Γεγονός , 300, "οκ2"
            Κάλεσε Γεγονός , 400, "οκ3"
      }
}
Τύπωσε "Βήτα.χ, Δέλτα.χ, Έψιλον.χ"
Τύπωσε Βήτα.χ, Δέλτα.χ, Έψιλον.χ
Τύπωσε Βήτα.Όλαμαζί(&Αλφα), Βήτα.ΤιΈχω(), "Βητα"
Τύπωσε Δέλτα.Όλαμαζί(&Αλφα), Δέλτα.ΤιΈχω(), "Δέλτα"
Τύπωσε Έψιλον.Όλαμαζί(&Αλφα), Έψιλον.ΤιΈχω(), "Έψιλον"
Τύπωσε Άλφα.ΤιΈχω()


1. Παλαιότερα (πριν την 10η έκδοση) τα γεγονότα στα αντικείμενα δεν αντιγράφονταν με νέο δείκτη, αλλά αυτό έχει αλλάξει, και στη συγχώνευση ο δείκτης είναι διαφορετικός, δηλαδή τα Βήτα, Δέλτα, Έψιλον έχουν διαφορετικό αντικείμενο γεγονός. Μπορούμε όμως να το αλλάξουμε αυτό μετά. Όπως στο πρόγραμμα που βάλαμε σε μια επιπλέον γραμμή το Βήτα.Κ=Άλφα.Κ
2. Όταν διαβάζουμε ένα αντικείμενο από τον σωρό όπως στην Έψιλον, ο διερμηνευτής δίνει γενικό όνομα στο Έψιλον, με συνέπεια για να αλλάξουμε τιμή στο ονομα$ να χρειάζεται το <= όπως στις γενικές. Ο λόγος που γίνεται αυτό είναι για να μην αυξάνονται τα μήκη των ονομάτων εσωτερικά όταν δίνουμε ένα αντικείμενο σαν παράμετρο σε κλήση σε μια μέθοδο αντικειμένου.


Άλλο παράδειγμα! Εδώ φαίνεται ότι οι συναρτήσεις κρατούνται στο γεγονός, όχι σαν απλές αναφορές. Μετά το πέρας του τμήματος Εσωτερικό καλούμε το γεγονός και εκτελείται η συνάρτηση εντός του τμήματος, ενώ αυτό έχει τερματίσει και έχει διαγράψει την συνάρτηση. Έχουμε δηλαδή κάνει στην προσθήκη της συνάρτησης στο γεγονός προσθήκη ανώνυμης συνάρτησης! Το όνομα το χρησιμοποιεί μόνο για να την πετάξουμε από τη λίστα του αντικειμένου Γεγονός!
Δώστε Φόρμα 80,40 για να φανούν όλες οι γραμμές (η Φόρμα φτιάχνει το μέγεθος των γραμμάτων για να δείχνει επακριβώς 80 χαρακτήρες Χ 40 γραμμές σε οποιοδήποτε οθόνη, για μη αναλογικά τυπωμένους χαρακτήρες, αλλά μπορούμε να τυπώσουμε ότι θέλουμε και γραφικά, ακόμα και εικόνες)

\\ μπορώ να φτιάχνω και γενικά γεγονότα!
Γενικό ΜιαΦορά = Αληθής
Γενικό Γεγονός Α {
      Διάβασε Μ
}
Συνάρτηση Γενική ΚάνεΚάτι {
            Διάβασε Χ
            Τύπωσε Χ
      }
Τμήμα Εσωτερικό {
      Άδειασε \\ αδειάζω το σωρό
      Βάλε 10 \\ βάζω στην κορυφή το 10
      Τύπωσε "δεν θα κάνει τίποτα"
      Κάλεσε Γεγονός Α
      Σωρός
      Τύπωσε "Αλλά θα πετάξει ένα στοιχείο από το σωρό"
      Συνάρτηση ΚάνεΚάτιΑκόμα {
            Διάβασε Χ
            Τύπωσε Χ**2
      }
      \\ βάζω ένα γενικό και ένα τοπικό
   
      Αν ΜιαΦορά τότε {
            Γεγονός Α Νέο ΚάνεΚάτι(), ΚάνεΚάτιΑκόμα()
            ΜιαΦορά <= Ψευδής \\ οι γενικές θέλουν "<=" αλλιώς με "=" φτιάχνουμε τοπική
      } Αλλιώς {
            Δες Εντάξει {
                  Γεγονός Α Πέτα ΚάνεΚάτιΑκόμα()
            }
            Αν όχι Εντάξει τότε Τύπωσε "Δεν είναι γραμμένη η ΚάνεΚάτιΑκόμα()"
      }
      Τύπωσε "τώρα βάζω πάλι κάτι"
      Βάλε 100
      Κάλεσε Γεγονός Α
      Κάλεσε Γεγονός Α 200
      Κάλεσε Γεγονός Α, 300 \\ αν θέλω βάζω και κόμμα
   
}
Τύπωσε "Καλούμε το Εσωτερικό τμήμα"
Εσωτερικό
\\ Στην έξοδο (τερματισμό) του τμήματος Εσωτερικό ...
\\ ...έχει σβηστεί η τοπική συνάρτηση ΚάνεΚάτιΑκόμα
\\ όμως στο γεγονός είναι γραμμένη και τρέχει σαν ...
\\ Εσωτερικό.ΚάνεΚάτιΑκόμα()
\\ αλλά ουσιαστικά τρέχει μια Α()
\\ Στα γεγονότα δεν σώνουμε αναφορές στις συναρτήσεις
\\ αλλά αντίγραφα των συναρτήσεων και στοιχεία περιβάλλοντος!
Τύπωσε "Καλούμε το Γεγονός Α αφού τερμάτισε το Εσωτερικό τμήμα"
Κάλεσε Γεγονός Α 500
\\ Καλούμε το τμήμα Εσωτερικό πάλι, αλλά δεν θέλουμε..
\\.. να αυξήσουμε τις γραμμένες συναρτήσεις στο Γεγονός
\\.. να γιατί έχουμε βάλει μια γενική ΜιαΦορά για να κρατάμε λογαριασμό
Τύπωσε "Καλούμε πάλι το Εσωτερικό τμήμα"
Εσωτερικό
Τύπωσε "Καλούμε πάλι το Εσωτερικό τμήμα"
Εσωτερικό



Αναθεώρηση 175 Επέκταση του Αντικειμένου Γεγονός

Έκανα μεγαλύτερη ενσωμάτωση του αντικειμένου στη γλώσσα. Αρκετές διορθώσεις (τα παραδείγματα που έχουν αναφερθεί τρέχουν κανονικά, αλλά τρέχουν και επιπρόσθετα).
Τα προβλήματα ξεπεράστηκαν και τώρα μπορούμε να δώσουμε την κλάση Άλφα σε πίνακα και το αντικείμενο Γεγονός του κάθε στοιχείου του πίνακα τρέχει το δικό του πρόγραμμα (στη ανώνυμη συνάρτηση) και βλέπει τις μεταβλητές του στοιχείου. Υπάρχουν περιθώρια βελτίωσης, σε άλλη αναθεώρηση να προσθέσω τις Μ2000 φόρμες.  Δείτε κάτι άλλο, όταν η κλειστή ομάδα ανοίγει με τη Για, αντιγράφεται πρόσκαιρα σε μια κανονική ομάδα. Στην αντιγραφή παίρνει ένα όνομα, και αυτό το όνομα μπαίνει στις συνδρομές (εδώ έχουμε μόνο μία την ανώνυμη συνάρτηση). Προφανώς αν θέλουμε να δουλέψουμε συνεχώς με Γεγονότα, θα ήταν καλό να δουλεύαμε με ανοικτό/με όνομα αντικείμενο, μια ομάδα και όχι ένα στοιχείο πίνακα με μια ομάδα (κλειστό/ανώνυμο αντικείμενο).
Στη Μ2000 οι κλάσεις είναι συναρτήσεις που δημιουργούν ένα αντικείμενο, το κλείνουν, και το επιστρέφουν σαν αποτέλεσμα. Το Α=Άλφα() κάνει το Α ομάδα, ένα αντικείμενο με λίστα με διάφορα, και όλα αυτά χωριστά.  Π.χ. το Α.μετρητής θα είναι μια κανονική μεταβλητή. Η ομάδα το Α, όταν χρησιμοποιηθεί χωρίς ιδιαίτερο στοιχείο, πχ. όψι Α.βββ$, μπορεί να βγάλει αντίγραφο, ή να περάσει με  αναφορά σε κάποιο άλλο πρόγραμμα. Δεν μπορεί να σβήσει όμως. Σε αντίθεση τα κλειστά/ανώνυμα αντικείμενα (ομάδες) μπορούν να σβήσουν όσο είναι κλειστά.


Κλάση Αλφα {
      μετρητής
      βββ$="οκ12212"
      Γεγονός Κ {
            Διάβασε Κάτι$
            Συνάρτηση {
                  τύπωσε .βββ$, .μετρητής
            }
      }
      Συνάρτηση ΜεΌνομα {
                  Διάβασε Κ$
                  Τύπωσε Κ$
                  .μετρητής++
              
            }
      Τμήμα Άλφα {
            Γεγονός .Κ Νέο .ΜεΌνομα()
      }
      Τμήμα Διαδικασία {
            Κάλεσε Γεγονός,"οκ"
            Τύπωσε .μετρητής
      }
}
Πίνακας Α(10)=αλφα()
Α(1).βββ$="τεστ"
Για Α(4) {
      Κάλεσε Γεγονός "τέλειο"
      Τύπωσε .μετρητής
      Κάλεσε Γεγονός "τέλειο"
      Τύπωσε .μετρητής
}
Για Α(1) {
      Κάλεσε Γεγονός "τέλειο 1"
      Τύπωσε .μετρητής
      Κάλεσε Γεγονός "τέλειο 1"
      Τύπωσε .μετρητής
}
Για Α(4) {
      Κάλεσε Γεγονός "τέλειο"
      Τύπωσε .μετρητής
      Κάλεσε Γεγονός "τέλειο"
      Τύπωσε .μετρητής
}
Για Α(1) {
      Κάλεσε Γεγονός "τέλειο 1"
      Τύπωσε .μετρητής
      Κάλεσε Γεγονός "τέλειο 1"
      Τύπωσε .μετρητής
}


Άλλο παράδειγμα με πέρασμα με αναφορά. Έχουμε μια γενική ομάδα Δ που έχει ένα Γεγονός Α. και μια συνάρτηση που την συνδέουμε με το Γεγονός. Μετά έχουμε μια κλάση με ένα τμήμα με όνομα Διαδικασία, το οποίο κάθε φορά στέλνει ένα οκ και ζητάει ένα νούμερο. (αυτός είναι ο σκοπός της αναφοράς, να επιστρέψει κάτι). Δείτε ότι σε μια γραμμή ενώσαμε το Γεγονός με μια συνάρτηση, έξω από τα αντικείμενα.


Γενική Ομάδα Δ {
      ΚΛΜ=1
      Γεγονός Α {
            Διάβασε Μ$, &ΑΑ
      }
      Συνάρτηση ΠάρεΜ {
            Διάβασε μ$, &ΒΒ
            Τύπωσε "Το έλαβα"
            ΒΒ=.ΚΛΜ
            .ΚΛΜ++
      }
}
Γεγονός Δ.Α νέο Δ.ΠάρεΜ()
Κλάση Αλφα {
      Νούμερο
      Τμήμα Διαδικασία {
           Κάλεσε Γεγονός Δ.Α , "οκ", &.Νούμερο
      }
}
Πίνακας Α(10)=Άλφα()
Α(3).Διαδικασία
Α(7).Διαδικασία
Α(1).Διαδικασία
? Α(3).Νούμερο, Α(7).Νούμερο, Α(1).Νούμερο


Προσθήκη (13/4/2016)
Παραλλαγή με δείκτη. Οι δείκτες στην Μ2000 είναι αλφαριθμητικά και δείχνουν το όνομα, είναι δηλαδή ισχνές αναφορές. Τις λέμε ισχνές γιατί ενώ είναι αναφορές, για να χρησιμοποιηθούν θέλουν ένα στάδιο ακόμα, δηλαδή αυτό της ένωσης ή αναζήτησης του αναφερόμενου, που ενδέχεται να μην υπάρχει!

Τώρα στον κώδικα της κλάσης Άλφα δεν έχουμε γνωστοποιήσει το γεγονός που θα συνδεθεί. Εδώ στην Διαδικασία παίρνω αντίγραφο στην Μ. Αλλά θα μπορούσα να δημιουργήσω κανονική αναφορά, με έναν από τους δύο τρόπους που δείχνουν οι σημειώσεις 1 και 2
Προσοχή δεν μπορώ να διαβάσω δυο φορές την Μ στο &Μ, δηλαδή δεν μπορώ να ορίσω πριν δώσω αναφορά στην Μ. (υπάρχει τρόπος με  Διάβασε Νέο &Μ αλλά το αποφεύγουμε όταν ξέρουμε ότι θα φτιαχτεί μια μεταβλητή, θα δουλέψουμε με αυτήν και μετά θα χαθεί όπως πρέπει στο πέρας της κλήσης).

Ομάδα Δ {
      ΚΛΜ=1
      Γεγονός Α {
            Διάβασε Μ$, &ΑΑ
      }
      Συνάρτηση ΠάρεΜ {
            Διάβασε μ$, &ΒΒ
            Τύπωσε "Το έλαβα"
            ΒΒ=.ΚΛΜ
            .ΚΛΜ++
      }
}
Γεγονός Δ.Α νέο Δ.ΠάρεΜ()
Κλάση Αλφα {
      Νούμερο, Δείκτης$
      Τμήμα Αλφα {
            Διάβασε .Δείκτης$
      }
      Τμήμα Διαδικασία {
           Μ=εκφρ(.Δείκτης$)

Σημ 1 : Βάλε .Δείκτης$ : Διάβασε
Σημ 2 : Ένωσε Ισχνή .Δείκτης$ στο Μ
           Κάλεσε Γεγονός Μ , "οκ", &.Νούμερο
      }
}
Πίνακας Α(10)=Άλφα(&Δ.Α)
Α(3).Διαδικασία
Α(7).Διαδικασία
Α(1).Διαδικασία
? Α(3).Νούμερο, Α(7).Νούμερο, Α(1).Νούμερο




Άλλο πρόγραμμα. Εδώ βάζουμε δυο φορές την Κ() στο Γεγονός Α. Δείχνω πως αντιγράφω το Γεγονός σε άλλο,
Γεγονός Α {
      Διάβασε μ$
}
Συνάρτηση Κ {
      διαβασε μ$
      Τύπωσε μ$
}
Γεγονός Α νέο Κ()
Γεγονός Α νέο Κ() \\ 2η φορά!
Κάλεσε Γεγονός Α, "οκ Α"
Βαλε Α
Τύπωσε Φάκελος$()
Σωρος
Τύπωσε Ταύτιση("Ε")
Διάβασε Β
Γεγονός Α πέτα Κ()
Κάλεσε Γεγονός Α, "οκ Α"
Κάλεσε Γεγονός Β, "οκ Β"