Πέμπτη 20 Απριλίου 2017

Συναρτησιακός Προγραμματισμός ΙΙ (προσθήκη)

Σε αυτό το παράδειγμα χρησιμοποιώ το αντικείμενο σωρός, μια ειδική στοίβα που μπορεί να έχει μεγάλο αριθμό στοιχείων (παίρνει οτιδήποτε, αριθμό, αλφαριθμητικό, αντικείμενα), και είναι ίδιο ακριβώς με το σωρό τιμών που χρησιμοποιούν τα τμήματα και οι συναρτήσεις για να πάρουν τιμές.
Η ListLit έχει επιστροφή μόνο το [] και αυτό είναι αναγνωριστικό και επιστρέφει τον τρέχον σωρό τιμών (στην υλοποίηση ο "παλιός" ή τρέχον γίνεται η επιστροφή και στη θέση του μπαίνει ένας νέος άδειος). Οι σωροί είναι συνδεδεμένες λίστες. Η Κάθε() ή Each() μπορεί να χειριστεί ένα τέτοιο αντικείμενο, χωρίς να σηκώσει στοιχεία (ενώ κανονικά ένα αντικείμενο σωρού διαβάζεται από την κορυφή), αλλά εσωτερικά κάνει χρήση ενός index, δείκτη θέσης, και διαβάζει κάθε φορά το επόμενο στοιχείο. Μόλις το index περάσει το τέλος τότε στο While θα βγει εκτός. Η τιμή του επαναλήπτη δίνεται και με τον τελεστή ^ αμέσως μετά το όνομα (x1^), αλλά εδώ χρησιμοποιούμε το stackitem(x1) όπου αν δεν είχαμε επαναλήπτη αλλά το x (ως stack αντικείμενο) θα παίρναμε κάθε φορά την κορυφή (χωρίς να την πετάγαμε, το πέταγμα το κάνει η Διάβασε). Τώρα η x1 δίνει αυτό που λέει ο δείκτης. Μπορούμε να έχουμε για το ίδιο αντικείμενο πολλούς επαναλήπτες, και καθένας έχει το δικό του index δηλαδή το δικό του δρομέα (κέρσορα).
Ο επαναλήπτης παίζει και ανάποδα αν θέλουμε πχ. Each(x,-1,1) θα πάει από το τέλος στην αρχή)
Στους σωρούς το Data (Σειρά) βάζει στο τέλος, ενώ το Push (Βάλε) βάζει στην κορυφή. Το Διάβασε διαβάζει πάντα από την κορυφή. Το Match() ή Ταύτισε() διαβάζει ένα αλφαριθμητικό με γράμματα για τύπους και αν υπάρχει ο αριθμός γραμμάτων ως αριθμός στοιχείων, και ταυτίζονται οι τύποι γυρνάει -1, και έτσι μπορούμε να κάνουμε ταυτοποίηση τύπου στο σωρό τιμών (η Μ2000 αν βρει λάθος τύπο βάσει αυτού που ζητάμε θα βγάλει λάθος), και αυτό το κάνουμε για να επιλέγουμε διαφορετικούς τύπους ορισμάτων στην ίδια συνάρτηση/τμήμα.

