Σάββατο 13 Μαΐου 2017

Τμήματα, Συναρτήσεις και Μεταβλητές


Στη γλώσσα Μ2000 δεν υπάρχει ως αναγνωριστικό η Διαδικασία αλλά το Τμήμα που μοιάζει με τη Διαδικασία άλλων γλωσσών και η Συνάρτηση.
Βασική ιδέα από την πρώτη έκδοση της Μ2000 ήταν η επέκταση των λεξικών (Ελληνικού και Αγγλικού) υπό τη μορφή τμημάτων (και συναρτήσεων). 

Τα τμήματα είναι κώδικας με όνομα

Ένα τμήμα έχει ένα όνομα (σε όποια γλώσσα θέλουμε) και ένα κείμενο εντολών και μπορεί να πάρει μια λίστα ορισμάτων, τιμές δηλαδή, σε έναν σωρό τιμών, από τον οποία θα διαβάσει τις τιμές σε μεταβλητές που ορίζει τοπικά, με την εντολή Διάβασε, που θα έχουμε στο κείμενο του εντολών, και αν θέλουμε μπορεί να αφήσει τιμές αποτελέσματα στο ίδιο μέσο, τον σωρό τιμών, με μια εντολή Βάλε
Στο παράδειγμα καλούμε την Άλφα με δυο τρόπους. Στο πρώτο έχουμε βάλει στο σωρό τιμές, ενώ στο δεύτερο θα τις βάλει αυτόματα ο διερμηνευτής. Η λίστα παραμέτρων (Χ,Υ) εσωτερικά θα γραφτεί ως Διάβασε Χ,Υ και θα μπορούσαμε να το γράφαμε και εδώ, χωρίς την χρήση της απλούστευσης που δίνει η λίστα παραμέτρων.
Τμήμα Άλφα (Χ,Υ) {
      Τύπωσε Χ*2, Υ**2
}

Βάλε 10, 5
Άλφα            \\ 10,100
Άλφα 5, 10 \\  10, 100

Αντικείμενο Εκτέλεσης

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

Δεν είναι αυτό που φαίνεται!

Ενώ λοιπόν έχουμε με μια απλή ματιά σε ένα πρόγραμμα τμήματα και συναρτήσεις, και μέσα σε αυτά τμήματα και συναρτήσεις, ουσιαστικά αυτό που βλέπουμε είναι οδηγίες που θα δει και ο διερμηνευτής και όχι μια απεικόνιση του πώς θα διαταχθεί η μνήμη κατά την εκτέλεση.
Ο κώδικας δεν θα πάρει "ουσία", αν δεν κληθεί και δεν οδηγηθεί σε ένα  αντικείμενο εκτέλεσης. Όταν βλέπει ορισμούς τμημάτων/συναρτήσεων ο διερμηνευτής απλά τους βάζει σε μια λίστα και ίσως βάζει προθέματα κατάλληλα για να ξεχωρίσει σε ποιο ανήκει το καθένα. Μόλις καλέσουμε κάποιο από αυτά ένα νέο αντικείμενο εκτέλεσης δημιουργείται, με γονικό το προηγούμενο. 
Στη γραμμή εντολών βρισκόμαστε στο αρχικό αντικείμενο εκτέλεσης, όπου ο κώδικας που εκτελείται είναι η εισαγωγή εντολών και η άμεση εκτέλεσή τους.
Ο βασικός λόγος ύπαρξης των αντικειμένων εκτέλεσης είναι ότι καλύπτουν την εκτέλεση νημάτων, δηλαδή μέρη του τμήματος μπορούν να τρέχουν σε άλλα αντικείμενα εκτέλεσης, και ενώ έχουν το ίδιο όνομα τμήματος έχουν άλλο αριθμό νήματος. Δυο νήματα θα έχουν διαφορετικές στατικές μεταβλητές, και ας έχουν αυτές το ίδιο όνομα, ενώ θα διαβάζουν κανονικά τις μεταβλητές του τμήματος και αν θέλουν θα αλλάζουν τις τιμές τους! Επίσης ένα νήμα μπορεί να γράφει σε ένα επίπεδο (layer) στη κονσόλα (η κονσόλα έχει 32 επίπεδα πάνω από το βασικό επίπεδο και ένα από κάτω), ή σε μια φόρμα του γραφικού περιβάλλοντος (παράθυρο πάνω από την κονσόλα - η κονσόλα μπορεί να μπει σε ελαχιστοποίηση, ανεξάρτητα από τα παράθυρα που φτιάχνουμε). Καθορίζεται το αντικείμενο εκτέλεσης στη φάση που ορίζουμε το νήμα, δηλαδή παίρνει ένα δείκτη από το τρέχον αντικείμενο. Όταν συμβαίνει ένα γεγονός σε μια φόρμα χρήστη και υπάρχει συνάρτηση εξυπηρέτησης στο τμήμα (οι φόρμες γνωρίζουν ποιο αντικείμενο της δημιούργησε) τότε αυτόματα δημιουργείται ένα αντικείμενο εκτέλεσης με κώδικα από το τμήμα και εκτελείται, ανεξάρτητα από το τι εκτελείται σε άλλα νήματα. Στο παράδειγμα με τα 30 παράθυρα και τα 30 νήματα φαίνεται αυτή η λειτουργία. Εκεί ζωγραφίζουμε σε οποιαδήποτε παράθυρο με το ποντίκι. ή επιλέγουμε πλήκτρα, ενώ τα νήματα σχεδιάζουν γραμμές σε όλα τα παράθυρα. (το γραφικό περιβάλλον της Μ2000 είναι ιδιωτικό, δικό της, αν και ο κώδικας είναι ελεύθερος για σπουδή και όποια άλλη χρήση, και γράφτηκε αρχικά μόνο για τις φόρμες διαλόγου, ώστε να είναι Unicode, και μετά την "ανακάλυψη" του αντικειμένου Γεγονός φάνηκε πώς μπορούσε να συνδεθεί η εκτέλεση του κώδικα με τις φόρμες/παράθυρα).

