Πέμπτη, 28 Απριλίου 2016

Αναθεώρηση 224 - (Linux συμβατή)

Η αναθεώρηση 224 (222 και 223 έφυγαν..άμεσα) έλυσε ένα θέμα με τo Wine (Linux). Είχα αφήσει στους πίνακες κατακερματισμού να διαβάζουν ένα word το οποίο είχε δεδομένα που άλλαζαν..με συνέπεια πότε να δουλεύει και πότε όχι. Τυχαία κάνω έλεγχο και σε XP και βλέπω ότι έχει και εκεί το ίδιο πρόβλημα με το Wine. Σημειώστε ότι τα 7 δεν είχαν τέτοιο πρόβλημα.

Όλες εντολές που ήταν σε τρεις συνεχόμενες συναρτήσεις επειδή δεν μπορούσαν να μπουν σε μια γιατί  ο κώδικας ήταν μεγαλύτερος από 64k, τώρα είναι σε μια, επειδή κάθε εντολή είναι σε δική της συνάρτηση, και η κεντρική απλά χρησιμοποιείται ελάχιστες φορές. Τι περισσότερες φορές χρησιμοποιείται ένας πίνακας κατακερματισμού που έχει τις διευθύνσεις των συναρτήσεων, των εντολών. Αυτό που διαφοροποιεί το τρόπο που θα κληθούν είναι οι ρουτίνες, π.χ. execute που τρέχει το κυρίως πρόγραμμα και η interpret που εκτελεί την γραμμή εντολών χρησιμοποιεί την απευθείας κλήση. Ο επεξεργαστής για τις κλάσεις χρησιμοποιεί την στάνταρ οδό

Μπορούμε να ορίσουμε μια γενική με το όνομα μιας εντολής. Η εντολή Print δεν θα ξαναδουλέψει ως Print, μέχρι να δώσουμε New (όταν σβήνουμε το πρόγραμμα ξανακτίζεται η πίνακας κατακερματισμού, και εδώ έχει αφαιρεθεί η Print). Δουλεύει το ? ως Print αλλά μπορούμε να καλέσουμε την γνήσια Print με το @. 

Module Global Print {
      ? "ok", number
}
Module Check {
      Print 100
}
Check
@Print "normal print"


Μια άλλη περίπτωση. Η Σ είναι η συντόμευση της εντολής Συγγραφή. Μπορούμε να την καλέσουμε και μέσα από ένα τμήμα που εκτελείται. Η Μ2000 μπορεί να αλλάζει κώδικα την ώρα της εκτέλεσης. Όχι τον κώδικα που εκτελεί εκείνη την ώρα το αντικείμενο εκτέλεσης, αλλά τον κώδικα στη λίστα που περιέχονται τα τμήματα, στο αντίστοιχο όνομα, εδώ άλφα. Θα μπορούσε κανείς πράγματι να πειράξει και τμήμα που τρέχει εκείνη την ώρα αν πειράξει ρουτίνα, επειδή τις ρουτίνες της διαβάζει άμεσα από την "αποθήκη" κάθε φορά που την χρησιμοποιεί. Το παράδειγμα εδώ απλά θέλει να δείξει ότι μπορούμε να έχουμε μια Σ ως μεταβλητή. ενώ λειτουργεί και ως εντολή. Δεν γίνεται σε όλες τις εντολές αυτό, παρά μόνο σε αυτές που δεν έχουν άμεση κλήση. Η Σ ή Συγγραφή δεν έχει άμεση κλήση. 

Σ αλφα
Σ=10
Τύπωσε Σ
Σ αλφα


Ένα άλλο θέμα που διόρθωσα ήταν το Ctrl + Tab που ενναλλάσει τα παράθυρα που φτιάχνουμε. Όταν ήταν modal ...είχαμε κατάρρευση του προγράμματος (δεν μπορεί να πάρει focus το παράθυρο που δεν είναι enabled, ή ελληνικά δεν μπορεί να γίνει τρέχον - αυτό που έχει την εστίαση- το παράθυρο που είναι ανενεργό).

