Τρίτη 29 Σεπτεμβρίου 2015

Συναρτησιακός Προγραμματισμός (Μ2000-Προχωρημένο Επίπεδο)

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

Τύπωσε (1,2,3,4,5)#Αθρ()=15
Print (1,2,3,4,5)#Sum()=15


Εδώ υπάρχει ένα πρόγραμμα που αρχικά γράφτηκε στην αγγλική (η Μ2000 έχει όλες τις εντολές και στα αγγλικά), όμως έκανα αλλαγές και ό,τι έχει μείνει στα αγγλικά...δεν είναι εντολές! Άφησα δηλαδή επίτηδες τα ονόματα στα αγγλικά για να καταλάβει κανείς ποιες είναι εντολές και ποια ονόματα (αναγνωριστικά μπορούμε να τα λέμε) που ορίζουμε εμείς.
Σε  μια γραμμή Συναρτησιακός Προγραμματισμός:
Γενικό ThisString$ : Goal "{Κάλεσε integer(25)}"  , "{qubic_of &ThisString$}" : Τύπωσε ThisString$
Παίρνουμε  τους κύβους (χ^3) των αριθμών 1...25.
Goal &ThisString
Παίρνουμε τη λίστα το ένα στοιχείο κάτω από το άλλο (αν υπήρχαν πράξεις θα εκτελούνταν πριν την εξαγωγή (Οκνηρή αποτίμηση - Lazy evaluation)

Στον Συναρτησιακό Προγραμματισμό δεν υπάρχουν αντικαταστάσεις π.χ. Χ=10.
Εδώ φτιάξαμε μια κενή ThisSring$ την βάλαμε στη Goal και τη πήραμε γεμάτη.

Η Μ2000 δεν είναι Συναρτησιακή Γλώσσα. Αυτό που κάνουμε εδώ είναι να φτιάξουμε εργαλεία που να κάνουν αυτό που δεν μπορεί η Μ2000 με τις έτοιμες εντολές. Ομοίως και η Μ2000 είναι γραμμένη με Visual Basic 6 (ο κώδικας συνοδεύεται μαζί με το εκτελέσιμο), και κάνει πράγματα που χωρίς κώδικα δεν μπορεί άμεσα να τα κάνει η Vb6.

Προσθήκη:
Εκτός από τις συναρτήσεις που ορίζουμε με την εντολή Συνάρτηση, καθώς και τις μεταβλητές που ορίζονται ως συναρτήσεις (όταν φτιάχτηκε το παρακάτω πρόγραμμα δεν υποστήριζε η Μ2000 τέτοιες μεταβλητές), υπάρχουν οι συναρτήσεις εντός αλφαριθμητικού ως ανώνυμες συναρτήσεις. 
Πχ το "{=3+5}"  αν το βάλουμε στο σωρό τιμών με την ΒΑΛΕ τότε μπορούμε να την διαβάσουμε ως αλφαριθμητικό πχ Διάβασε Α$ αλλά και εδώ αυτό μας ενδιαφέρει να την διαβάσουμε ως ορισμό συνάρτησης: Διάβασε &Α().
Ομοίως αν έχουμε μια συνάρτηση Α(), που είχαμε ορίσει πιο πριν τότε με Βάλε &Α() μπαίνει ο ορισμός της ως αλφαριθμητικό στο σωρό. Ειδικά στις συναρτήσεις ενός αντικειμένου (ομάδα) το πέρασμα στο σωρό βάζει επιπλέον στοιχεία μετά τη τελευταία αγκύλη έτσι ώστε όταν τρέξει να έχει η συνάρτηση πρόσβαση στα μέλη της ομάδας, άλλες συναρτήσεις και μεταβλητές. Με αυτό τον τρόπο περνάμε συνάρτηση ομάδας  με αναφορά στην ομάδα (αντικείμενο) κατά την κλήση άλλης συνάρτησης ή τμήματος, ακόμα και αν αυτό είναι σε άλλο αντικείμενο, χωρίς να περάσουμε όλο το αντικείμενο, δηλαδή εκθέτουμε με αναφορά σε μια λειτουργία που θα παραλάβει κάποια δεδομένα, από εκεί που εκθέτουμε, θα τα επεξεργαστεί και θα δώσει αποτέλεσμα, όσες φορές θέλουμε πριν επιστρέψει η ροή στην επόμενη εντολή. Πχ αντικ2.τμημα1 &αντικ1.συναρτ1() όπου στο 2 και στο τμήμα του 1 εκθέτουμε το αντικείμενο 1 μέσω της συνάρτησης του 1. Στην Μ2000 όλα τα αντικείμενα έχουν τον τύπο Ομάδα, ανεξάρτητα από το τι μέλη έχουν (η Μ2000 έχει και ειδικά αντικείμενα που σχετίζονται με το σύστημα COM, για τις φόρμες και για επικοινωνία με προγράμματα όπως το Word)


Η πρώτη έκδοση του προγράμματος έγινε εδώ  στο Vbforums

\\ Συναρτησιακός προγραμματισμός
\\ γραμμένος στη γλώσσα Μ2000
\\ Με F1 ο διορθωτής αλλάζει την αναδίπλωση λέξεων (τη βάζει ή τη βγάζει)
\\ Αν θέλουμε Ελληνικά στα μενού τότε γράφουμε Ελληνικά στην γραμμή εντολών
\\ ή με το Ρυθμισεις (ctrl U) βάζουμε ελληνικά εξ αρχής


\\ Γιώργος Καρράς



\****************** Τμήμα Γενικό Pack ******************************************
\* Η Pack δέχεται με αναφορά μια μεταβλητή αλφαριθμητική και βάζει ένα στοιχείο
\* που διαβάζει από το σωρό κατάλληλα διαμορφωμένο.
\* Δεν επιστρέφει τιμή στο σωρό
\**************************************************************************
Τμημα Γενικό Pack {
            Διάβασε &a$
            Αν Ειναρ Τότε Βάλε trim$(str$(αριθμός)) \\ η Ειναρ γυρίζει αληθές η κορυφή του σωρού είναι αριθμός  (για αλφαριθμητικό είναι το Εινγρ.
            Αν a$="" Τότε { a$="{"+γράμμα$+"}"
             } Αλλιώς a$=a$+", {"+γράμμα$+"}"
      }
\********************Τμήμα Γενικό Unpack********************************
\* Αυτά που είχε βάλει το Pack τα διαμορφώνει το Unpack
\*  ώστε σίγουρα να αποτελούν συναρτήσεις!
\* ο χειριστής ~ είναι ίδιος με την Like της VB6
\* το b$ ~ "*=*"  δίνει αληθές (-1) αν υπάρχει το
\* ίσον κάπου μέσα στο κείμενό του B$, αλλά όχι σε άκρες
\* το ? "=12" ~ "*=*" τυπώνει 0 (ψευδές) γιατί δεν έχει γράμματα
\* αριστερά του ίσον
\**************************************************************************
Τμήμα Γενικό Unpack {
      Διάβασε b$
      Αν b$ ~ "*=*" Τότε {
       b$="{"+b$+"}"
      } Αλλιώς b$="{= "+b$+"}"
      Βάλε b$
}     
\**********************Συνάρτηση Γενικό List$******************************
\* Δημιουργεί μια λίστα συναρτήσεων (χωρίς όνομα)
\* γενική b=10
\* a$=list$(b+12,{b**2})
\* όταν χρησιμοποιήσουμε τη λίστα το b**2  (ίδιο με το b^2)
\* θα υπολογιστεί τότε, ενώ το b+12 υπολογίζεται στη δημιουργία
\* Έτσι υλοποιούμε τις eager και lazy επεξεργασίες (evaluations).
\*************************************************************************************
Συνάρτηση Γενική List$ {
      s$=""
                        \\ ο σωρός της συνάρτησης κληρονομείται στην Pack
                        \\ έτσι οι παρέμετροι ένας προς έναν πάνε στην Pack
                        \\ με πρώτο όμως μια αναφορά την s$ για να μαζέψουμε τη λίστα.
      Αν Μέγεθος.Σωρού =0 Τότε Βάλε ""
      Για i=1 Έως Μέγεθος.Σωρού { Pack &s$ }
      =s$
}
\**************************** Συνάρτηση List.count************************************
\* Διαβάζουμε τον αριθμό στοιχείων στην λίστα
\* Η εντολή ένθεση εκτελεί ένα αλφαριθμητικό ως κώδικα
\* Με την Pack κάναμε όλη τη λίστα να έχει αλφαριθμητικά
\* (οι αγκύλες { } ορίζουν και αλφαριθμητικά εκτός από μπλοκ εντολών)
\* Η συνάρτηση έχει δικό της σωρό και στο πέρας θα διαγραφεί
\* Έτσι παίρνουμε μόνο το μέγεθος σωρού που μας ενδιαφέρει.
\**************************************************************************************
Συνάρτηση List.count {
      Διάβασε a$
      Ένθεση "Βάλε "+a$
      =Μέγεθος.Σωρού
}
\*******************************Τμήμα  Goal******************************************
\* Με παράμετρο μια αναφορά σε λίστα μας δίνει τα στοιχεία της ένα προς ένα
\* στην τρέχουσα έξοδο που είναι μέσω της Τύπωσε
\* (εξ ορισμού η τύπωσε εξάγει στην οθόνη αλλά μπορεί να αλλάξει αυτό)
\* Μπορούμε να δώσουμε μια δεύτερη παράμετρο και να αλλάξουμε το τι θα κάνουμε
\* σε κάθε στοιχείο της λίστας. Ουσιαστικά αυτό το τμήμα τρέχει τις λίστες.

\* Η εντολή Πάνω χωρίς παραμέτρους διπλασιάζει τη κορυφή
\* του σωρού τιμών (ειδική στοίβα της Μ2000)
\**************************************************************************************
Τμήμα Γενικό Goal {
      Πάνω : Διάβασε test$
      Αν Θέση(test$,"{")=1 Τότε {
            Διάβασε &a() \\ Συνάρτηση
            Σωρός νέος {
            a$=""
            Κάλεσε a()
            Αν Μέγεθος.Σωρού=0 Τότε Διέκοψε \\ η Διέκοψε (break) **σπάει** πολλά μπλοκ μαζί
            Για i=1 Έως Μέγεθος.Σωρού {pack &a$}
            }
      } Αλλιώς Διάβασε &a$
      Αν a$="" Τότε Έξοδος \\ η έξοδος **σπάει** μόνο το τρέχον μπλοκ
      Αν ταύτιση("S") Τότε { Διάβασε &redirect() } Αλλιώς Συνάρτηση redirect {Διάβασε a: Τύπωσε a}
      Σωρός νέος {
            Ένθεση "Σειρά "+a$ \\ Η εντολή σειρά βάζει στο σωρό ως FiFo  \\ Η Βάλε ως  LiFo
            Ενώ Όχι Κενό {
                  Για Αυτό { \\  δημιουργούμε ένα μπλοκ για προσωρινά ονόματα.
                        Unpack
                        Διάβασε &pp() \\ μόνο σε ονόματα που δεν υπάρχουν βάζουμε αναφορές
                        \\ εδώ έχουμε τους δυο τρόπους κλήσης συνάρτησης
                        \\ ο πρώτος δίνει νέο σωρό και περιμένει τιμή.
                   
                          Βάλε pp() \\ βάζουμε το αποτέλεσμα στο σωρό
                     
                        \\ ο δεύτερος καλεί τη συνάρτηση ως τμήμα, παρέχοντας το σωρό
                   
                          Κάλεσε redirect() \\  μη μηδενική τιμή αν επιστραφεί (π.χ. με =10) θα δώσει Λάθος
                   
                        \\\  κάποιος θα έβαζε π.χ. kk=redirect(pp()) και θα δούλευε...στο παράδειγμα
                        \\ kk=redirect(pp())     \\ σκίασε τα παραπάνω Βάλε και Κάλεσε και αποκάλυψε αυτό εδώ!
                   
                        \\ πράγματι δουλεύει για αυτά τα παραδείγματα. Αλλά με τον παραπάνω τρόπο
                        \\\ εκθέτουμε το σωρό στην redirect() που σημαίνει ότι παρέχουμε δυνατότητα να
                        \\ "διαβάσει μπροστά"...ή look ahead, να δουλεύει ανά δυο στοιχεία.
                        \\ να γιατί παραπάνω έχουμ εμια Ενώ όχι κενό { } και όχι μια Για ι=1 Έως Μέγεθος.Σωρού {}
                   
                        \\ τώρα η pp() θα διαγραφεί. Και έτσι την επόμενη φορά θα της δώσουμε αναφορά!
                  }
            }
      }


}
\********************************Τμήμα Γενικό Process*******************************
\* Δέχεται μια λίστα ή μια συνάρτηση και μια πράξη.
\* Επιπλέον διαβάζει έναν αριθμό (αυτός δίνεται στην Goal ως αποτέλεσμα
\* από κάθε συναρτηση (η λίστα της Goal είναι μια λίστα συναρτήσεων)
\* Αν με την Process περάσουμε λίστα έχουμε για κάθε αποτέλεσμα πράξη..
\* με κάθε στοιχείο στη λίστα
\**************************************************************************************
Τμήμα Γενικό Process {
      Διάβασε mylist$, op$
      Διάβασε a
      Σωρός νέος {
            Ένθεση "Σειρά "+ mylist$
            Διάβασε where$
            Ενώ Όχι Κενό {
                  Για Αυτό {
                        Unpack
                        Διάβασε &bb()
                        Ένθεση " Pack "+where$+", a"+op$+"(bb())"                       
                  }
            }
      }
}
\**************************************************************************************
\* Σε μια γραμμή Συναρτησιακός Προγραμματισμός:
\* Γενικό ThisString$ : Goal "{Κάλεσε integer(25)}"  , "{qubic_of &ThisString$}" : Τύπωσε ThisString$
\**************************************************************************************


Φόρμα 60,28 \\ οθόνη με φόρμα 60 χαρακτήρες πλάτος επί 28 γραμμές
Άδειασε   \\ ο σωρός τώρα αδειάζει από οτιδήποτε
Τύπωσε list.count("") \\ 0
Γενικό ab=10, bb=30
      a$=List$({bb+=ab : =sqrt(ab)},40,{ab**2+bb-20}, 50,60)
            Goal &a$
Γενικό sss$
      Goal &a$,  "{Pack &sss$}"  \\ δίνουμε συνάρτηση για να πάρουμε μια λίστα
            Τύπωσε sss$ \\ τυπώνουμε τη λίστα


Τύπωσε ab, bb



Γενικό add$, mul$
a$=List$(1,2,3)
Γενικό b=10, a=25


\\ Θα προσθέσουμε κάθε στοιχείο της λίστας a$ με άλλη λίστα
\\ η εξαγωγή θα πάει στο add$
\\ ουσιαστικά εδώ με το b++ σπάμε το κανόνα που θέλει να μην γίνονται αντικαταστάσεις


Goal &a$ ,  "{Process List$({&add$},{b++: =b},5,{a/2+b},20, a),{+} }"
Τύπωσε add$


\\ Θα πολλαπλασιάσουμε κάθε στοιχείο της λίστας a$ με άλλη λίστα
\\ η εξαγωγή θα πάει στη λίστα mul$
Goal &a$ ,  "{Process List$({&mul$},{b++: =b},5,{a/2+b},20),{*} }"
Τύπωσε mul$


Γενικό Result$, Result1$, Result3$
      zero$=list$(25)
      Goal &zero$, "{Διάβασε kl : Για i=1 Έως kl {Σειρά i*i : Pack &Result$}}"
      Τύπωσε Result$
 
      Goal "{Για i=1 Έως 25 {Σειρά i*i}}", "{Pack &Result1$}"
      Τύπωσε Result1$


Συνάρτηση Γενική integer { Διάβασε x : Ενώ x>0 { Βάλε x : x--}}
Τμήμα Γενικό square_of { Διάβασε &S$, x: Pack &S$, x*x}
Τμήμα Γενικό qubic_of { Διάβασε &S$, x: Pack &S$, x*x*x}


      Goal "{Κάλεσε integer(25)}"  , "{square_of &Result3$}"
      Τύπωσε Result3$


Καθαρό Result3$ 


      Goal "{Κάλεσε integer(25)}"  , "{qubic_of &Result3$}"
      Τύπωσε Result3$
      Τύπωσε "ok"


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

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

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