Κανένας έλεγχος στη κλήση - Έλεγχος στο διάβασμα από το σωρό.

Λογικά όταν καλούμε σε μια γλώσσα μια διαδικασία, αυτή βάζει κάπου τα ορίσματα και το πρώτο μέλημα του κώδικα της διαδικασίας είναι να πάρει τα στοιχεία αυτά, χωρίς να τα πάρει, δηλαδή να τα πάρει έμμεσα! Δηλαδή έχει ορίσει τις μεταβλητές του τοπικά να έχουν μια θέση από την θέση (λέγεται Offset) της κορυφής της στοίβας εκτέλεσης. Έτσι μια Α στον κώδικα είναι ο δείκτης της Α στην θέση SP+8 (stack pointer, κατεβαίνει προς τα κάτω, άρα οι τιμές είναι από κει και πάνω, σε μεγαλύτερες διευθύνσεις). Άν έχουμε περάσει μια τιμή από έκφραση τότε η Α θα πάρει πάλι το δείκτη που θα δείχνει μια πρόχειρη τιμή. Σε μερικές περιπτώσεις μπορεί να έχουμε άμεσα την τιμή στη στοίβα εκτέλεσης. Αυτά όμως δεν συμβαίνουν με τον διερμηνευτή. 
Ο διερμηνευτής έχει ένα σωρό τιμών και βάζει ή διαβάζει τιμές από αυτόν, αφαιρώντας τις. Αυτός είναι ανεξάρτητος από την στοίβα εκτέλεσης. Μπορούμε να τα κάνουμε σαλάτα όπως λέμε και θα βγει λάθος και θα γυρίσει ο διερμηνευτής στη γραμμή εντολών. Με μια εντολή Σωρός βλέπουμε τις τιμές που έχει (το ίδιο βλέπουμε και από τη φόρμα Έλεγχος που ανοίγει με την εντολή Δοκιμή).