Επίσης δεν το είχα αναφέρει αλλά από την 221 είχα φτιάξει και τα Tab-Shift-Control και Tab-Control για το EditBox. Από οποιοδήποτε άλλο στοιχείο ελέγχου δουλεύει το Tab-Control για αλλαγή παραθύρου, αλλά στο EditBox δουλεύει για να προσθέτει κενά σε μια γραμμή ή περισσότερες στα αριστερά.(με το Shift και τα Tab-Control αφαιρούμε κενά),
Αν επικολλήσουμε κείμενο με TAB τότε θα γίνουν κενά (έχω φτιάξει έναν αλγόριθμο για να υπολογίζει πόσα κενά θα βάλει αν το κείμενο που βάζουμε ήταν σταθερού πλάτους χαρακτήρα για κάθε χαρακτήρα.(όπως στην κονσόλα του Dos).

Όριο.Αναδρομής
Εξ ορισμού είναι 10000 κλήσεις για ρουτίνα και 14500 για συναρτήσεις. Το όριο για ρουτίνες μπορεί να αλλάξει. Ουσιαστικά οι ρουτίνες δεν απασχολούν τον σωρό του exe, οπότε μπορούμε να το αλλάξουμε σε 30000 . Η εντολή Όριο.Αναδρομής χωρίς αριθμούς δείχνει τη ρύθμιση που έχει, ενώ με έναν αριθμό αλλάζουμε για τις ρουτίνες και με δεύτερο για τις συναρτήσεις. Ειδικά όμως για τις συναρτήσεις το αλλάζουμε προς τα κάτω. Σαν ένα είδος κόφτη, δηλαδή, για ασφάλεια. Μπορεί να λέει 14800 αλλά δεν είναι σίγουρο. Το τσεκάρουμε με αυτό το πρόγραμμα

function rec {
      read bb
      if bb<=0 then =0 : exit function
      print bb
      =rec(bb-1)
}
Profiler
a= rec(14500)
print timecount

Στον φάκελο με την Μ2000 (αν έχουμε αφήσει και τον πηγαίο κώδικα) θα δούμε ένα αρχέιο stack.bat το οποίο περιέχει αυτό:
Echo off
Cls
Echo Set Stack Size for M2000 - press enter
C:\masm32\bin\editbin /stack:108000000 m2000.exe

Η μνήμη των 100+Mbytes δεν αποδίδεται στο πρόγραμμα αλλά να τι γίνεται: Δεσμεύονται διευθύνσεις συνεχόμενες για το μέγεθος που ζητάμε. αλλά αποδίδεται μνήμη σε πακέτα, όσο χρειάζονται και μέχρι να καλυφθεί ο χώρος.
Χρειαζόμαστε τον masm32 και το editbin για να αλλάξουμε το μέγεθος του Stack. Θα πρέπει να μην τρέχει το πρόγραμμα και η αλλαγή δεν πειράζει την υπογραφή. (το m2000.exe είναι υπογεγραμμένο πρόγραμμα και το πιστοποιητικό ρίζας περιέχεται στο φάκελο, το ca.crt - certificate, το οποίο μπορούμε να εγκαταστήσουμε ως ριζικό, και το οποίο βγάζει έγκυρη την υπογραφή στο exe)

Για έλεγχο σε ρουτίνες:

Recursion.limit 20000
Profiler
rec(20000)
Print Timecount


Sub rec(x)
Print x
If x>1 Then rec(x-1)
End Sub

Τρίτη, 26 Απριλίου 2016

Αναθεώρηση 221, περισσότερη ταχύτητα!

Στην Αναθεώρηση 221, έβαλα και άλλες εντολές να καλούνται εσωτερικά με δείκτη σε συνάρτηση, αντί να αναζητούνται σε ένα selcet case, ώστε να έχουμε σταθερό χρόνο απόκρισης. Μια εντολή βρίσκεται με το πολύ δυο συγκρίσεις, λόγω του πίνακα κατακερματισμού που κάνει το εξής: Βγάζει με μαθηματικό τύπο τη θέση του εντολής σε έναν πίνακα, ένα νούμερο, και αν δεν το βρει εκεί, το στοιχείο που είναι εκεί έχει μια δική του λίστα στοιχείων με ίδιο νούμερο. 

Παράδειγμα με πίνακα κατακερματισμού  γραμμένο σε M2000 υπάρχει εδώ  (μάλιστα βάσει αυτού του παραδείγματος αποφάσισα να εντάξω στη γλώσσα το πίνακα κατακερματισμού, και τώρα δουλεύει για τις μεταβλητές, τους πίνακες, τις συναρτήσεις, τα τμήματα, όλα αυτά τα ονόματα βρίσκονται γρήγορα).

Επίσης ένα άλλο σημείο που με απασχόλησε (και μου πήρε δυο μέρες να το φέρω στα ίσα, να δουλεύει για όλες τις περιπτώσεις)  είναι η δυνατότητα να ανοίγουν διαδοχικά modal παράθυρα. Δεν υπάρχει λέξη που να δηλώνει τι  λέμε modal, αλλά περιγραφικά σημαίνει να ανοίγουμε ένα παράθυρο κάνοντας πρόσκαιρα ανενεργά τα παράθυρα της εφαρμογή μας. Ένα παράδειγμα απλού modal παραθύρου είναι το MessageBox, όπου στη Μ2000 βγαίνει με την συνάρτηση Ρώτα() ή Ask().

Δεν είναι εύκολο να κατανοήσουμε την δυσκολία του Modal. Διότι το πρόβλημα είναι σε πια κατάσταση θα μεταβαίνει κάθε παράθυρο όταν ένα Χ παράθυρο ανοίξει ως modal και πάλι σε πια κατάσταση θα μεταβαίνει κάθε παράθυρο όταν αυτό το Χ παράθυρο κλείσει. Αν έχουμε ένα μόνο βαθμό για άνοιγμα Modal παραθύρου, το πρόβλημα και πάλι δεν είναι εύκολο γιατί μπορεί ένα παράθυρο να είναι ήδη ανενεργό,. Δηλαδή αν αποφασίσουμε ό,τι είναι ενεργό να το κάνουμε ανενεργό τότε στην φάση που θα τα ενεργοποιήσουμε ξανά, επειδή έκλεισε το modal, τότε ενδέχεται να ενεργοποιήσουμε και εκείνο που δεν ήταν από πριν ενεργό. Μια λύση είναι να μαρκάρουμε πια κάναμε ανενεργά και μετά να τα ενεργοποιήσουμε. Αν έχουμε πολλά παράθυρα Modal, τότε κάθε φορά που επιστρέφουμε από ένα Modal, πέφτουμε στο προηγούμενο, μέχρι να φτάσουμε στο τελευταίο. Το πρόβλημα δυσκολεύει περισσότερο αν σκεφτούμε ότι ένα modal παράθυρο μπορεί να ανοίξει άλλα παράθυρα που δεν είναι Modal...αλλά δεν μπορεί να τα μπλοκάρει. Όλο αυτό το μπέρδεμα καταστάσεων το βγάζει σε πέρας αυτό που έχω γράψει.

Κάθε φορά που ανοίγουμε ένα modal σταματάει η ροή εκτέλεσης εντολών...στο νήμα (εδώ χρησιμοποιούμε την AFTER {}  που κάνει αυτόματα ένα νήμα να τρέξει μια μόνο φορά μετά από συγκεκριμένο χρόνο. Όταν έχουμε ανοίξει και το πέμπτο παράθυρο..έχουμε σταματήσει τον κώδικα της Μ2000 σε πέντε σημεία. Παρόλα αυτά το νήμα που γράφει στην οθόνη (κονσόλα της Μ2000) συνεχίζει να τρέχει. Δοκιμάστε με ΧΧ=0 για να φτιάξει τέσσερα παράθυρα κανονικά πάνω από το πρώτο Modal. Το τελευταίο παράθυρο ανοίγει με κλικ ένα messagebox, το οποίο απενεργοποιεί όλα τα παράθυρα και στην επιστροφή ενεργοποιεί όπως πρέπει και πάλι το πρώτο παράθυρο είναι Modal αν έχει ανοίξει τα άλλα με XX=0 δηλαδή κανονικά, τότε μπορεί να έρθει και μπροστά από αυτά. Ενώ κανονικά ένα Modal όταν είναι ενεργό είναι πάντα μπροστά. Εδώ αν ανοίξει ένα μη modal μπορούν να αλλάζουν θέση, να έρχεται μπροστά αυτό που θέλουμε. 

Τα modal παράθυρα εξ ορισμού δεν χάνονται όταν κλείνουν από το χρήστη, έτσι ώστε να ανοίξουν και άλλη φορά. Αν θέλουμε όμως και στα μη Modal να τα κρατάμε φορτωμένα, θα πρέπει στο κλείσιμο να τα κρύβουμε, και αυτό γίνεται στο simple.unload με την μέθοδο "Hide".

Δείτε επίσης ότι η simple.click  εκτελείται και ίσως να φτιάξει ένα νήμα, αλλά το νήμα δεν τρέχει μέσα στη συνάρτηση, έχουμε δώσει χρόνο και αυτός αρκεί για να τρέξει το νήμα όταν αυτή τερματίσει. Με τον τρόπο αυτό τερματίζουμε την εξυπηρέτηση του clik, και αφήνουμε το σύστημα να "παίξει" στην ώρα του την επόμενη "Ασύγχρονη" εντολή, ή μπλοκ εντολών

Επίσης δείτε ότι το πρόγραμμα σταματάει στην εμφάνιση της πρώτης φόρμας και από εκείνο το σημείο παίζουν μόνο τα μηνύματα. Αν κλείσουμε την πρώτη φόρμα...τότε μια εντολή τερματίζει όλα τα νήματα και διαγράφει τις φόρμες.

\\ An example of modal show
\\ use XX=1 for non modal after first modal
\\ also note that messagebox is a modal window and popup by Ask() Function
Global XX=1
Declare Simple(5) form
For i=0 to 4
      Method Simple(i), "FontAttr", "Arial Black", 18
      Layer Simple(i) {
            Linespace 30
            Window 12, 10000,8000
            Cls 1,0
            Form 30,20 \\ make 30X20 chars*lines calculating new font size.
            Cursor 0,3
            Print width, height
            Print "01234567890123456789"
      }
Next i
Function simple.unload {
      If XX<>0 then exit
      read new index, &cancel
      method Simple(index), "Hide"
      cancel=true
}


k=0
\\ this is the background task
Thread {
      k++
      Print k
} As anything Interval 20


Function simple.click {
      Threads
      Read New index
      Select Case index
      Case 0
      {
            After 50 {
                  Method Simple(1), "Show" , XX
                  Print "end case 0"
            }
        }
      Case 1
      {
            After 50 {
                  Method Simple(2), "Show" , XX
                  Print "end case 1"
                  }
      }
      Case 2
      {
            After 50 {
                  Method Simple(3), "Show" , XX
                  Print "end case 2"
                  }
      }
      Case 3
      {
            After 50 {
                  Method Simple(4), "Show" , XX
                  Print "end case 3"
                  }
      }
      Case 4
      {
            After 50 {
                  Print Ask("ok")
                  Print "end case 4"
                  }
      }
      End Select
      Threads
}
Method Simple(0), "Show" ,1
Print "Finish"
Threads Erase
Declare simple() Nothing
Show  \\ set focus to M2000 console



Δευτέρα, 18 Απριλίου 2016

Κλάσεις από κλάσεις στη Μ2000.

Μπορούμε στη Μ2000 να φτιάξουμε ένα αντικείμενο και να του δώσουμε επιπλέον ιδιότητες ενός άλλου αντικειμένου.
1. Βασική γνώση εδώ είναι ότι ένα αντικείμενο έχει φυσική παρουσία, ενώ μια κλάση είναι συνάρτηση που δίνει ένα αντικείμενο. Γλώσσες όπως η Java έχουν ειδικό λεκτικό το extents που δημιουργεί κλάση με βάση άλλη κλάση. Στη Μ2000 η λογική είναι πιο απλή (επειδή δεν υπάρχουν έλεγχοι τύπων, και θα γίνει αντιληπτό στον αναγνώστη γιατί δεν μπορούν να υπάρχουν τύποι),
2. Βασική γνώση επίσης είναι ότι ο μηχανισμός επέκτασης ενός αντικειμένου  είναι η συγχώνευση. Δηλαδή μπορούμε να συγχωνεύσουμε ένα αντικείμενο σε ένα άλλο. Δείτε όμως ότι πάντα μιλάμε για αντιγραφή με συγχώνευση  Στην κυριολεξία αν θέλουμε το Α να συγχωνευθεί στο Β, τότε θα πάρουμε ένα Β που θα έχει ότι το Α και ότι είχε το Β διαφορετικό, Το Α θα παραμένει ως έχει.
3. Βασική γνώση επίσης είναι ότι η αντιγραφή με συγχώνευση γίνεται μόνο σε ανοικτό αντικείμενο. Κλειστά αντικείμενα στη Μ2000 είναι τα ανώνυμα αντικείμενα, αυτά που επιστρέφουν από συναρτήσεις, και αυτά που βρίσκονται σε πίνακες. Ένα ανώνυμο αντικείμενο μπορεί να βρίσκεται στο σωρό τιμών. Ξέρουμε ότι έχουμε ανοικτό αντικείμενο όταν αυτό υπάρχει σε μια μεταβλητή.

Το παράδειγμα είναι στα αγγλικά:
Η Class (Κλάση) είναι μια συνάρτηση που επιστρέφει κλειστό αντικείμενο (ανώνυμο). Πώς λειτουργεί;
Θα φτιάξει ένα αντικείμενο Some με μια ιδιωτική ιδιότητα count, και με μια μέθοδο increment και μια συνάρτηση toString$
Ας τρέξουμε το πρόγραμμα (έστω είναι σε ένα τμήμα Α, module A)
Καθώς ξεκινάει την εκτέλεση ο διερμηνευτής (δ.) βλέπει τον ορισμό και τον καταχωρεί τοπικά ως συνάρτηση Some(). Δεν ασχολείται με το αν είναι έγκυρος ή όχι, ούτε φτιάχνει κάποιο αντικείμενο.
Μετά o δ. βρίσκει την s, βλέπει ότι δεν υπάρχει τοπική s και δημιουργεί μία άδεια (Empty), και εκτελεί την παράσταση μετά το = για να καταχωρήσει τιμή. Τότε τρέχει η συνάρτηση Some() και δίνει το κλειστό αντικείμενο. Με το που βλέπει το αντικείμενο ο δ. φτιάχνει για το s ότι λέει το κλειστό αντικείμενο, και δίνει τιμές ότι έχει αυτό και το πετάει.
Μένει τότε το ανοικτό αντικείμενο, δηλαδή θα μείνει μια κρυφή μεταβλητή s.count, ένα τμήμα s.increment, μια συνάρτηση s.toString$() και η s που κρατάει τη λίστα μελών της ομάδας, γιατί στην πράξη ομάδα στοιχείων έχουμε φτιάξει. Το ερώτημα που προκύπτει είναι, ότι αφού η s.toString$() είναι μια κανονική, ξεχωριστή συνάρτηση, πώς γίνεται να διαβάζει την s.count.
Οι συναρτήσεις στη Μ2000 βλέπουν γενικές και τοπικές μεταβλητές συν μια ακόμα, αυτή του αντικειμένου που τις δημιούργησε (αν τις δημιούργησε αντικείμενο). Έτσι η s.toString$() είναι μια κανονική συνάρτηση, που βλέπει όμως τις ιδιωτικές και δημόσιες μεταβλητές/συναρτήσεις/τμήματα του αντικειμένου που "ανήκει". Ομοίως και η s,increment βλέπει την s.count.

Αν στο τέλος απαριθμήσουμε τον αριθμό μεταβλητών θα πούμε με ακρίβεια ότι έχουμε τρεις, την s, την s.count (που είναι κρυφή) και την v$. Αν απαριθμήσουμε τις συναρτήσεις και τα τμήματα (με εξαίρεση αυτό που βρίσκεται ο κώδικας), θα πούμε με βεβαιότητα ότι έχουμε δυο συναρτήσεις, την Some() και την s.toString$() και ένα τμήμα το s.increment. Σύνολο στις λίστες 5 οντότητες.
Αν είχαμε φτιάξει άλλα δύο αντικείμενα με την Some() τότε θα είχαμε επιπλέον 4 μεταβλητές και 4 συναρτήσεις-τμήματα.

Class Some {
   Private: count
   Public:
    Module increment {
      .count++
   }
   Function toString$ {
       =Str$(.count, "00000")
   }
}


s = Some()
s.increment
s.increment
s.increment
v$ =s.toString$()
Print v$


Αφού είδαμε όλα αυτά, πάμε να δούμε πώς θα κάνουμε κάτι εξαιρετικό! Πώς θα κάνουμε επέκταση ενός αντικειμένου, αλλάζοντας την ιδιωτική μεταβλητή και αλλάζοντας ένα τμήμα του.
Θα χρησιμοποιούσε εδώ απ΄ευθείας ορισμό ανοικτού αντικειμένου. Η Group φτιάχνει απ΄ευθείας ανοικτό αντικείμενο. Που σημαίνει ότι όταν φτάσουμε στην επόμενη εντολή Group θα υπάρχει η Some ως αντικείμενο, η Some.count, το τμήμα Some.increment, και η συνάρτηση Some.toString$()

Αμέσως μετά φτιάχνουμε ένα ανοικτό αντικείμενο, το ExtentSome με μια ιδιωτική την ExtentSome.count, και ένα τμήμα το ExtentSome.increment. Εδώ δίνουμε αρχική τιμή στη μεταβλητή και επιπλέον δίνουμε και στο τμήμα μια άλλη λειτουργία, έναν άλλο τύπο στην ExtentSome.count

Δείτε τι γίνεται στην αμέσως επόμενη γραμμή μετά τον ορισμό της ομάδας (group) ΕxtentSome. Φτιάχνω μια S από το κλειστό αντικείμενο που επιστρέφει η Some. Η Some είναι αντικείμενο και να χρησιμοποιηθεί στα δεξιά μιας αντικατάστασης θα δώσει ένα κλειστό αντικείμενο. Στην κυριολεξία μαζεύει ότι έχει η λίστα της και τα αντιγράφει σε ένα αντικείμενο που λέγεται κλειστό (είναι η κατάστασή του τέτοια δηλαδή). Αυτά που έχει θα πάνε στην S όπως ακριβώς έκανε και η κλάση στο προηγούμενο παράδειγμα. Κάθε αντικείμενο group (ομάδα) στη Μ2000 δίνει ένα αντίγραφο όποτε θέλουμε. Θα δημιουργηθούν τα s και s.count, και τα τμήματα/συναρτήσεις s.increment και s.toString$()    (όταν λέμε για ανοικτό αντικείμενο μιλάμε για δημιουργία μεταβλητών στους καταλόγους του τμήματος, άρα για οντότητες που μπορούμε να χειριστούμε ανεξάρτητα)

Δείτε τι γίνεται αμέσως μετά. Ενώ τη πρώτη φορά η s ήταν άδεια (δεν υπήρχε και δημιοθργήθηκε), τη δεύτερη είναι ήδη ομάδα άρα το ExentSome θα αντιγραφεί στην s με συγχώνευση. Που σημαίνει ότι δεν θα δημιουργηθεί νέα s.count (θα παραμείνει ιδιωτική), ούτε νέo τμήμα  s.increment (μπορούμε να το λέμε και μέθοδο, αλλά η λέξη μέθοδος ως εντολή κάνει κάτι άλλο στη Μ2000, οπότε η αναφορά στη μέθοδο γίνεται μόνο λεκτικά όχι με εντολή).

Μπορούμε να παραλείψουμε τη γραμμή s=ExtentSome() και θα δουλέψει το πρόγραμμα, με αυτά που ;έδωσε η Some στην s.
Στην ουσία η s κληρονόμησε την Some, και μετά την ExtentSomt. Τα αρχικά αντικείμενα μπορούν να αλλάξουν, αλλά δεν σχετίζονται πια με την s. Σε άλλες γλώσσες γίνεται μεταξύ τους τα αντικείμενα ενός τύπου να έχουν κοινή μεταβλητή, εδώ δεν γίνεται. Κοινές μεταβλητές δίνουν τα αντικείμενα στο πρώτο επίπεδο συναρτήσεων και τμημάτων (στη Μ2000 μπορούν οι συναρτήσεις και τα τμήματα  να έχουν φωλιασμένες συναρτήσεις και τμήματα). Όπως επίσης κοινές μεταβλητές κάνουμε ως γενικές (μια γενική σε ένα τμήμα θα υπάρχει όσο το τμήμα υπάρχει και θα σκιάζει όποια τυχόν γενική υπήρχε στο πατρικό τμήμα).

Group Some {
   Private: count
   Public:
    Module increment {
      .count++
   }
   Function toString$ {
       =Str$(.count, "00000")
   }
}
Group ExtentSome {
      Private: count=1000
      Public:
          Module increment {
            .count*=10000
       }
}
s = Some
s = ExtentSome
s.increment
s.increment
s.increment
v$ =s.toString$()
Print v$



Όμως η δημιουργικότητά μας δεν σταματάει εδώ. Στο προηγούμενο παράδειγμα στο τέλος μετράμε τι έχει στις λίστες του ο διερμηνευτής  (έχει μια λίστα για πίνακες και μεταβλητές και μια για συναρτήσεις και τμήματα).
Τέσσερα κομμάτια για το Some συν τρία για το ExtentSome, συν Τέσσερα για το s και μια η v$ σύνολο 12. Στο προηγούμενο παράδειγμα είχαμε 5, και εδώ αλλάξαμε μόνο δυο οντότητες, άρα τα επιπλέον 5 ήταν απαραίτητα για την αλλαγή.
Εδώ χρησιμοποιούμε λάμδα συναρτήσεις H λάμδα Some έχει και μια αδελφή συνάρτηση την Some(). Στις λίστες του διερμηνευτή μόνο αυτά τα δύο αναφέρονται. Η λάμδα ExtentSome έχει και αυτή την ExtentSome μεταβλητή και την ExtentSome() συνάρτηση, παράλληλα εσωτερικά έχει και ένα αντίγραφο της Some (γιατί την έχουμε μετά την λέξη Lambda και πριν το "->" και αυτός είναι ο χώρος που δείχνουμε τι θα συλλάβει το αντικείμενο λάμδα. Δεν περνάμε αναφορά στο Some αλλά αντίγραφο του Some, το οποίο για την λάμδα είναι μη τοπικό, δηλαδή θα υπάρχει για αυτό όσες φορές και αν καλέσουμε την συνάρτηση ExtentSome. Αν μάλιστα βγάλουμε αντίγραφο του ExtendSome θα έχει και αυτό την δική του Some.

Για την Some. όταν τρέχει δημιουργεί τοπικά μια κλάση και την δίνει ως επιστροφή, ως κλειστό αντικείμενο (άρα δεν γράφονται στο κατάλογο του διερμηνευτή τα στοιχεία του. αλλά σε κατάλογο στο ίδιο το αντικείμενο χωρίς όνομα, να γιατί λέγεται κλειστό, δεν ξέρει τι όνομα να δώσει, ενώ π.χ. στο s παρακάτω το count είναι s.count, στο κλειστό απλά γνωρίζει ότι αν ανοίξει θα φτιάξει για δοσμένο όνομα Χ το Χ.count)

Πραγματικά αν μετρήσουμε εδώ θα βγάλουμε 2 +2+4+1 =9 οντότητες στις λίστες άρα 4 λιγότερες και τώρα μια λάμδα η extented δίνει επακριβώς ένα αντικείμενο εκτεταμένο, ή παραλλαγμένο, ή υποκλάσης της κλάσης Some (αν θέλουμε συμβατικά να το λέμε, για τη Μ2000  αυτά τα αντικείμενα είναι ομάδες groups)

Some = Lambda -> {
      Class InnerSome {
         Private: count
         public:
          Module increment {
                  .count++
               }
         Function toString$ {
             =str$(.count, "00000")
               }
         }
         =InnerSome()
}


ExtentSome=Lambda Some -> {
      Class Extend {
      Private: count=1000
      Public:
          Module increment {
            .count*=10000
         }
      }
      B=Some() \\ first make a some
      B=Extend() \\ and extend it
      =B
}



s = ExtentSome()
s.increment
s.increment
s.increment
v$ =s.toString$()
Print v$



Μια παραλλαγή του παραπάνω προγράμματος είναι αυτή εδώ όπου αν προσθέσουμε τις οντότητες είναι τώρα μια λιγότερη αφού τη πρώτη λάμδα την κάναμε κλάση. Και αντί στην ExtentSome να κρατάμε με σύλληψη την λάμδα κάνουμε κάτι άλλο, δημιουργούμε τo ανοικτό αντικείμενο Β, το οποίο δημιουργείται μόνο για την ExtentSome, και κλείνει, γίνεται κλειστό και μπαίνει στο αντικείμενο λάμδα ExtendSome (το αντικείμενο κρατάει την συνάρτηση και ότι έχει συλλάβει από το περιβάλλον, και έχουμε δηλώσει να το κάνει,η σύλληψη είναι αντιγραφή).

Class Some {
   Private: count
   Public:
    Module increment {
      .count++
   }
   Function toString$ {
       =Str$(.count, "00000")
   }
}
ExtentSome=Lambda B=Some() -> {
      Class Extend {
      Private: count=1000
      Public:
          Module increment {
            .count*=10000
         }
      }
      \\ merge Extent() to B
      B=Extend()
      =B
}


s = ExtentSome()
s.increment
s.increment
s.increment
v$ =s.toString$()
Print v$



Και για Bonus (αφού διαβάσατε μέχρι εδώ)...
Ένα Group μπορεί να πάρει και λάμδα συναρτήσεις στην λίστα του. Εδώ φτιάχνουμε την Μ. Επειδή δημιουργείται και συνάρτηση Μ() θα έχει επίσης και ένα πεδίο που θα λέει "ανήκω στο Alfa".  Θέλω όμως να συλλάβω την k και να την χρησιμοποιώ, αλλά είναι ιδιωτική. Οπότε φτιάχνω ένα τμήμα που ξεκινάει την Μ. Στην ουσία της δίνει νέο ορισμό (δείτε το "<=" αν το ξεχάσουμε θα φτιάξει ο διερμηνευτής τοπική μεταβλητή Μ, η οποία θα χαθεί με το πέρας εκτέλεσης της StartM. Επειδή η Alfa.k είναι ιδιωτική την αντιγράφουμε σε μια άλλη, εδώ δείτε ότι μετά το = υπάρχει μια τελεία και το k (lambda k=.k). Τώρα χειριζόμαστε το αντίγραφο της Αlfa.k στην k της Μ. Οι συναρτήσεις λάμδα δουλεύουν όπως και οι μεταβλητές στην αντικατάσταση, πετάνε ότι έχουν και παίρνουν νέο ορισμό. Πράγματι καλούμε δεύτερη φορά την Alfa.SrartM και κάνουμε νέα σύλληψη (και αυτή είναι μια σκοπιμότητα των λάμδα).


Group Alfa {
Private:
      k=100
Public:
      klm=5
      M=lambda->0
      Module StartM {
            .M<=lambda k=.k -> {
                  k++
                  =k*.klm
            }
      }
      Function M2 {
            .k--
            =.k
      }    
}
Alfa.StartM
For I=1 to 10
      Print Alfa.M(), Alfa.M2()
Next i
\\ new capture
Alfa.StartM
For I=1 to 10
      Print Alfa.M(), Alfa.M2()
Next i


Επειδή έχουμε στον ορισμό της Μ την .klm σημαίνει ότι αν δώσουμε αντίγραφο  και τρέξει η Μ χωρίς να είναι σε αντικείμενο ή αν είναι χωρίς αυτό να έχει μια klm τότε θα βγει λάθος. Μπορούμε να περάσουμε με αναφορά την συνάρτηση. Οι συναρτήσεις που ανήκουν σε πρώτο επίπεδο σε μια ομάδα (όχι στις φωλιασμένες) περνούν και το περιβάλλον της ομάδας μαζί τους, δηλαδή μπορούν να καλέσουν συναρτήσεις και τμήματα της ομάδας και να αλλάξουν τιμές σε αυτήν.
Εδώ θα δουλέψει γιατί το Alfa.M είναι λάμδα αντικείμενο και έχει και τη συνάρτηση ALFA.Μ()  που περνάει με αναφορά στο TestMe
Βάλτε το κώδικα αυτό ως συμπλήρωμα του προηγούμενου!

Module TestMe {
      Read &MM()
      Print MM()
}


TestMe &Alfa.M()


Αναθεώρηση 220, μεγαλύτερη ταχύτητα!

Μετέφερα και άλλες εντολές στο νέο σύστημα για άμεση εκτέλεση (και τα δυο δουλεύουν ταυτόχρονα, ότι δεν υπάρχει δείκτη σε συνάρτηση καλείται με τον κανονικό τρόπο, μέσω ενός μεγάλου select case).

Επίσης έφτιαξα το Κλείσε Βάση γιατί δεν την έκλεινε αν δεν δίναμε όλη την διαδρομή (θα έκλεινε μόνο με τον τερματισμό ή με μια Κλείσε χωρίς παράμετρο που κλείνει ότι έχει έχει ανοικτό, βάση και αρχείο).
Στο παράδειγμα έχω αναμείξει την Τύπωσε με την Αναφορά (η πρώτη τυπώνει σε στήλες, ενώ η δεύτερη εμφανίζει κείμενο, αλλά παίρνει την θέση του δρομέα για αριστερό περιθώριο.
Δείτε ότι στη βάση γράφω και ρώσικους χαρακτήρες (τυχαίοι μάλλον)..
Η εντολή ανάκτηση επειδή γυρνάει διαφορετικό αριθμό στοιχείων τα περνάει στο σωρό τιμών, με την κορυφή τον αριθμό εγγραφών (αν και φέρνει μια εγγραφή, μας λέει πόσες βρήκε βάσει το ερωτήματος, και στην ουσία αυτό παραμένει ενεργό για να διαβάσουμε ξανά, και αυτός είναι ο λόγος που απαιτείται κλείσιμο). Δοκιμάστε να τρέξετε δυο φορές τo m2000.exe και πριν πατήσετε το πλήκτρο (δείτε το α$=κομ$) μπείτε από το άλλο πρόγραμμα και διαβάστε την βάση. Γίνεται γιατί η βάση είναι ανοικτή για πολλαπλή χρήση. Αυτό που δεν γίνεται είναι η εκτέλεση του Create Table, πρέπει να κλείσει πρώτα η βάση στο πρόγραμμα που ανοίχτηκε και μετά το άλλο πρόγραμμα να την σβήσει (η εντολή Βάση σβήνει τη βάση αν την βρει...δηλαδή αν θέλουμε να δουλέψουμε με το αρχείο...με στοιχεία που είχαμε δώσει..δεν θα δώσουμε τις εντολές Βάση...και Εκτέλεση όπως είναι παρακάτω).

Βάση "ΑΛΦΑ"  ' ΔΙΑΓΡΑΦΕΙ  ΤΗΝ ΒΑΣΗ ΑΝ ΒΡΕΙ ΤΟ ΙΔΙΟ ΟΝΟΜΑ
Εκτέλεση "ΑΛΦΑ", { CREATE TABLE Employees(ID autoincrement primary key,  LastName   VARCHAR(40) ,  FirstName  VARCHAR(40)  NOT NULL, MyMemo TEXT )}
Προσθήκη "ΑΛΦΑ","Employees",,"George","йваоаптаЭЭ","Γεια χαρά από Ελλάδα"
Ανάκτηση "ΑΛΦΑ", "Employees", 1,"",""
Διάβασε ΠΟΣΑ, ΑΝΑΓΝΩΡΙΣΤΙΚΟ, ΕΠΙΘΕΤΟ$, ΟΝΟΜΑ$, ΣΤΟΙΧΕΙΑ$
Τύπωσε $(4, 6),  "Βάση:"
Τύπωσε @(Στήλη(1),Γραμμή-1)
Αναφορά "ΑΛΦΑ"


Τύπωσε @(0),"ΟΝΟΜΑ:"
Τύπωσε @(Στήλη(1),Γραμμή-1)
Αναφορά ΟΝΟΜΑ$ + " " + ΕΠΙΘΕΤΟ$
Τύπωσε @(0)
Τύπωσε "ΣΤΟΙΧΕΙΑ:"
Τύπωσε @(Στήλη(1),Γραμμή-1)
Αναφορά ΣΤΟΙΧΕΙΑ$
\\ και χωρίς να κλείσει η βάση μπορεί να αλλαχθεί από άλλο πρόγραμμα, αλλά δεν αφήνει δημιουργία νέου πίνακα.
\\ δεν μπορεί να διαγραφεί η βάση όσο την χρησιμοποιούμε.
α$=κομ$
Κλείσε Βάση "ΑΛΦΑ"



Παράλληλα έφτιαξα στο EditBox στην επικόλληση να αλλάζει το σύστημα τα tab σε διαστήματα. υπολογίζοντας τις θέσεις σαν το κείμενο να ήταν με monospace γραμματοσειρά (δηλαδή ίδιου πλάτους χαρακτήρες, όπως στην courier). Μπορούμε να το αφαιρέσουμε αυτό αλλάζοντας την ιδιότητα tabwidth σε 0 (είναι σε 6 για να βάζει σε στήλες των 6 χαρακτήρων το κείμενο). Το EditBox δεν έχει στήλες. Μόνο παραγράφους. Τα F1 έως και F12 έχουν λειτουργίες και επίσης και με Shift ορισμένα. Π.χ. Shift-F3 ανοίγει εισαγωγή για εύρεση λέξης προς τα κάτω. Με F3 συνεχίζει την εύρεση στην επόμενη λέξη προς τα κάτω. Φαίνονται ορισμένα και στο δεξί μενού

Δείτε λίγο από τις δοκιμές. Ανοίγω 4 παράθυρα ως πίνακα παραθύρων ώστε να έχω κοινές συναρτήσεις για εξυπηρέτηση μηνυμάτων.







Κυριακή, 17 Απριλίου 2016

Ανοικτό και Κλειστό Αντικείμενο (Παραδείγματα)


Διαβάστε το κώδικα. Εξηγεί διάφορα θέματα για τα αντικείμενα και ειδικά τι είναι Ανοικτό και τι Κλειστό αντικείμενο (έχουν νόημα αυτές οι έννοιες στη Μ2000)
Σε κλασικές γλώσσες ένα αντικείμενο είναι ένα απλά αντικείμενο κατασκευασμένο και μια μεταβλητή κρατάει μια αναφορά σε αυτό. Στη Μ2000 τα αντικείμενα δεν είναι έτσι, τουλάχιστον όχι αυτά που λέμε Ομάδες ή Group. Δεν χρησιμοποιούμε δείκτες σε αντικείμενα. Τα ονόματα των αντικειμένων τα βλέπουμε όπως και τις μεταβλητές. Οπωσδήποτε εσωτερικά υπάρχει αναφορά, αλλά δεν μπορούν να πάρουν δεύτερη αναφορά. Τα κλειστά αντικείμενα είναι ανώνυμα, έχουν μόνο θέση, και μπορούν να μετακινηθούν, δηλαδή να φύγουν από εκεί που δημιουργήθηκαν (λέγονται και πτητικά). Π.χ. αν μια συνάρτηση επιστρέφει ένα αντικείμενο τότε αυτό είναι ανώνυμο. Αν εμείς του δώσουμε όνομα ή το συχγωνεύσουμε σε υπάρχον τότε χάνεται το ανώνυμο και έχουμε ένα ανοικτό αντικείμενο. Γίνεται να διατηρούμε και να χειριζόμαστε κλειστά αντικείμενα. Με τον τρόπο αυτό φαίνεται σαν να δουλεύουμε με δείκτες, αλλά στην ουσία είναι χειρισμός με τιμή (by value).


\\ Ανοιχτό Αντικείμενο
\\ Δημιουργία με ιδιωτικά και δημόσια στοιχεία
\\
\\ η μεταβλητή Άλφα είναι αντικείμενο τύπου Group (το λέμε Ομάδα).
\\ Ως ανοιχτό αντικείμενο κρατάει μόνο την λίστα των μελών του, μεταβλητές/πίνακες/τμήματα/συναρτήσεις
\\ Αυτή η λίστα είναι ανοιχτή. Μπορούμε να προσθέτουμε δηλαδή.
\\ Τα αντικείμενα για το λόγο αυτό δεν έχουν τύπο άλλο από τον γενικό τύπο Ομάδα ή Group


Ομάδα Άλφα {
Ιδιωτικό:
      Α, Β
Δημόσιο:
      Τμήμα ΜέθοδοςΑ {
            \\ αν έχουμε δυο αριθμούς φορτώνουμε τα Α και Β
            Αν Ταύτιση("ΑΑ") Τότε Διάβασε,
            Τύπωσε "Κατάσταση Α:",*50+
      }
      Συνάρτηση ΙδιότηταΑ {
            =
      }
}


\\ Το παρακάτω δίνει Group κα 2 ( το 2 για τις ιδιωτικές μεταβλητές- δεν δίνει αριθμό τμημάτων-συναρτήσεων)
Τύπωσε Τύπος$(Άλφα), Ομάδα.Σύνολο(Άλφα)


Άλφα.ΜέθοδοςΑ 100,30 \\ δίνει 5030
Τύπωσε Άλφα.ΙδιότηταΑ() \\ δίνει 100
Τύπωσε Γραφή$(Έγκυρο(Άλφα.Α) , {;"Έγκυρο";"Μη Έγκυρο";}) \\ Μη έγκυρο
Τύπωσε Γραφή$(Έγκυρο(Άλφα.ΙδιότηταΑ()) , {;"Έγκυρο";"Μη Έγκυρο";}) \\ Έγκυρο


\\ Στο ανοιχτό αντικείμενο  τα μέλη/στοιχεία του είναι μεταβλητές/συναρτήσεις του τμήματος.
\\ όπως και κάθε μεταβλητή/συνάρτηση που κάνουμε σε αυτό.
\\ η διαφορά είναι ότι οι συναρτήσεις/τμήματα γνωρίζουν το όνομα του αντικειμένου που ανήκουν
\\ οπότε οι μεταβλητές με μόνο τελεία στην αρχή αναφέρονται σε αυτό το όνομα
\\ η .Α αναφέρεται στην Άλφα.Α αλλά επειδή είναι ιδιωτική δεν εμφανίζεται άμεσα στο τμήμα


\\ Παρόλο που λέγονται ιδιωτικές οι Α και Β μπορούμε να βάλουμε κάτι σε αυτές
\\ με την χρήση συμπληρωματικού ορισμού.
Ομάδα Άλφα { Ιδιωτικό: Α=30, Β=50}
Άλφα.ΜέθοδοςΑ  \\1550
Δες Οκ {
      Άλφα.Α+=100
}
\\ το Οκ γίνεται ψευδές αν έχουμε λάθος στο επίπεδο του μπλοκ, εδώ έχουμε εντολή σε επίπεδο του μπλοκ
Αν όχι Οκ τότε Τύπωσε Λάθος$ \\ τυπώνει "Δεν υπάρχει τέτοια μεταβλητή



\\ Σκοπός των ιδιωτικών μεταβλητών/συναρτήσεων κ.α. είναι να μην χρησιμοποιούνται από λάθος.
\\ Μπορούμε όμως αν θέλουμε να πάρουμε τις δυο πρώτες μεταβλητές ως αναφορές στις ΑΑ και ΒΒ
Διάβασε από Άλφα, ΑΑ, ΒΒ
\\ οι ΑΑ και ΒΒ είναι αναφορές στις ιδιωτικές μεταβλητές Α και Β, αν αλλάξουν αλλάζουν και τα Α και Β
Τύπωσε ΑΑ, ΒΒ
Στη ΑΑ=500, ΒΒ=100
Άλφα.ΜέθοδοςΑ  \\ 25100
Άλφα.ΜέθοδοςΑ 500, 100 \\ 25100



\\ Αντιγραφή και Συγχώνευση Ανοικτών Αντικειμένων
\\ ένα ανοικτό αντικείμενο μπορεί να αντιγραφεί κάπου αλλου, εδώ σε ένα νέο
\\ μαζί με τις ιδιωτικές μεταβλητές.
\\ Εδώ το Άλφα έδωσε ένα κλειστό, ανώνυμο αντικείμενο το οποίο γράφτηκε ως Βήτα.
\\ το Βήτα είναι πια ανοικτό αντικείμενο όμως μεσολάβησε το κλείσιμο και η τελική αντιγραφή


Βήτα=Άλφα
Βήτα.ΜέθοδοςΑ \\ 25100
Στη ΑΑ=30, ΒΒ=50
Άλφα.ΜέθοδοςΑ \\ 1550
\\ στη Βήτα οι Α και Β είναι νέες ιδιωτικές τιμές, η αντιγραφή δίνει νέα ονόματα αλλά ίδιες τιμές
Βήτα.ΜέθοδοςΑ   \\ 251000


\\ Μπορώ να προσθέτω μεθόδους
Ομάδα Βήτα {
      Τμήμα ΜέθοδοςΒ {
      Τύπωσε "Κατάσταση Β:",*30+*10
       }
}
Βήτα.ΜέθοδοςΒ  \\ 16000
\\ μπορώ να συγχωνεύω αντικείμενο σε άλλο, αυτή είναι μια αντιγραφή σε όμοια:
Βήτα=Άλφα
Βήτα.ΜέθοδοςΒ   \\ 1400
Δες Οκ {
      Άλφα.ΜέθοδοςΒ
}
Αν όχι Οκ τότε Τύπωσε Λάθος$ \\ τυπώνει "Άγνωστο τμήμα ΑΛΦΑ.ΜΕΘΟΔΟΣΒ"
\\ τώρα θα τα κάνουμε ίσα, αφού αντιγράφουμε το Βήτα στο Άλφα,
\\  και του δίνουμε και αυτό που δεν έχει! Δηλαδή ένα αντικείμενο αναβαθμίζει ένα άλλο.
Άλφα=Βήτα
Άλφα.ΜέθοδοςΒ  \\ 1400
\\ Στη Μ2000 δεν μπορούμε να σβήσουμε μέλη του αντικειμένου
\\ Μπορούμε να φτιάξουμε πρόσκαιρα όμως, και να τα χρησιμοποιήσουμε
\\ Όπως εδώ φτιάχνουμε ένα τμήμα για μια φορά!
Ομάδα Έψιλον {
Ιδιωτικό:
      Α, Β
}
Για Έψιλον {
      Ομάδα Αυτό {
              Τμήμα Μιαφορά {
                    Διάβασε .Α,
              }
      }
      .Μιαφορά 123, 56
}
Διάβασε από Έψιλον, Εψ.Α, Εψ.Β
Τύπωσε Εψ.Α, Εψ.Β '123, 56
Δες Οκ {
      Έψιλον.Μιαφορα 10, 50
}
Αν όχι Οκ τότε Τύπωσε Λάθος$ \\ τυπώνει "Άγνωστο τμήμα ΕΨΙΛΟΝ.ΜΙΑΦΟΡΑ"


Άλφα=Έψιλον \\ του έδωσε μόνο τις τιμές Α και Β
Άλφα.ΜέθοδοςΑ  \\ 6206


\\ Μπορούμε να δημιουργούμε συναρτήσεις που δίνουν ανώνυμα τμήματα (κλειστά)
\\ Εδώ η επιστροφή του κλειστού αντικειμένου συγχωνεύεται με το Άλφα (και αλλάζει το κώδικα του τμήματος)


Κλάση ΑναβάθμισηΑ {
            Τμήμα ΜέθοδοςΑ {
                  Αν Ταύτιση("ΑΑ") Τότε Διάβασε,
                  Τύπωσε "Νέα Κατάσταση Α:",*5000+*100
            }
}
Άλφα=ΑναβάθμισηΑ()
Άλφα.ΜέθοδοςΑ  \\ 620600


\\ Μπορούμε να φτιάχνουμε ομάδες με χρήση της κλάσης και να δίνουμε αρχικές τιμές
Κλάση ΣανΤηνΆλφα {
Ιδιωτικό:
      Α, Β
Δημόσιο:
      Τμήμα ΣανΤηνΆλφα {
            Αν Ταύτιση("ΑΑ") Τότε Διάβασε,
      }
      Τμήμα ΜέθοδοςΑ {
            \\ αν έχουμε δυο αριθμούς φορτώνουμε τα Α και Β
            Αν Ταύτιση("ΑΑ") Τότε Διάβασε,
            Τύπωσε "Κατάσταση Α:",*50+
      }
      Συνάρτηση ΙδιότηταΑ {
            =
      }
}
Άλφα=ΣανΤηνΆλφα(100,50)
Άλφα.ΜέθοδοςΑ  \\ 5050


\\ όμως έχει μείνει η μέθοδοςΒ
Άλφα.ΜέθοδοςΒ  \\ 3050


Άλφα.ΣανΤηνΆλφα 30,30 \\ μπορώ τον κατασκευαστή να τον χρησιμοποιώ όποτε θέλω
Άλφα.ΜέθοδοςΑ  \\ 1530
\\ μπορούμε να δούμε τι τμήματα και τι συναρτήσεις είναι αυτό το τμήμα
\\ αν το τμήμα λέγεται Α θα δούμε τα Α.ΑΛΦΑ.ΜΕΘΟΔΟΣΑ, Α.ΑΛΦΑ.ΙΔΙΟΤΗΤΑΑ( και άλλα
\\ δηλαδή θα μας δείξει κάθε μέλος της κάθε ομάδας σαν χωριστές οντότητες και οι ομάδες χωριστά.
\\ Σε άλλες γλώσσες τα αντικείμενα είναι ένα πακέτο, εδώ είναι πιο χαλαρή η έννοια
\\ είναι μια λίστα οντοτήτων που κάνουμε προσθήκη, αντιγραφή ή και συγχώνευση.
\\ και μπορούμε να περνάμε με αναφορά σε κλήσεις τμημάτων συναρτήσεων.
\\ η δε αντιγραφή δημιουργεί το κλειστό αντικείμενο.


Τμήματα ?
Συνάρτηση ΚάνεΚάτι {
      Διάβασε Κάτι
      Κάτι.ΣανΤηνΑλφα 1000, 20
      \\ εδώ επιστρέφουμε κλειστό αντικείμενο, ανώνυμο
      \\ η ομάδα Κάτι θα χαθεί, όχι όμως το κλειστό αντικείμενο
      =Κάτι
}


Άλφα=ΚάνεΚάτι(Άλφα)
Άλφα.ΜέθοδοςΑ  \\ 50020


\\ Τώρα θα περάσουμε με αναφορά το αντικείμενο
Τμήμα ΚάνεΚάτι2 {
      Διάβασε &Κάτι
      \\ δημιουργούνται όλα τα μέλη της Άλφα με αναφορά με όνομα Κάτι
      \\ τα τμήματα μόνο μαζί με το αντικείμενο μπορούν να περάσουν
      \\ με αναφορά
      Κάτι.ΣανΤηνΑλφα 500, 10
}
ΚάνεΚάτι2 &Αλφα
Άλφα.ΜέθοδοςΑ  \\ 25010


\\ μπορούμε να περάσουμε με αναφορά μια συνάρτηση του Άλφα
\\ χωρίς να περάσουμε το αντικείμενο. (μόνο οι συναρτήσεις το κάνουν αυτό)
Τμήμα ΚάνεΚάτι3 {
      Διάβασε &ΙδιότηταΜόνο()
      Τύπωσε ΙδιότηταΜόνο() \500
}
ΚάνεΚάτι3 &Αλφα.ΙδιότηταΑ()


\\ Αυτό εδώ είναι προχωρημένο!
\\ Αντί για χρήση αναφοράς - που δημιουργεί όλα τα μέλη με αναφορά
\\ μπορούμε να χρησιμοποιήσουμε δείκτη, ως ισχνή αναφορά
Δείκτης$=Ισχνή$(Άλφα)


Τμήμα ΚάνεΚάτι4 {
      Διάβασε Δ$
      Δ$.ΣανΤηνΑλφα 150, 5
      Τύπωσε Συνάρτηση(Δ$.ΙδιότηταΑ()) \\ 500
      Για Δ$ {
            Τύπωσε .ΙδιότηταΑ() \\ 500
            .ΜέθοδοςΑ  \\ 7505
      }
      Τύπωσε Δ$ \\ αν το Άλφα είναι στο Α τυπώνει Α.ΑΛΦΑ
}
ΚάνεΚάτι4 Δείκτης$
Δείκτης$.ΜέθοδοςΑ \\ 7505
Τύπωσε Τμήμα$+".ΑΛΦΑ"=Ισχνή$(Άλφα) \\ -1 δηλαδή Αληθές
\\ το όνομα του τμήματος μπορεί να είναι Α αλλά αν το τμήμα κληθεί με Κάλεσε θα αλλαξει όνομα
\\ έτσι δεν φτιάχνουμε δείκτες με το όνομα που δίνουμε, αλλά αφήνουμε την Ισχνή$() να το δημιουργήσει
\\ την ώρα της εκτέλεσης.


\\ Κλειστό (ανώνυμο) αντικείμενο δημιουργούμε στο σωρό:
Για Αυτό {
      \\ στο μπλοκ Για Αυτό {} θα υπάρχουν οι Κάπα και Μι μετά χάνονται
      \\ βάζουμε αντίγραφα ως κλειστά αντικείμενα στο σωρό τιμών
      Βάλε Αλφα, Αλφα
      \\ διαβάζουμε τα κλειστά σε ανοιχτά
      Διάβασε Κάπα, Μι
      Κάπα.ΜέθοδοςΑ
      Μι.ΜέθοδοςΑ
}
\\ Κλειστά αντικείμενα μπαίνουν και σε πίνακα
Πίνακας Α(10)
Βάλε Άλφα, Άλφα
Διάβασε Α(0), Α(1)
\\ Μπαίνουν απευθείας
\\ Στους πίνακες δεν γίνεται ποτέ συγχώνευση, αλλά μόνο αντικατάσταση του παλιού από το νέο.
Α(3)=Άλφα
Α(0).ΜέθοδοςΑ \\ 7505
Α(1).ΜέθοδοςΒ \\ 4550
\\ Η Μ2000 δεν έχει αναφορές ξεχωριστές για στοιχεία πίνακα. Μπορεί να φτιάξει ισχνή αναφορά όμως
\\ και είναι η μόνη περίπτωση που δέχεται ανοικτό ή κλειστό αντικείμενο για πέρασμα σε τμήμα
ΚάνεΚάτι4 Ισχνή$(Α(3))


\\ Ο πίνακας αντιγράφεται με όλα τα κλειστά αντικείμενα (όχι με αναφορές στα αντικείμενα)
\\ Ο νέος πίνακας πρέπει να δηλωθεί πριν
\\ (όλοι οι πίνακες στη Μ2000 είναι δυναμικοί, μεγαλώνουν ή μικραίνουν όπως θέλουμε)
\\ μετά θα μπορούσα να βάλω Π()=Α()
Βάλε Α()
Πίνακας Π()
Διάβασε Π()
\\ δεν έχουμε συγχώνευση μεταξύ κλειστών αντικειμένων
\\ αριστερά είναι κλειστό γιατί είναι σε πίνακα
\\ δεξιά είναι κλειστό γιατί είναι επιστροφή από συνάρτηση.
\\ μόνο αν το αριστερό ήταν ανοικτό θα γίνοταν συγχώνευση
Α(3)=ΣανΤηνΆλφα(20,20)
Δες Οκ {
      Α(3).ΜέθοδοςΒ
}
Αν όχι Οκ τότε Τύπωσε Λάθος$ \\ τυπώνει "Άγνωστο τμήμα"
Α(3).ΜέθοδοςΑ \\ 1020
Π(3).ΜέθοδοςΑ \\ 7505
Α()=Π()
Α(3).ΜέθοδοςΑ \\ 7505  '' όχι μόνο αντιγράψαμε το Α(3) αλλά ότι είχε ο πίνακας Π()!
\\ Για να κάνουμε συγχώνευση πρέπει προσωρινά να δουλέψουμε στο ανοικτό
\\ με την Για {} δουλεύουμε πάντα σε ανοικτό αντικείμενο
Για Α(1) {
      Αυτό=ΣανΤηνΆλφα(20,20)
}
Α(1).ΜέθοδοςΒ \\ 800
\\ εκτός από την χρήση του δείκτη μπορούμε να περάσουμε το ανοικτό αντικείμενο
\\ θα γίνουν αλλαγές και θα κλείσει ξανά
Για Α(0) {
      ΚάνεΚάτι2 &Αυτό
}
\\ Εδώ φαίνεται σαν να είναι ανοικτό, αλλά ανοίγει άμεσα εκτελείται και μετά κλείνει.
Α(0).ΜέθοδοςΑ \\ 25010


\\ μια ομάδα μπορεί να την συλλάβει μια λάμδα συνάρτηση
\\ αυτή η άλφα θα είναι μια νέα, ένα κλειστό αντικείμενο
\\ που θα ανοίγει όταν εκτελείται η λάμδα και θα κλείνει στο πέρας αυτού
Λ=Λάμδα Άλφα -> { Άλφα.ΜέθοδοςΑ Αριθμός, Αριθμός}
Κάλεσε Λ(30,30) \\ 1530
\\ και μια λάμδα συνάρτηση μπορεί να την συλλάβει μια άλλη
Κ=Λάμδα Λ->{Κάλεσε Λ(Αριθμός,20)}
Κάλεσε Κ(100) \\ 5020
Τμήμα ΚάτιΆλλο {
      Διάβασε Λ1
      Κάλεσε Λ1(20)
}
\\ αντί να περάσω τη Κ πέρασα κατευθείαν μια Λάμδα, χωρίς όνομα!
ΚάτιΆλλο Λάμδα Λ->{Κάλεσε Λ(Αριθμός, 10)} \\ θα δώσει 1010
ΚάτιΆλλο Κ \\ 1020


\\ Μια ομάδα μπορεί να έχει λάμδα συναρτήσεις και γεγονότα αλλά αυτό σε άλλη ανάρτηση!




Στο παραπάνω παράδειγμα η Λ μπορεί να γραφτεί και έτσι:
Λ=Λάμδα Άλφα -> { Άλφα.ΜέθοδοςΑ }

Δηλαδή χωρίς το πέρασμα Αριθμός, Αριθμός
αυτό γίνεται γιατί η κλήση τμημάτων γίνεται με κοινό σωρό τιμών. Η Αριθμός παίρνει τον αριθμό από την κορυφή του σωρού. Η κλήση  της μεθόδου με δυο παραμέτρους βάζει στο σωρό δυο τιμές με πρώτη τιμή στη κορυφή αυτήν που έχουμε αριστερά δηλαδή παίρνει το διερμηνευτής τις παραμέτρους τις βάζει σε μια στοίβα FIFO (το πρώτο που μπαίνει το πρώτο θα βγει), και κάνει συγχώνευση της λίστας με τον σωρό τιμών, ως πρώτο μέρος αυτού. Αν βάλουμε το Αριθμός, Αριθμός τότε θα φτιαχτεί μια στοίβα με το πρώτο και μετά το δεύτερο του σωρού τιμών και μετά θα συγχωνευθεί με αυτόν και πάλι θα έχουμε πρώτο στοιχείο αυτό που είχαμε και δεύτερο αυτό που είχαμε. Αν λοιπόν δεν βάλουμε το Αριθμός, Αριθμός τότε αφήνουμε το σωρό όπως πρέπει να είναι!
Οι συναρτήσεις αν κληθούν με την κάλεσε "παντρεύονται" το σωρό του τμήματος που τις κάλεσε. αν  όμως κληθούν σε παράσταση τότε έχουν δικό τους σωρό.

Ο λόγος που οι συναρτήσεις και τα τμήματα δεν έχουν περιγραφή του τι παραμέτρους παίρνουν είναι απλός. Παίρνουν οτιδήποτε αποφασίσει το πρόγραμμά μας, δηλαδή ότι εμείς θέλουμε.  Επιπλέον τα τμήματα μπορούν να αφήσουν τιμές στο σωρό. Πρακτικά όλα τα τμήματα έχουν το σωρό για είσοδο και έξοδο τιμών. Στο σωρό μπαίνει οτιδήποτε εκτός από αντικείμενα που δεν αντιγράφονται όπως τα αντικείμενα Gui και τα Com.

Δικό τους σωρό έχουν τα νήματα, ενώ οι ρουτίνες έχουν τον σωρό του τμήματος ή συνάρτησης που βρίσκονται. Μια αναδρομική διαδικασία σε ρουτίνα θα έχει πρόσβαση στον ίδιο σωρό, ενώ σε συνάρτηση σε χωριστό. Σε μια συνάρτηση αν δώσουμε επιπλέον παραμέτρους θα χαθούν στο πέρας της εκτέλεσης, δεν θα βγει λάθος. Μια ρουτίνα που περιγράφει το είδος και τον αριθμό στοιχείων εισόδου, ουσιαστικά είναι ψεύτικο, περιγράφει μόνο τα πρώτα που θα λάβει υποχρεωτικά. εσωτερικά μπορεί να λάβει και άλλα! Μόνο που θα υπάρχει θέμα να δεν σηκώσουμε αυτά που βάζουμε επιπλέον. Για το λόγο αυτό στις ρουτίνες χρησιμοποιούμε για εισαγωγή ότι προκαθορίζουμε, και επίσης προσέχουμε στα τμήματα να βάζουμε ότι χρειάζονται. Με την Σωρός Νέος { } φτιάχνουμε μπλοκ με νέο σωρό. Ο παλιός μπαίνει σε αναμονή και ο νέος διαγράφεται στο πέρας. Υπάρχουν εντολές μετακίνησης στοιχείων (είναι σαν collection αλλά μπορεί να σηκωθεί στοιχείο μόνο από την κορυφή, ενώ μπορούμε να διαβάζουμε άμεσα από οπουδήποτε αν είναι αριθμός ή αλφαριθμητικό, ενώ αντικείμενο πρέπει να το σηκώσουμε από την κορυφή)