Οι λάμδα συναρτήσεις περνάνε όπως έχουν (Χωρίς παρενθέσεις) σαν μεταβλητές, ενώ με παρενθέσεις καλούμε την συνάρτηση εσωτερικά. Μπορούν να έχουν κλεισίματα, οτιδήποτε. Αν δώσουμε αντικείμενα που είναι πάντα με αναφορά (όπως η κατάσταση, ο πίνακας με αναφορά και ο σωρός) για κλείσιμο θα κλείσει την αναφορά (και θα κρατάει το αντικείμενο "ζωντανό", αλλά ίσως αυτό το αντικείμενο να φαίνεται και αλλού. Σε όλες τις άλλες περιπτώσεις (που έχουμε αντιγραφή) όπως σε ομάδες, πίνακες, μεταβλητές, λάμδα συναρτήσεις το κλείσιμο θα είναι ιδιωτικό και δεν υπάρχει τρόπος να "βρεθούν" ή να αλλαχθούν, παρά μόνο από τη συνάρτηση της λάμδα.
Οι λάμδα συναρτήσεις έχουν αναδρομή με τη χρήση του ονόματος λάμδα() και λάμδα$() για αυτές που γυρνούν αλφαριθμητικό (ή αντικείμενο με τιμή αλφαριθμητικό). Δείτε την Goal όπου σε κάποια περίπτωση περνάμε πάλι την Goal σαν δεύτερη παράμετρο.
Η συνάρτηση στην λάμδα μπορεί να έχει ότι κάθε συνάρτηση στη Μ2000, τμήματα, συναρτήσεις, ρουτίνες. Μπορούμε να πάρουμε και λάθος (με την Λάθος ή Error δημιουργούμε λάθος, και με την Δες μεταβλητή { } πιάνουμε το λάθος ή εντός του μπλοκ ή εντός κλήσεως μέσα από αυτό το μπλοκ.
Μπορούμε να φτιάχνουμε λάμδα που δεν επιστρέφουν τιμή και τις καλούμε με την Κάλεσε Α()  (Εδώ ο σωρός του τμήματος μεταφέρεται στη συνάρτηση, δηλαδή είναι σαν να καλούμε τη συνάρτηση σαν τμήμα).


Range =lambda (x) -> {
      A=Stack
      Stack A {
         Push X
         X--
         if X>0 Then loop
      }
      =A
}
ListLit = Lambda ->[]
Goal=Lambda (op) ->{
       'Goal take three parameters, but 2nd and 3rd can be number or stack object
      ' local lambda   [] means copy stack as result
      ListLit = Lambda ->[]
      If Match("N") Then {
            \\ Number read number for stack
            \\ so we place it to lIstLit stack
            \\ and return it to x
            x=Listlit(Number)
      } Else.If Match("C") Then {
             Read x
       } Else Error "(second argument Not a number Or stack)"
     
      If Match("N") Then {
            y=Listlit(Number)
      } Else.If Match("C") Then {
             Read y
       } Else Error "(third argument Not a number Or stack)"
    
      Z=Stack
      x1=each(x)
      While x1 {
            y1=each(y)
            While y1 {
                  Stack Z {
                        Data op(stackitem(x1),stackitem(y1))
                  }
            }
      }
      =Z
}
Mult=Lambda (x,y)->x*y
Print Goal(Mult,3,4)
Print Goal(Mult,ListLit(1,2,3),ListLit(3))
Print Goal(Mult,Range(30),ListLit(3))
Print Goal(Mult,Range(10),5)
Print Goal(Mult,5,Range(10))
Print Goal(Mult, Goal(Mult,5,Range(10)),ListLit(100,200,300))
Try ok {
      Print Goal(Mult,5)
}
If Error Or Not ok Then Print : Report Error$
Add=Lambda (x,y)->x+y
Power=Lambda (x,y)->x**y
Print Goal(Add,Listlit(1,2,3,4,5,6),10)
Print Goal(Power,2,Range(16))

\\ this is a closure for x and stp and fun (fun as lambda)
generator=Lambda (x, stp, fun) -> {
      =lambda x ,stp, fun (m, n) -> {=fun(m*x,n) : x+=stp }
}
gen2=lambda goal,Mult, Range (multiplier, times)->Goal(Mult,multiplier,Range(times))
Print Goal(generator(20,5, Add),ListLit(3,6,9), Listlit(5,10,15))
\\ same but with gen2()
Print Goal(generator(20,5, Add),gen2(3,3), gen2(5,3))
AddOffset=Lambda (offset, fun) -> {
      = lambda offset, fun -> {
            =offset+fun(number, number)
      }
}
Print Goal(AddOffset(100,Mult),3, gen2(2,10))
Print Goal(Mult,3, gen2(2,10))



Το ίδιο πρόγραμμα αλλά αντί για αντικείμενο Σωρός χρησιμοποιώ πίνακα.


Range =lambda (x) -> {
      L=Lambda M=1 ->{=M:M++}
      Dim A(x)<<L()
      =A()
}
ListLit = Lambda -> {
      Dim A(stack.size)
      M=0
      While Not Empty {
            Read A(M)
            M++
      }
      =A()
}
Goal=Lambda ListLit (op) ->{
       'Goal take three parameters, but 2nd and 3rd can be number or Array object
      If Match("N") Then {
            x=ListLit(Number)
      } Else.If Match("A") Then {
             Read x
       } Else Error "(second argument Not a number Or Array)"
    
      If Match("N") Then {
            y=ListLit(Number)
      } Else.If Match("A") Then {
             Read y
       } Else Error "(third argument Not a number Or Array)"
   
      Dim Z(Len(x)*Len(y))
      M=0
      x1=each(x)
      While x1 {
            y1=each(y)
            While y1 {
                        Z(M)=op(array(x1),array(y1))
                        M++
                  }
      }
      =Z()
}
Mult=Lambda (x,y)->x*y
Print Goal(Mult,3,4)
Print Goal(Mult,ListLit(1,2,3),ListLit(3))
Print Goal(Mult,Range(30),ListLit(3))
Print Goal(Mult,Range(10),5)
Print Goal(Mult,5,Range(10))
Print Goal(Mult, Goal(Mult,5,Range(10)),ListLit(100,200,300))
Try ok {
      Print Goal(Mult,5)
}
If Error Or Not ok Then Print : Report Error$
Add=Lambda (x,y)->x+y
Power=Lambda (x,y)->x**y
Print Goal(Add,Listlit(1,2,3,4,5,6),10)
Print Goal(Power,2,Range(16))

\\ this is a closure for x and stp and fun (fun as lambda)
generator=Lambda (x, stp, fun) -> {
      =lambda x ,stp, fun (m, n) -> {=fun(m*x,n) : x+=stp }
      }
gen2=lambda goal,Mult, Range (multiplier, times)->Goal(Mult,multiplier,Range(times))
Print Goal(generator(20,5, Add),ListLit(3,6,9), Listlit(5,10,15))
\\ same but with gen2()
Print Goal(generator(20,5, Add),gen2(3,3), gen2(5,3))
AddOffset=Lambda (offset, fun) -> {
      = lambda offset, fun -> {
            =offset+fun(number, number)
      }
}
Print Goal(AddOffset(100,Mult),3, gen2(2,10))
Print Goal(Mult,3, gen2(2,10))


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

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

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