Εδώ λοιπόν είναι θέμα του τμήματος (άρα του προγραμματιστή) το τι θα κάνει με ότι του δώσουμε. Αν θέλουμε ελέγχουμε τι έχουμε στο σωρό τιμών, σταδιακά, και ανάλογα καθορίζουμε τι θα κάνει το τμήμα σε κάθε περίπτωση. Σε άλλες γλώσσες έχουμε διαφορετικές διαδικασίες/συναρτήσεις με κοινό όνομα αλλά με διαφορετικές παραμέτρους σε σχέση με τον τύπο τους, ενώ εδώ πετυχαίνουμε το ίδιο σε ένα τμήμα. Ίσως αυτό να μην βολεύει κάποιους, γιατί θα έλεγε κανείς ότι βάζει κάτι σαν "έμπλαστρο" στο κώδικα που με αυτό θα κάνει και κάτι άλλο, αλλά στην ουσία το κάτι άλλο θα το βάλουμε μέσα σε ένα χώρο, σε κάποιο φάκελο με αρχεία, γιατί διαφορετικά θα υπάρχει περίπτωση αν είναι σε ξεχωριστό φάκελο (ή μετά από αντιγραφή/μετακίνηση) να κάνουμε χρήση της λάθους έκδοσης, και το ένα η μία να είναι νέα έκδοση και τη άλλη παλιά. Δεν υπάρχει τίποτα που να μας λέει ποιο είναι ποιο εκτός από σημειώσεις μέσα σε κάθε έκδοση, αλλά αυτό το ψάχνεις αφού γίνει η πατάτα! Άλλος λόγος που "Αρέσει" αυτό το σπάσιμο είναι ότι το κάθε κομμάτι το αναλαμβάνει άλλος! Δηλαδή η παραγωγικότητα. Και στη Μ2000 θα μπορούσε κανείς να κάνει αυτό:

Ομάδα Άλφα {
Ιδιωτικό:
      Τμήμα Περίπτωση1 (Α$, Β$) {
            Βάλε Τιμή(Α$)+Τιμή(Β$)
      }
      Τμήμα Περίπτωση2 (Α, Β) {
            Βάλε Α+Β
      }
Δημόσιο:
      Συνάρτηση Κάτι {
            Αν Ταύτιση("ΓΓ") τότε {
                  .Περίπτωση1
            }  Αλλιώς .Περίπτωση2
            =Αριθμός
      }
}
Τύπωσε Άλφα.Κάτι("10","20"), Άλφα.Κάτι(5,6)

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

Αν το παραπάνω πρόγραμμα το είχαμε σε ένα τμήμα Α τότε μια εντολή


Τύπωσε Άλφα.Κάτι("10",5)
θα δώσει αυτό:
Λείπει αριθμός από το σωρό στο τμήμα  Α[1].ΑΛΦΑ.ΚΑΤΙ().Α.ΑΛΦΑ.ΠΕΡΙΠΤΩΣΗ2

Το Περίπτωση2 έχει ακριβώς αυτό το μακαρόνι για όνομα τη δεδομένη στιγμή που έτρεξε. Το [1] στο Α δηλώνει στο πρώτο βάθος κλήσης. Αν είχε ας πούμε το 20 θα σήμαινε ότι έχουμε φθάσει σε 20 κλήσεις βάθος. Οι συναρτήσεις κρατάνε το βάθος και στο όνομα λοιπόν, και από εκεί καλέσαμε το .Περίπτωση2 στο οποίο του μπήκε η ισχνή αναφορά του αντικειμένου, το Α.ΑΛΦΑ. και πράγματι ο κώδικας του Περίπτωση2 είναι στο Α.ΑΛΦΑ.ΠΕΡΙΠΤΩΣΗ2. Αν το αντικείμενο ήταν σε πίνακα τότε η ισχνή αναφορά θα είχε το πρόσκαιρο όνομα που θα έβαζε ο διερμηνευτής κατά το "άνοιγμα" του "κλειστού" ή ανώνυμου αντικειμένου. Παρατηρήστε ότι άλλο είναι η ισχνή αναφορά για το που βρίσκεται η τιμή σε κάτι (το τμήμα έχει τιμή τον κώδικά του), και άλλο το όνομα του τρέχοντος τμήματος.  Οι μεταβλητές Α$ και Β$ θα είναι οι Α.ΑΛΦΑ.ΠΕΡΙΠΤΩΣΗ1.Α$ και Α.ΑΛΦΑ.ΠΕΡΙΠΤΩΣΗ2.Β$ αν και εδώ δεν θα φανούν με το Λίστα στη Περίπτωση1 γιατί είναι ιδιωτική. Μπορούμε να το αφαιρέσουμε και να βάλουμε το Λίστα στο κώδικα του Περίπτωση1. Αυτές όμως θα υπάρχουν μόνο όσο τρέχει το Περίπτωση1, μετά θα διαγραφούν.
Δείτε επίσης ότι και οι δυο Περιπτώσεις βάζουν μια τιμή στο σωρό και η συνάρτηση Κάτι παίρνει την τιμή ως Αριθμός (αυτή είναι μια μεταβλητή μόνο για ανάγνωση και τραβάει τον αριθμό από την κορυφή του σωρού, ενώ αν δεν υπάρχει τιμή βγάζει λάθος). Η Περίπτωση2 θα γραφόταν και έτσι:
Βάλε Αριθμός+Αριθμός
χωρίς μεταβλητές Α και Β
Και από την γραμμή εντολών μπορούμε να το δούμε αυτό. Πρώτα θα αδειάσουμε το σωρό (δεν είναι απαραίτητο):
Άδειασε
Βάλε 1, 2
Βάλε Αριθμός+Αριθμός
Η εντολή Σωρός μας δείχνει τα στοιχεία του και βλέπουμε το 3
Σωρός
Τώρα θα την πετάξουμε
Πέτα 
Σωρός
Ο σωρός είναι άδειος
Τύπωσε Κενό
        -1
Το -1 είναι το Αληθές (ή Αληθής)
Τύπωσε Αληθής Και Αληθής, Ψευδές Ή Αληθές, Αληθές Από Αληθές
Τα Και, Ή και Από είναι τα And, Or, Xor
Υπάρχει και το Όχι (και το Δεν) που κάνει αντιστροφή (Not)
Τύπωσε Αληθές Και Όχι Ψευδές

Οι μεταβλητές μπορούν να είναι αριθμοί, αλφαριθμητικά, αντικείμενα. Ότι ορίζουμε σε ένα τμήμα θα υπάρχει ως όνομα όσο το τμήμα εκτελείται, δηλαδή θεωρείται προσωρινό για το τμήμα. Ακόμα και γενικές μεταβλητές μπορούν να οριστούν σε ένα τμήμα, αλλά θα πάψουν να υπάρχουν στο πέρας εκτέλεσής του. 
Σκοπίμως στο επόμενο μέρος δεν έγραψα κάποιο πρόγραμμα αλλά δίνω μερικά στοιχεία σε διάγραμμα για να δει ο αναγνώστης πως απεικονίζονται τα τμήματα/συναρτήσεις στο διερμηνευτή. Από την γραμμή εντολών ή Επίπεδο 0 μπορούμε να γράφουμε τμήματα με τη Σ (Συγγραφή) και αυτά θα είναι γενικά, που σημαίνει ότι μπορούν να κληθούν από οπουδήποτε εκτός από τα ίδια, γιατί σε απλές κλήσεις η Μ2000 απαγορεύει την κλήση τμήματος στον εαυτό του. Οι προχωρημένες κλήσεις είναι ενδιαφέρουσες και αυτές αλλά θα τις δούμε σε άλλη ανάρτηση.
Το ότι γράφουμε γενικά τμήματα στο Επίπεδο 0 βοηθάει στο να έχουμε φορτωμένα πολλά προγράμματα, όπου το καθένα ως τμήμα εφαρμόζει μια λύση. Με το Σ Α ως Β αλλάζουμε το όνομα του τμήματος Α με το όνομα Β. Μπορούμε δηλαδή να έχουμε δυο τρεις εκδόσεις ενός τμήματος και να βλέπουμε τις διαφορές. Άλλος τρόπος είναι να φορτώνουμε ένα τμήμα με την Φόρτωσε μέσα στο κώδικα ενός τμήματος. 
Δείτε ένα παράδειγμα όπου εμφανίζεται ο ένας από τους δυο τρόπους φόρτωσης γενικών τμημάτων. Ας φτιάξουμε απευθείας σε αρχείο ένα τμήμα (το ανοίγει ο διορθωτής από το δίσκο, αν δεν υπάρχει το φτιάχνει, και στο τέλος το αφήνει εκεί, δεν το φορτώνει). Αρχικά θα σβήσουμε το περιβάλλον από τα προγράμματα/τμήματα με την Νέο. Προσοχή έχει σημασία το όνομα του αρχείου αν έχει ή όχι τόνο. Στα ονόματα αρχείων δεν γίνεται αλλαγή στους τόνους, οπότε αν περαστεί με τόνο θα πρέπει να ζητηθεί με τόνο.
Νέο
Σ "γενικο.gsb"
Γράφουμε:
Τμήμα Γενικό Β {
     Τύπωσε "Είμαι γενικό τμήμα"
}
πατάμε Esc και έχει σωθεί στο φάκελο του χρήστη (Δώστε την εντολή Κατάλογος να τον δείτε)
Τώρα φτιάχνουμε το Α απευθείας στο περιβάλλον
Σ Α
Γράφουμε:
Φόρτωσε γενικο
Τμήματα ?
Β
πατάμε Esc
Α
εκτελείται το πρόγραμμα και βλέπουμε ότι υπάρχει το Β ως γενικό
Τμήματα ?
Τώρα βλέπουμε ότι υπάρχει μόνο το Α (το Β φορτώθηκε και μετά διαγράφτηκε)
Τώρα θα δοκιμάσουμε με Σ "γενικο.gsb" διαγράφοντας το Γενικό.
Τρέχουμε πάλι το Α και βλέπουμε ότι δεν έχει πρόβλημα τρέχει το Β αλλά τώρα το Β εμφανίζεται ως Α.Β  δηλαδή τοπικό στο Α
Τώρα θα αλλάξουμε το Α ώστε να γίνει γενικό, με Σ Α ανοίγουμε το Α και βάζουμε πριν την πρώτη γραμμή ως Θέσε Φόρτωσε γενικο
Η εντολή Θέσε παίρνει ότι ακολουθεί στη γραμμή (παράγραφο) και το στέλνει στη γραμμή εντολών, σαν να το γράφαμε στην γραμμή εντολών, δηλαδή πρόσκαιρα γυρνάμε στο επίπεδο 0.
Τώρα τρέχει η Α και βλέπουμε το Β ως γενικό. Η διαφορά των δυο μεθόδων είναι στην περίπτωση που υπάρχει ήδη μια γενική Β, ότι με την λέξη Γενικό στο τμήμα θα φτιαχτεί νέα Β ενώ με το δεύτερο τρόπο θα γίνει τροποποίηση της παλιάς Β.
Η εντολή ΣΣυγγραφή) δουλεύει και μέσα σε τμήμα. Μπορούμε δηλαδή να φτιάξουμε τμήμα την ώρα που τρέχει τμήμα! Επειδή όμως αν έχουμε κενό ορισμό η Σ δεν δημιουργεί τμήμα, το καλούμε μέσα σε μια Δες { } για να εξαφανίσει το τυχόν λάθος.
Η Θέσε χρησιμεύει για αν αλλάξει ταχύτητα εκτέλεσης ο διερμηνευτής. Θέσε Αργά ή Θέσε Γρήγορα (νορμάλ) ή Θέσε Γρήγορα ! (ό,τι πιο γρηγορο). Οι διαφορές τους έχουν να κάνουν με το πώς αφήνουν χρόνο στο σύστημα. Η αργά δεν έχει μεγάλες διαφορές αν δεν υπάρχει φόρτος στο σύστημα. Η γρήγορα ! έχει λιγότερες ανανεώσεις και ενδέχεται σε επαναλήψεις να μην πιάνει το ESC. Μπορούμε όμως με μια Αν Πατημένο(27) Τότε Έξοδος να ελέγχουμε ειδικά. Η Πατημένο() ή Keypress() κοιτάει άμεσα το πλήκτρο (εφόσον η εφαρμογή είναι στο προσκήνιο, δεν δουλεύει ως Keylogger)
Παρακάτω είναι μια "επανάληψη" βάσει του σχήματος.
Στην εικόνα που ακολουθεί, έχουμε τα τμήματα Άλφα, Βήτα και τη συνάρτηση Κάπα (ή τα γράψαμε άμεσα με το διορθωτή, ή τα φορτώσαμε από το δίσκο στην γραμμή εργασιών), στο επίπεδο 0 (είναι γενικά). Καλούμε το Άλφα 10, 5 με τον απλό τρόπο, τα 10 και 5 ως τιμές θα μπουν πρώτα στο σωρό τιμών και θα κληθεί το Άλφα. Στο άλφα θα διαβάσουμε τις τιμές στα Χ, Υ (θα βγουν από το σωρό τιμών).

 
Μέσα στο κώδικα του Άλφα ορίζουμε ένα τμήμα Δέλτα. Αυτό μπορεί να θεαθεί μόνο από το Άλφα, και εφόσον ο ορισμός δοθεί (θα μπορούσε να εκτελεστεί κώδικας πριν τον ορισμό και να κάνουμε έξοδο με την Έξοδος). Όταν το Άλφα τερματίσει, θα διαγραφεί ο ορισμός του Δέλτα. Η Κλήση του Δέλτα από το Άλφα θα γίνει με παροχή του σωρού που έχει ήδη το Άλφα (και ήταν αυτό που του δόθηκε από την αρχή). Εμείς γράφουμε το Δέλτα 500 αλλά ο διορθωτής θα δώσει όλο το σωρό, και το 500 στη κορυφή του. Οφείλει ο κώδικας της Δέλτα να τραβήξει μόνο ένα. Θα μπορούσαμε όμως να βάλουμε τιμές στο σωρό στη Δέλτα και στην επιστροφή, η Άλφα να τις πάρει (εφόσον αυτό θέλουμε).
Επειδή η Συνάρτηση Κάπα είναι γενική (στο επίπεδο 0) μπορεί να κληθεί και από το τμήμα Βήτα και από το τμήμα Δέλτα. Σε κάθε περίπτωση, με κανονική κλήση (σε αριθμητική παράσταση), η συνάρτηση θα ξεκινήσει με δικό της σωρό τιμών, και στο τέλος θα τον πετάξει. Ακόμα και αν βάζαμε πέντε ορίσματα μετά τα δυο που ζητάει, δεν θα έβγαινε λάθος, απλά οι τιμές θα έμεναν στο σωρό τιμών της συνάρτησης και θα διαγράφονταν. Όμως αν θέλουμε μπορούμε με εντολές να δούμε τι έχει ο σωρός, πόσα και τύπος είναι το καθένα. Αυτό μπορούμε να το κάνουμε από το πρώτο όρισμα που παρέχουμε στην Άλφα, αρκεί πριν την Διάβασε να βάλουμε τη λογική για την εξέταση του σωρού και τι κάνουμε μετά. 
Επιγραμματικά εδώ θα δοθεί μόνο το πώς δίνουμε μεταβλητές με αναφορά. Οι αριθμητικές, αλφαριθμητικές όπως και οι ομάδες και οι πίνακες (ονόματα με παρενθέσεις) περνούν με τιμή (αν και τα δυο τελευταία είναι αντικείμενα ο διερμηνευτής τα θεωρεί ως τιμές). Οι πίνακες όσο βρίσκονται στο σωρό δύναται να αλλάξουν, είναι με δείκτη σε αντικείμενο, αλλά στο διάβασμα θα έχουν την εικόνα της στιγμής που διαβάστηκε σε νέο αντικείμενο. Κατά την κλήση τμήματος δεν προλαβαίνει ο πίνακας να αλλάξει, εκτός αν το θέλουμε επίτηδες (πχ το αλλάζει κάποιο γεγονός από μια φόρμα).
Το παράδειγμα εδώ μοιάζει με αυτό της κλήσης σε τμήμα, θα βάλουμε  τιμή και θα πάρουμε τιμή, και απλά δείχνει το πέρασμα με τιμή (υποθέστε ότι η Διάβασε γίνεται σε ένα τμήμα και επίσης η Βάλε έγινε κατάλληλα στην κλήση του τμήματος).
Α=10
Βάλε Α
Διάβασε Β
Τύπωσε Β
Β+=10
Τύπωσε Α, Β
Τώρα θα περάσουμε με αναφορά (ο διερμηνευτής βάζει μόνο μια αναφορά σε νέο όνομα, όχι σε παλιό). Οπότε τα παρακάτω τα γράφουμε σε άλλο τμήμα.
Α=10
Βάλε &Α
Διάβασε &Β
Β+=10
Τύπωσε Α, Β
Και τα δύο έχουν την ίδια τιμή.
Τώρα θα κάνουμε κάτι πιο ζόρικο. Θα περάσουμε έναν πίνακα (σβήνουμε το παλιό κώδικα)
Πίνακας Α(10)=1
Τύπωσε Α() 
Βάλε &Α() : Διάβασε &Β()
Β(3)=100
Τύπωσε Α(3)
Τώρα θα κάνουμε κάτι ακόμα πιο ζόρικο. Θα περάσουμε συνάρτηση (σβήνουμε το παλιό κώδικα)
Συνάρτηση Α (χ) {=χ**2}
Τύπωσε Α(10)
Βάλε &Α() : Διάβασε &Β()
Τύπωσε Β(10)
Να ξεκαθαρίσω εδώ ότι το &Α ή το &Α() είναι αλφαριθμητικό. Δηλαδή στο σωρό μπαίνει η ισχνή αναφορά της μεταβλητής, και στις συναρτήσεις μπαίνει ο κώδικας της συνάρτησης μέσα σε αγκύλες. Ο σωρός τιμών κατασκευάστηκε για να παίρνει τιμές (στις αρχικές εκδόσεις δεν μπορούσε να πάρει αντικείμενα). Πριν από την "ανακάλυψη" του πώς θα μπουν τα αντικείμενα, είχε φτιαχτεί ο τρόπος των αναφορών.  
Α=100
Τύπωσε &Α
θα πάρουμε την ισχνή αναφορά του Α. Μόνο η Διάβασε ξέρει τι να κάνει με τις ισχνές αναφορές, και αυτό όταν ζητάμε κάτι τέτοιο. Δηλαδή πρέπει στη Διάβασε όταν ζητάμε αναφορά να έχουμε το & μπροστά από το όνομα. (και αυτό για μια φορά μόνο, μέχρι να τελειώσει το τμήμα, ή το μπλοκ που κάνει προσωρινούς ορισμούς- δεν θα το δούμε και αυτό εδώ)
Η αναφορά συνάρτησης δεν είναι πραγματική αναφορά αλλά αντιγραφή κώδικα. Αυτό συμβαίνει γιατί μας ενδιαφέρει να περάσουμε συναρτήσεις, σαν να περνάμε κώδικα σε τμήμα/συνάρτηση. Σε άλλες γλώσσες είναι σαν να περνάμε δείκτη στη συνάρτηση. Πράγματι στις συναρτήσεις ομάδων περνάει και μια ισχνή αναφορά στην ομάδα οπότε καθώς τρέχει ο κώδικας της συνάρτησης μιας ομάδας,του τμήματος έστω Α στο τμήμα έστω Β μπορούν να αλλάζουν τιμές στην ομάδα, ή να καλούνται τμήματα στην ομάδα (αυτό έχει μια έννοια της κλήσης προς τα πίσω, σαν αυτό που λέμε CallBack, και είναι υποσύνολο της μεγάλης λύσης που δίνει το αντικείμενο Γεγονός)
Μπορούμε λοιπόν να ορίσουμε μια ΆλλαξεΤιμή να αλλάζει τιμές από δυο  μεταβλητές Α και Β (υπάρχει η Άλλαξε που το κάνει χωρίς τα & αλλά εδώ θα το δούμε ως παράδειγμα)
Τμήμα ΆλλαξεΤιμές (,) {
      Κ=Χ
      Χ=Υ
      Υ=Κ
}
Α
=10
Β
=5
Τύπωσε Α, Β
ΆλλαξεΤιμές &Α
,
Τύπωσε Α, Β
\\ η κανονική εντολή
Άλλαξε Α, Β
Τύπωσε Α, Β



Εδώ φαίνεται ο τρόπος περάσματος με αναφορά και ο τρόπος CopyInCopyOut ή όπως το γράφω με αντιγραφή εισόδου εξόδου.
Τμήμα Με_Αναφορά (, ) {
      Α++ : Β++
}
Τμήμα Με_Αντιγραφή_Εισόδου_Εξόδου (, ) {
     Στη Α1=Α, Β1=Β
     Α1++
     Β1++
     Στη Α=Α1, Β=Β1
}
Χ=0
Με_Αναφορά &Χ,
Τύπωσε Χ \\ 2
Χ=0
Με_Αντιγραφή_Εισόδου_Εξόδου &Χ,
Τύπωσε Χ \\ 1




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


Ομάδα Άλφα {
      Χ=100
      Μ=λάμδα Ν=10->{
            \\ η Ν είναι "κλείσιμο" στην Μ
            Ν+=10
            =+Ν
            ++
      }
}
Τύπωσε Άλφα.Μ()
Ένωσε Ισχνη &Άλφα.Μ() στο ΜΜ()
Τύπωσε ΜΜ()
Τμήμα ΚΛΜ (&Μ()){
      Τύπωσε Μ()
}
ΚΛΜ &ΜΜ()
ΚΛΜ &Άλφα.Μ()
ΚΛΜ &Άλφα.Μ()
ΚΛΜ &Άλφα.Μ()

Τμήμα ΝΞΟ (){
      Τύπωσε Ζ()
}
\\ Αποτυχία περάσματος λάμδα ομάδας με αναφορά
\\ διότι δεν έχει αναφορά στην ομάδα, και το .Χ είναι άγνωστο
Δες {
      ΝΞΟ &Αλφα.Μ
}


Στο δεύτερο πρόγραμμα βλέπουμε ότι δίνουμε την λάμδα ως παράμετρο, χωρίς καν όνομα. Στο τμήμα Κ βάζουμε τη λάμδα στο σωρό, με το όνομά της (χωρίς το όνομα με τις παρενθέσεις). Την διαβάζουμε σε μια μεταβλητή και αυτή τώρα θα έχει και όνομα με παρενθέσεις. Η τιμή της Χ συνεχίζει να αυξάνεται. Παρόλο που την περνάμε ως τιμή τη λάμδα, έχει μαζί της το κλείσιμο, τη Χ.
Αλλάζουμε τον ορισμό της Κ. Σε περίπτωση που ένα τμήμα υπάρχει...δεν κάνει κάτι ο διερμηνευτής με τυχόν λίστα παραμέτρων και βγαίνει λάθος, αλλά εδώ απλά δώσαμε σε μια διάβασε το τι θέλουμε (ίσως σε άλλη αναθεώρηση διορθωθεί, ίσως όχι, το σκέφτομαι ακόμα, το αφήνω σαν ασφάλεια, για να μην αλλάζει κάτι από λάθος)
Στο δεύτερο ορισμό περνάμε την λάμδα ως αναφορά συνάρτησης. Και πάλι δουλεύει και συνεχίζει να αυξάνει το Χ
Στο τρίτο ορισμό περνάμε την λάμδα με αναφορά ως μεταβλητή. Και πάλι δουλεύει και συνεχίζει να αυξάνει το Χ

Όπως είδαμε σε ομάδες όπου η λάμδα διαβάζει/αλλάζει μεταβλητή ομάδας ο δεύτερος τρόπος, με πέρασμα ως αναφορά συνάρτησης δίνει τα στοιχεία που χρειάζεται ο διερμηνευτής για να εκτελέσει σωστά τον κώδικα.

Τμήμα Κ (Μ, Ν) {
      Τύπωσε Μ(), Ν
      Τύπωσε Μ(), Ν
      Βάλε Μ
}
Κ
λάμδα Χ=1 -> {=Χ:Χ++}, 10
Διάβασε ΜΜ
Τύπωσε ΜΜ()
\\ νέος ορισμός  \
\ σε νέους ορισμούς δεν δέχεται ο διερμηνευτής λίστα παραμέτρων,
Τμήμα Κ {
      Διάβασε &Μ(), Ν
      Τύπωσε Μ(), Ν
      Τύπωσε Μ(), Ν
}
Κ &ΜΜ()
, 20
Τμήμα Κ {
      Διάβασε, Ν
      Τύπωσε Μ(), Ν
      Τύπωσε Μ(), Ν
}
Κ &ΜΜ
, 20


Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου

You can feel free to write any suggestion, or idea on the subject.