Πέμπτη 9 Μαρτίου 2017

Παράδειγμα με τελεστές σε ομάδες

Το παράδειγμα εδώ (από 8 Απριλίου 2016), έχει ένα πρόγραμμα που δείχνει πως γίνονται πράξεις, αφαίρεση και πρόσθεση μεγάλων αριθμών που "μένουν" σε αλφαριθμητικά. Μπορεί κανείς να το συγκρίνει με το παλιό παράδειγμα.
Έχω ορίσει τελεστές"+", "-" και  ">". Η εντολή Class ή Κλάση είναι συνάρτηση που δίνει ως επιστροφή ένα αντικείμενο. Το τμήμα (module) Num καλείται και από την συνάρτηση Num() που απλά την καλεί με τις παραμέτρους που δώσαμε ως έχουν. Μάλιστα με την Match() κοιτάμε αν η παράμετρος είναι αλφαριθμητικό (String) και την διαβάζουμε άμεσα, ή αν είναι αριθμός και την κάνουμε αλφαριθμητικό (επειδή βολεύει στο πρόγραμμα να είναι έτσι). Ο κώδικας δεν έχει αλλάξει από τον παλιό παρά ελάχιστα. Μάλιστα το Dimension(M$(),1) θα μπορούσε να γραφτεί ως Len(M$()).

Όπου έχουμε απλό Read σε Module, Operator, Function μπορούμε να το γράψουμε και έτσι (οι παρενθέσεις με τα ορίσματα να ξεχωρίζουν από το όνομα, να ξεχωρίζει το χρώμα τους - μπαίνει αυτόματα στον διορθωτή):

Module Complement (many) {
           b$=""  : m%=1
           ....
           }


Operator ">" (A) {
           ....
           }
Η συνάρτηση Place$() θα μπορούσε να γραφτεί και έτσι σε ορισμό μιας γραμμής με την εντολή Def (απλά είναι μια ευκολία):

Def Place$(A, X)=Right$(String$(" ",X)+A.Val$,X)
 
Αναβαθμίστηκε το παράδειγμα, για να γίνει συμβατό με την έκδοση 9.2 αναθεώρηση 3. Αν και κρατάω την συμβατότητα με τα παλιά προγράμματα, εδώ έπρεπε να αλλάξει η θέση των δυο στοιχείων που θα εκτελεστούν από τον τελεστή. Στην παλαιά έκδοση το This ήταν το αριστεριό μέλος, ενώ τώρα είναι στο δεξιό (πχ το Α+Β γίνονταν με This το B και Push to Α, τώρα γίνεται αλλιώς)


Class Num {
      Val$="0"
      Module Num {
            If Match("S") then {
                  Read .Val$
            } Else {
                  .Val$<=Str$(Number,"0")
            }
      }
      Module Complement {
           read many
           b$=""  : m%=1
           If many>len(.Val$) then .Val$<=string$("0",many-len(.Val$))+.Val$
           For i=len(.Val$) to 1 {
                 m%=9-val(mid$(.Val$, i,1))+m%
                 mm%=m%-10
                 if m%<10 then {
                  b$=str$(m%,"0")+b$ : m%=0
                }   else b$=str$(mm%,"0") +b$: m%=1
           }
           .Val$<=Right$(b$, many)
      }
      Operator ">" {
            Read A
                  If Len(A.Val$)=Len(.Val$) then {
                        Push A.Val$>.Val$
                  } Else.If Len(A.Val$)<Len(.Val$) then {
                        Push True
                  } Else Push False
      }
      Operator "-" {
       Read B
       If This>B then { \\ this is the new operator ">"
            
             B.complement Len(.Val$)
             this<=B+this
             For this {
                  Many=1
                  i=len(.Val$)
                  If i>many then {
                      while many<i {
                        If mid$(.val$,many+1,1)<>"0" then exit
                        many++
                  }
                  if many=i then many--
                        .val$<=mid$(.val$, many+1)
             }
             }
       } Else Error "Error, A<B"       
      }
      Operator "+" {
            Read B
            if B.val$="0" then exit
            Dim Base 0, M$(Max.Data(len(.Val$)+1,Len(B.Val$)+1)+1)
           
            If len( B.Val$)<len(.Val$) then {
                  swap .Val$, B.Val$
            } Else.if len( B.Val$)=len(.Val$) Then {
                  If B.Val$<.Val$ then swap .Val$, B.Val$
            }          
         
            M%=0
            ofs=Len(B.Val$)-Len(.Val$)
            if ofs<0 then error "??????"
            For I=Len(.Val$) to 1 {
                  M%=M%+Val(Mid$(.Val$, I,1))+Val(Mid$(B.Val$, I+ofs,1))
                  M$(I+ofs+1)=Str$(M% mod 10,"0")
                  M%=-(M%>9)
            }
           If M%>0 Then {
                 While ofs>0 {
                          M%=M%+Val(Mid$(B.Val$, ofs,1))
                          M$(I+ofs)=Str$(M% mod 10,"0")
                          M%=-(M%>9)
                          ofs--
                 }
                 If M%>0 Then {
                      M$(0)=Str$(M% mod 10,"0")
                 }    
           }
           F$=""
           For i=0 to Dimension(M$(),1)-1 {
                 F$=F$+M$(i)
           }
           If ofs>0 Then {
                 .Num Left$(B.Val$,ofs)+F$
           } Else .Num F$
      }
}

Function Place$ {
      Read A, X
      =Right$(String$(" ",X)+A.Val$,X)
}
A=Num("20")
B=Num("3")
F=A-B \\ 17
F=F+Num(50) \\ 67
Print Place$(F,len(A.Val$)+2)
A=Num("999999999999999999999999999999999999999999999999999999999999999999999999")
B=Num("3")
M=Num(50)
'F=(M+A)-B  \\ work ok
F=(A-B)+M
Print Place$(F,len(A.Val$)+2)
Print Num(5)>Num(3) '' -1
Print Num("5")>Num("12313") '' 0
Print Place$(Num("5")+Num("10")+Num("150"), 20) ' 165
A=Num("99999")
B=Num("100001")
F=A+B
Print Place$(F,len(F.Val$)+2)
Print F>A

Αναθεώρηση 1, έκδοση 8.4

Νομίζω ότι ολοκληρώθηκε η γλώσσα (ίσως ασχοληθώ με το να φτιάξω κάποιο στοιχείο ελέγχου, έχει τα βασικά η Μ2000, εκτός από λίστα τύπου δένδρο και λίστα πολλαπλών στηλών)

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

Το παρακάτω πρόγραμμα δείχνει τι γίνεται. Η λάμδα συνάρτηση L έχει δική της μεταβλητή την Χ και ο τελεστής << στην DIM κάνει την λάμδα να εκτελείται για κάθε στοιχείο του πίνακα α(). Επειδή χρησιμοποιούμε την number, η οποία διαβάζει από το σωρό, πρέπει να παρέχουμε ένα νούμερο στη κλήση της lambda, και αυτό κάνουμε με το νούμερο 200.
Μετά φτιάχνουμε την c ως ένας επαναλήπτης του πίνακα. Στην ουσία και η c είναι αναφορά στο πίνακα. Μάλιστα δίνουμε να ξεκινάει από το δέκατο στοιχείο (δεν δίνουμε το τέλος οπότε εξορισμού βάζει το τελευταίο). Θα μπορούσαμε να δώσουμε αρνητικά νούμερα, πχ το -2 σημαίνει δεύτερο από το τέλος. Μπορούμε να δώσουμε χωρίς το πρώτο κόμα μετά τον πίνακα γράμματα όπως :
c=each(a Start to End)
ή ελληνικά
c=κάθε(a Αρχή έως Τέλος) ή το ανάποδο c=κάθε(a Τέλος έως Αρχή) ή με νούμερα:
c=κάθε(a Αρχή έως 10) όπου 10 είναι το δέκατο στοιχείο.
Μετά φτιάχνουμε την b ως αναφορά στη c (που είναι αναφορά στην α()), αλλά είναι στην ουσία ένας επαναλήπτης και αυτός. Στο δέκατο στοιχείο Α(9) βάζουμε ένα νούμερο για να δείξουμε ότι όλες οι αναφορές είναι σωστές.
Ξεκινάμε την Ενώ και σκοπό έχουμε να δείξουμε τιμές με βήμα 12. Για να κάνουμε το βήμα, αναπρογραμματίζουμε τον επαναλήπτη. Η b^ είναι η τιμή του δρομέα, ο αριθμός δηλαδεί που ξεκινάει πάντα από το 0 για το πρώτο στοιχείο. Λέμε λοιπόν με την each(b, b^+12) να μεταθέσουμε την αρχή στο τωρινό στοιχείο συν 12. H While (Ενώ) ελέγχει το αντικείμενο b, και βλέπει ότι έχει αλλάξει ο εσωτερικός του μετρητής (ο οποίος γίνεται όσο το αρχικό νούμερο, εδώ το B^+12).

Μέσα στο μπλοκ εντολών έχουμε μια Τύπωσε (Print) η οποία δίνει τέσσερα πράγματα..η Πίνακας() ή Array() με μια παράμετρο δίνει το στοχείο που καθόρισε η While, και καταχώρησε στο πίνακα a() (αφού η b είναι αναφορά του a(), αν και έχει δικές ιδιότητες). Στη δεύτερη στήλη τυπώνουμε το a(b^) δηλαδή το στοιχείο που ήδη γνωρίζει ο a() (έχει καταχωρηθεί σε μια εσωτερική Index). Η εντολή πίνακας μπορεί να χρησιμοποιηθεί με παραμέτρους βάσει των διαστάσεων του πίνακα, εδώ τυπώμε το προηγούμενο στοιχείο b^-1 (το σύμβολο ^ όπως και το ** χρησιμοποιούνται για δυνάμεις, αλλά εδώ το b το χρησιμοποιεί αλλιώς). Τελευταία στήλη δείχνουμε ότι και ο πίνακας a() έχει δείκτη εσωτερικά για να δείξει αυτό που επιλέγει ο επαναλήπτης  b

Παρακάτω τυπώνουμε το τύπο του αντικειμένου, για τα b και c. Δείχνει mArray, που είναι η εσωτερική κλάση των πινάκων στη Μ2000.
Επίσης βλέπουμε ότι η πίνακας(c,9) ή array(c,9) δίνει το 12345 όπως θα περιμέναμε.
Μπορούμε να αλλάξουμε στη C τα όρια, και εδώ αυτό κάνουμε και παίρνουμε τα στοιχεια με την Τύπωσε (από την 8.4 τυπώνει πίνακες, καταστάσεις και αυτά τα δύο μέσω των επαναληπτών, όλα σ στήλες).
Στο τέλος βλέπουμε και τις φωλιασμένες λίστες (φωλιασμένοι πίνακες για την ακρίβεια) που φτιάχνουμε με τις παρενθέσεις. Χρησιμοποιούμε την Car() (την έχω πάρει από την Lisp) η οποία παίρνει το πρώτο στοιχείο και αν αυτός είναι πίνακας τον ανοίγει. Εδώ το πρώτο στοιχείο του πίνακα είναι ένας πίνακας τριών στοιχείων, τα δυο πρώτα εμφανίζονται, αλλά το τρίτο επειδή είναι πίνακας τον εμφανίνει η Τύπωσε ως ένα διάστημα στη στήλη του, οπότε πρακτικά δεν το βλέπουμε, παρά μόνο τα 1 και 2.


L=lambda X=0->{=X+number:X++}
Dim a(100)<<L(200) \\ fill 200.. 299
\\ walk from 10th (209) to end, step 12

c=each(a(), 10)
b=c \\ we can copy it
A(9)=12345
while b {
      \\ this is a special version of while, using an iterator
      \\ we can change b inside while block
      \\ b control internal index of array a()
      \\ array() with one parameter return item using internal index
       print array(b), a(b^), array(b, b^-1), array(a())
       b=each(b,b^+12)
}
Print type$(b),type$(c) \\ mArray is internal class of array
\\ b and c are all references to A()
Print array(c,9)
c=each(c 10 to 13) \\ 10th is the 9
Print c
m=(1,2,3,4)
n=((1,2,(3,4)), 10)
d=car(n)
Print d


Ειδικά για το παράδειγμα με τους πίνακες σε πίνακες υπάρχει το παρακάτω ωραίο παράδειγμα:

n=((1,2),3,(4,5))
Link n to a()
\\ print 1 2 3 4 5
Print a(0)(0),a(0)(1),a(1),a(2)(0),a(2)(1)
b=car(n)
c=car(cdr(n))
d=car(cdr(cdr(n)))
\\ Print 1 2 3 4 5
Print b,c,d
m=(1,) \\ this array of one item
k=() \\ zero len array
Print len(m), len(k)
z=cons(b,c,d)
Print z

Φτιάχνουμε τον πίνακα n με πρώτο στοιχείο ένα πίνακα (1,2), δεύτερο το 3 και τρίτο έναν άλλο πίνακα τον (4,5). Μπορούμε να συνδέσουμε το πίνακα n με αναφορά στον a(). Τώρα με την τύπωσε μπορούμε να εμφανίζουμε όποιο στοιχείο θέλουμε. Πχ. το a(0)(1) είναι το δεύτερο στοιχείο του πίνακα που είναι στο πρώτο στον a() που είναι αναφορά στον n.
Η εντολή b=car(n) βγάζει αντίγραφο του (1,2) στο b. Η εντολή car(cdr(n)) κάνει το εξής: βγάζει τα επόμενα στοιχεία από το πρώτο, ως αντίγραφο, τα οποία παίρνει η car() και εξάγει το πρώτο, άρα παίρνουμε το δεύτερο από την n, το 3.
Μετά με τα car(cdr(cdr(n))) παίρνουμε το (4,5). Η συνάρτηση car() μπήκε εδώ για να μετασχιματίσει το στοιχείο σε πίνακα πολλών στοιχείων (ήταν βέβαια, αλλά χωρίς την car() θα είχαμε ένα πίνακα ενός στοιχείου και εκεί το (4,5) δηλαδή το ((4,5)).
Τυπώνουμε τα b,c,d και παίρνουμε το 1 2 3 4 5
Με την m δείχνω πως βάζουμε ένα πίνακα ενός στοιχείου. (θέλει ένα κόμμα πριν την τελευταία παρένθεση). Αν δώσουμε δυο παρανθέσεις χωρίς στοιχεία, θα σχηματιστεί πίνακας, αλλά κενών από στοιχεία. Η συνάτηση Μήκος() εκτός από τη χρήση στα αλφαριθμητικά, τις καταστάσεις. χρησιμεύει και για τους πίνακες. Δείχνει το σύνολο των στοιχείων (σαν να ήταν μονοδιάστατος ο πίνακας, ενώ υπάρχει η συνάρτηση Διάσταση(), που δίνει τον αριθμό διαστάσεων, τη βάση του πίνακα 1 ή 0, και ανά διάσταση τον αριθμό στοιχείων, ανάλογα με τις παραμέτρους που παρέχουμε.
Θα πάρουμε 1 και 0 (αφού η k έχει μηδενικά στοιχεία.
Η z φτιάχνεται με την cons(b,c,d) οπότε με την εκτύπωση θα πάρουμε τα 1 2 3 4 5

Γ.Κ.




Τετάρτη 8 Μαρτίου 2017

Έκδοση 8.4

Νέα έκδοση του διερμνηνευτή Μ2000. Πολλές προσθήκες και βελτιώσεις!

Βελτιώσεις (μικρές και μεγάλες):
1. Στον διορθωτή (editor) το πλήκτο Home μια φορά πάει στην αρχή της γραμμής και την επόμενη στΗν αρχή της πρώτης λέξης. Αυτό βοηθάει όταν γρήγορα μαζεύουμε τις γραμμές (Tab πάνε οι επιλεγμένες γραμμές δεξιά. και Shift Tab πάνε αριστερά).

2. Στον έλεγχο (Control), μπορούμε να δώσουμε μια εντολή (στην Τύπωσε που εμφανίζει), ώστε να σταματήσει σε συγκεκριμένη ετικέτα δοκιμής (Εντολή Δοκιμή). Θα το δείξω σε άλλη ανάρτηση.

3. Βελτίωση στην κλήση ρουτινών. Ενώ τα τμήματα και οι συναρτήσεις, ανήκουν σε μια λίστα όπου υπάρχει όνομα και κώδικας, οι ρουτίνες δεν έχουν δική τους "υπόσταση", αλλά βρίσκονται σε κώδικα μέσα σε τμήματα και συναρτήσεις. Κάθε φορά που καλούνταν γίνοταν αναζήτηση από το τέλος του κώδικα, ενώ τώρα αυτό γίνεται την πρώτη φορά, και για κάθε κώδικα στη λίστα τμημάτων-συναρτήσεων υπάρχει λίστα ρουτινών που αναζητήθηκαν έστω μια φορά. Το παιχνίδι Φιδάκι που είχα ανεβάσει, κέρδισε σε ταχύτητα!

4.Νέου τύπου μεταβλητή, η μεταβλητή με αναφορά σε πίνακα. Μπορούμε να χειριστούμε το πίνακα σαν μεταβλητή. Πχ. να προσθέσουμε ένα αριθμό σε όλα τα στοιχεία του. Θα δείξω παραδείγματα χρήσης σε επόμενη ανάρτηση. Υπάρχουν οι εντολές Car(), Cdr() και Cons()  (από την Lisp) για να βγάζουμε αντίγραφο του πρώτου στοιχείου, ή των υπολοίπων, ή να αντιγράφουμε δυο πίνακες σε έναν. Οι πίνακες αυτοί μεταβιβάζουν την αναφορά τους σε άλλες μεταβλητές ή βγάζουν αντίγραφο αν δώσουμε όνομα πίνακα με παρενθέσεις. Μπορούν να έχουν μέχρι δέκα διαστάσεις, αλλά οι ειδικές εντολές λειτουργούν ως να ήταν μονοδιάστατοι. Μπορούμε να ενώσουμε μια μεταβλητή πίνακα, με ένα πίνακα, ώστε να διαβάζουμε όπως θέλουμε τα στοιχεία. Οι πίνακες μπορούν να έχουν εκτός από αλφαριθμητικά και αριθμούς οτιδήποτε άλλο, πχ λάμδα συναρτήσεις, καταστάσεις, πίνακες, ομάδες (αντικείμενα) και άλλα.

5.Νέου τύπου μεταβλητή (που δεν φαίνεται άμεσα, ως απαριθμητής στοιχείων) όπου παίρνει έναν πίνακα ή μια κατάταση και διατρέχει τα στοιχεία του. Προς το παρόν ο δρομέας ανήκει στο πίνακα/κατάσταση, άρα δεν μπορούν να χρησιμοποιηθούν πολλαπλές τέτοιες μεταβλητές για τον ίδιο πίνακα, αλλά μπορεί να αλλαχτεί χωρίς να έχει επιπτώσεις ο δρομέας, και να τον γυρίσουμε πάλι στο σημείο που θέλουμε. Προς το παρόν δεν έχει όνομα (είναι σαν μεταβλητή πίνακα, αλλά αναφέρει η Τύπος$() αυτό που δείχνει, τον πίνακα ή τη κατάσταση - η κατάσταση είναι λίστα με κλειδιά). Περισσότερα παραδείγματα στις επόμενες αναρτήσεις!


                  Κατάσταση αλφα="b","a","f","d","c"
                  Ταξινόμηση αλφα
                  Τύπωσε αλφα
                  M=Κάθε(αλφα Τέλος έως Αρχή)
                  Τύπωσε M
                  N=Κάθε(αλφα,-1, 1)
                  Τύπωσε M


6. Η εντολή τύπωσε τυπώνει πίνακες, καταστάσεις και σειρές αυτών (με τον απαριθμητή στοιχείων).

7. Νέου τύπου Κατάσταση. Αυτή λέγεται Κατάσταση Ουρά. Οι καταστάσεις χρησιμοποιούν πίνακα κατακερματισμού για γρήγορη αναζήτηση, διαγραφή, προσθήκη. Αν και υπάρχει η εντολή Ταξινόμηση, μια διαγραφή μπορεί να αλλάξει τη σειρά. Επιπλέον τα κλειδιά στην Κατάσταση είναι μοναδικά, δηλαδή δεν δέχεται διπλό ίδιο κλειδί. Η νέα Κατάσταση λέγεται Κατάσταση Ουρά, και έχει το πλεονέκτημα να παίρνει όμοια κλειδιά, αλλά δεν μπορεί να διαγράψει οποιαδήποτε κλειδιά, παρά μόνο τα τελευταία, και δεν μπορεί να ταξινομηθεί. Αν έχουμε ένα κλειδί ίδιο τρεις φορές, η αναζήτηση βρίσκει το τελευταίο που μπήκε στη λίστα. Αν το σβήσουμε τότε η αναζήτηση θα βρεί το αμέσως προηγούμενο. Μπορούμε βέβαια να διαβάζουμε όποιο στοιχείο θέλουμε στη κατάσταση, σαν να είναι πίνακας, ή να διαβάσουμε το κλειδί κάθε στοιχείου, ή να δώσουμε ένα κλειδί και να μας δώσει το σύστημα τη θέση στη κατάσταση. Για τα όμοια κλειδιά είναι μια κατάσταση "Το πρώτο που θα μπει θα βγεί τελευταίο".

                   Κατάσταση Ουρά αλφα=1,2,3:="αα",3:="ββ",4,4
                  Αν υπάρχει(αλφα, 3) Τότε Τύπωσε εκφρ$(αλφα)
                  Τύπωσε μήκος(αλφα) ' 6
                  Πέτα άλφα 3 ' πετάει τα τελευταία 3
                  Τύπωσε μήκος(αλφα) ' 3
                  Τύπωσε εκφρ$(αλφα, 2) ' Τυπώνει το 3ο στοιχείο

8. Σημαντική βελτίωση έγινε στις Ομάδες. Οι ομάδες είναι στην ουσία μικρά προγράμματα, τα οποία έχουν ότι θέλουμε από μεταβλητές, αλλά και συναρτήσεις και τμήματα, και κάποια από όλα αυτά τα δηλώνουμε ως δημόσια και άλλα ως ιδιωτικά. Ενώ στα τμήματα και στις συναρτήσεις ο κώδικας "παραμένει", οι ομάδες μπορούν να είναι επώνυμες μέσα σε τμήματα και συναρτήσεις, να αποτελούν μέρος τους, ή να είναι ανώνυμες, και να βρίσκονται σε θέση, πχ σε πίνακα, σε κατάσταση ή στο σωρό τιμών. Μέχρι εδώ αυτές τις δυνατότητες είχαν. Τώρα προστέθηκαν τα παρακάτω:

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

8.2 Τελεστές. στις ομάδες. Μπορούμε να ορίσουμε τελεστές και εν τέλει πράξεις που θα γίνουν με τις ομάδες μεταξύ τους. Π.χ. μπορούμε να ορίσουμε συγκρίσεις για μεγαλύτερο/μικρότερο. Είναι πολύ εύκολο στη χρήση! Ειδικά αυτή η λειτουργία των τελεστών ανέβασε ένα 0.1 την έκδοση, και από 8.3 γύρισε στο 8.4
Εδώ είναι ένα παράδειγμα στα αγγλικά (με το οποίο έκανα δοκιμές όταν έφτιαχνα τον κώδικα της γλώσσας). Κάθε τελεστής είναι μια συνάρτηση της οποίας η εξαγωγή  θα γίνει στο σωρό. Αν δεν κάνουμε εξαγωγή τότε δίνει ο διερμηνευτής ένα δείκτη στο αντικείμενο, και αυτό αν δεν χρησιμοποιηθεί σβήνεται. Αν όμως θέλουμε να δώσουμε κάτι μπορούμε να βάλουμε στο σωρό (με τη Βάλε ή Push). Στο παράδειγμα βλέπουμε να λειτουργούν οι τελεστές σε ομάδες που είναι σε πίνακες. Σε πίνακες έχουμε κλειστά αντικείμενα, ή αντικείμενα σε θέση, σε αντίθεση με τα επώνυμα αντικείμενα, όπου βρίσκονται σε ένα τμήμα και "πεθαίνουν" μαζί του, ενώ ο πίνακας μπορεί να μπεί στο σωρό για επιστροφή, άρα να πάρει και το κλειστό αντικείμενο. Και είναι πράγματι κλειστό το αντικείμενο γιατί για αν χρησιμοποιηθεί πρέπει να ανοίξει, να γίνει επώνυμο. Αυτό το κάνει αυτόματα ο διερμηνευτής. Στη γραμμή με το For Α(1) {This+=5} μέσα στις αγκύλες το αντικείμενο στο Α(1) είναι ανοικτό, απλά δεν βλέπουμε το όνομα...και για το λόγο αυτό χρησιμοποιούμε την This ή Αυτό. Μπορούμε όμως να συνδέσουμε ένα όνομα με την εντολή Ένωσε η οποία αποδίδει "αναφορές" σε νέα ονόματα (δεν μπορεί να δώσει στο ίδιο όνομα δεύτερη αναφορά).

                              Class alfa {
                                    x, y
                                    Module GetXY { Read ? .X, .Y }
                                    Operator "++" {
                                          .X++
                                          .Y++
                                    }
                                    Operator "=" {
                                         Read N
                                         push .X=N.X and .Y=N.Y
                                    }
                                    Operator ">" {
                                         Read N

                                         push .X<N.X and .Y<N.Y
                                    }
                                    Operator "+=" {
                                          Read N
                                          .X+=N
                                          .Y+=N
                                    }
                                    Operator "+" {
                                           Read M
                                          .X+=M.X
                                          .Y+=M.Y
                                    }
                                    Operator "*" {
                                           Read M
                                          .X*=M.X
                                          .Y*=M.Y
                                    }
                              }
                              alfa=alfa()
                              alfa.GetXY 100,300
                              Dim A(10)=alfa()

                              a(1).GetXY 1,30

                              For a(1) {This+=5}
                              Print a(1).x
                              a(2)=a(1)
                              Print a(1).x,a(2).x
                              Print a(1).x*(a(1).x+a(2).x),$(3),"6*(6+6)"
                              a(4)=a(1)*(a(1)+a(2))
                              a(5)=a(1)*(a(2)+a(1))
                              Print $(0), A(4)>A(5)
                              Print A(4)=A(5)
                              Print A(4).x, A(5).x

Γενικά δεν υπάρχουν προβλήματα με τα νέα καλούδια αλλά χρειάζεται λίγο ακόμα έλεγχος και δοκιμές. Οπότε μέσα στη βδομάδα θα ανέβουν οι αναθεωρήσεις και μαζί και τα παραδείγματα.
Στην τρέχουσα έκδοση 8.7 στο Α(4)>Α(5)  το Διάβασε Ν διαβάζει το Α(4) και όχι το Α(5), ενώ τρέχει ο τελεστής στο Α(5).

Πέμπτη 16 Φεβρουαρίου 2017

Αναθεώρηση 19 Έκδοση 8.2

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

Για τον πίνακα Π και τη θέση 1 υπάρχει μια εντολή που κάνει τη Κατάσταση να "ξεκολλήσει", και αυτό είναι το 0. Όταν πάμε στην Ν την κατάσταση, βάζουμε το 0 στη θέση στον πίνακα απ΄όπου την πήραμε. Εδώ πρακτικά δεν μας βοηθάει κάπου αυτό. Θα βοηθούσε αν τρέχουν νήματα και κάποιο νήμα θέλει να αλλάξει κάτι στη Κατάσταση, γιατί τώρα απλά δεν θα την βρεί!


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

Κατάσταση Κ1
Ομάδα αβγ {
      μ=5
      Συνάρτηση φ { Διάβασε χ : =χ*10+.μ }
}
Τύπωσε αβγ.φ(20)
κλειδί$="Ναι"
\\ φορτώνουμε στη λίστα ένα αντίγραφο της ομάδας
Προσθήκη Κ1, κλειδί$:=αβγ
\\ Ο διερμηνευτής επιλύει αυτό
Τύπωσε Κ1("Ναι").φ(20)
\\ και αυτό
Κ1("Ναι").μ++
Τύπωσε Κ1("Ναι").μ \\ 6


Πίνακας Π(10)
\\ η Κατάσταση πάντα γράφεται με αναφορά
\\ εδώ ο πίνακας κρατάει μια αναφορά στην κατάσταση Κ1
Π(1)=Κ1
Τύπωσε Π(1)("Ναι").φ(20), Π(1)("Ναι").μ
Για Αυτό {
      \\δεν έχουμε κάποια Λ στο κώδικα πριν, έστω ότι έχουμε: φτιάχναμε μια τοπική
      Τοπική Λ
      Κατάσταση Λ
      Λ=Π(1) \\ Τώρα θα δώσουμε μια αναφορά στο Ν (το Ν είναι κατάσταση
      Λ("Ναι").μ+=10
      \\ εδώ τελειώνει το Για Αυτό {}, και η Λ θα διαγραφεί (ο δείκτης στη Π(1) που είναι ίδιος με την Κ1)
     
}
\\ Απόδειξη
Τύπωσε Π(1)("Ναι").μ \\ 16
Τύπωσε Κ1("Ναι").μ \\ 16
Τύπωσε Μήκος(Κ1) \\ 1 στοιχείο
Καθαρό Κ1 \\ καθαρίζουμε τη κατάσταση, βάζοντας μια καινούργια μηδενική!
Τύπωσε Μήκος(Κ1) \\ 0
Τύπωσε Μήκος(Π(1)) \\ 1  η κατάσταση μένει εδώ ως έχει.
Τύπωσε Π(1)("Ναι").μ \\ 16
Για Αυτό {
      Τοπική Ν
      Κατάσταση Ν
      Ν=Π(1)
      Π(1)=0 \\ δεν παίρνει το μηδέν αλλά το Τίποτα
      Τύπωσε Τύπος$(Π(1)) \\ Nothing, παραμένει ένα "τίποτα"
      Π(1)=Ν \\ τώρα το βάλαμε στη θέση του1
      Τύπωσε Τύπος$(Π(1)) \\ Inventory (Κατάσταση)
}
\\ Σβήνουμε τον πίνακα
Πίνακας Π()
Λίστα
\\ την εντολή παρακάτω την δίνουμε για να αδειάσει η συλλογή σκουπιδιών.
\\ στην ουσία σβήνει τις κρατημένες αναφορές, και τις τυχόν κυκλικές
\\
Άδειασε Σκουπίδια

 

Τετάρτη 15 Φεβρουαρίου 2017

Αναθεώρηση 18 - Έκδοση 8.2

Διορθώθηκαν δυο πράγματα:
1) Στις λάμδα συναρτήσεις γίνεται έλεγχος για τις Καταστάσεις (τύπος Inventory, Κατάσταση) που μπορεί να έχουν κρατήσει (captured) κατά την διαγραφή τους ώστε να αποδεσμευτούν από τον συλλέκτη σκουπιδιών (garbage collector). Οι καταστάσεις (λίστες με κλειδί) περνούν με αναφορά, και η αναφορά περνάει και στον garbage collector.
Με την εντολή Λίστα (list) βλέπουμε τι μεταβλητές έχουμε τη δεδομένη στιγμή και αν έχουν κρατηθεί αναφορές στον συλλέκτη σκουπιδιών (δεν εμφανίζεται η αναφορά αν δεν έχουμε, ή εμφανίζεται "Αντικείμενα για διαγραφή και ο αριθμός τους"

 Φόρμα 60,40
δυαδ0$=λάμδα$ ->{
      Κατάσταση δυαδική_τιμή = 0:="0000",1:= "0001",2:= "0010", 3:="0011",4:= "0100", 5:="0101", 6:="0110", 7:="0111", 8:="1000", 9:="1001", "A":="1010", "B":="1011", "C":="1100", "D":="1101", "E":="1110", "F":="1111"     
      \\ η δυαδ$ είναι μια λάμδα συνάρτηση που συλλαμβάνει τη Κατάσταση δυαδική_τιμή
      \\ τα πρώτα κλειδιά έχουν ως αριθμοί. Η κατάσταση τα δέχεται και ως αριθμούς και ως γράμματα, γιατί τα κλειδιά τα κρατάει ως γράμματα εσωτερικά!
      = λάμδα$ δυαδική_τιμή->{
            Διάβασε μια_τιμή
            Αν Ταύτιση("Α") τότε {
                  Διάβασε από_εδώ
                 από_εδώ=2*(ακ(4-από_εδώ) υπολ 4+1)-1
            } Αλλιώς {
                  από_εδώ=1
            }
                  δεκαεξαδική$ = Δεκαεξ$( μια_τιμή, 4 )
            Εγγραφο Αα$
            Για ι = από_εδώ Εως Μήκος( δεκαεξαδική$ )
                  Αα$ =  δυαδική_τιμή$( Μεσ$( δεκαεξαδική$, ι, 1 ) )
            Επόμενο ι
            = Αα$
      }
}
δυαδ$=δυαδ0$()
Τύπωσε δυαδ$(12), 12
Τύπωσε δυαδ$(255,1), 255
Τύπωσε δυαδ$(256*256+255,2), 256*256+255
Τύπωσε δυαδ$(0xFF446688,4), 0xFF446688
Λίστα  \\ δείχνει τις μεταβλητές και στο τέλος λέει Αντικείμενα για καταστροφή 1 (και αυτό είναι η Κατάσταση, που είναι με αναφορά)
Βάλε δυαδ$ \\ βάζουμε στο σωρό ένα αντίγραφο
\\  όταν τερματίσει το πρόγραμμα δίνουμε τις εντολές
\\  Σωρός  (και βλέπουμε ότι υπάρχει ένα αντικείμενο λάμδα)
\\ Λίστα (και μας λέει ότι έχει ένα αντικείμενο για διαγραφή)
\\ έχουμε δυο δυνατότητες
\\ ή παίρνουμε τη λάμδα σε μια μεταβλητή (πρέπει να είναι τύπου αλφαριθμητικού, όπως φτιάξαμε τη λάμδα)
\\ Διάβασε δ$  : Τύπωσε δ$(123, 1) : λίστα  \\ παραμένει το ένα αντικείμενο
\\ Καθαρό : Λίστα  \\ τώρα δεν υπάρχει τίποτα
\\ ή αδειάζουμε το σωρό με την Άδειασε χωρίς να φτιάξουμε λάμδα συνάρτηση
\\ Άδειασε : Λίστα \\ τώρα έχει διαγραφεί και το αντικείμενο που κράταγε η λάμδα στο σωρό!



2) Διορθώθηκε και αυτό (είχε λάθος στο Read για τις λάμδα σε μεταβλητή string, κατά το διάβασμα από το σωρό)

a$=Lambda$->"Ok"
Print a$()
Push a$ \\ to stack
Read m$ \\ from stack to new variable
Print type$(m$), m$()
 

Τρίτη 14 Φεβρουαρίου 2017

Αναθεώρηση 17 (Έκδοση 8.2)

1) Πρόσθεσα δυο διευκολύνσεις στο σχηματισμό πινάκων.
Μια είναι η προσωρινή επιλογή βάσης (1 ή 0) που δεν επηρεάζει την τέχουσα επιλογή. Στη Μ2000 οι πίνακες από την έκδοση 8.2 αναθεώρηση 15μπορούν να έχουν μια από τις δυο βάσεις, δηλαδή να ξεκινά η κάθε διάσταση από το 0 ή από το 1 (μέχρι δέκα διαστάσεις υποστηρίζει η γλώσσα).

Βάση 0 \\ εξ ορισμού είναι 0 - Προσοχή δεν δέχται έκφραση αλλά μόνο το 1 ή το 0
Πίνακας Βάση 1, Α(10), Β() \\ ******* Πίνακας Βάση 1, ... ή Πίνακας Βάση 0, ...νέο στη 16
Πίνακας Β(4,6) \\ θυμάται ότι έχουμε ορίσει βάση 1 για τον πίνακα Β()
Πίνακας Δέλτα(10) \\ αυτός έχει βάση 0
Τύπωσε Διάσταση(Δέλτα()) \\ 1
Τύπωσε Διάσταση(Β()) \\ 2  *******Νεο****** στη 16
Τύπωσε Διάσταση(Β(),0) \\ 1 μας δίνει την βάση
Τύπωσε Διάσταση(Β(), 1) \\ 4 αριθμός στοιχείων στην πρώτη διάσταση
Τύπωσε Διάσταση(Β(), 2) \\ 6 αριθμός στοιχείων στην δεύτερη διάσταση


Δουλεύει και με πίνακες σε ομάδες (Κλάση στη Μ2000 είναι συνάρτηση που γυρίζει ομάδα. Ένα τμήμα με το όνομα της κλάσης είναι ο κατασκευαστής - δεν είναι απαραίτητο να υπάρχει, αλλά μπορούμε να θέλουμε η Κλάση να έχει κατά τη δημιουργία κάποια ρύθμιση. Εδώ γεμίζουμε όλα τα στοιχεία από το 1 μέχρι το τελευταίο με αύξηση κατά 1. Βάζουμε μια τοπική λάμδα να δίνει σε κάθε στοιχείο του πίνακα το νέο αριθμό. Η Κ στη Λάμδα είναι ιδιωτική. Πρώτα φτιάχνεται το αντικείμενο Λάμδα και μετά καταχωρείται στην Ν.

Κλάση Αλφα {
      Πίνακας Βάση 1, Μ()
      Τμήμα Αλφα {
            Πόσα=100
            Διάβασε ? Πόσα
            Ν=Λάμδα Κ=1 ->{=Κ : Κ++}
            Πίνακας .Μ(Πόσα)<<Ν()
      }
}
Ν=Αλφα()
Τύπωσε Ν.Μ(100)=100 \\ -1
Πίνακας Ν.Μ(30) \\ μείωση
Τύπωσε Διάσταση(Ν.Μ(),1) \\ 30
Τύπωσε Διάσταση(Ν.Μ(),0) \\ 1, ξεκινάει από 1
Ν=Αλφα(300)
Τύπωσε Διάσταση(Ν.Μ(),1) \\ 300
Τύπωσε Διάσταση(Ν.Μ(),0) \\ 1, ξεκινάει από 1
Τύπωσε Ν.Μ(300) \\ 300



3) Διόρθωσα ένα μικρό λάθος. Κατά την αντιγραφή ενός αντικειμένου γεγονότος σε ένα εντός ομάδας με το χειριστή (ή τελεστή) <= χανόταν η αντιγραφή, ενώ λειτουργούσε με =. Τώρα λειτουργεί και με <=.Το <= μπήκε για να ξεχωρίζει ο Διερμηνευτής αν φτιάχνουμε μια τοπική ή δίνουμε τιμή σε μια μεταβλητή (ή ιδιότητα) της ομάδας (αντικείμενο της Μ2000).

Ομάδα Κ {
Ιδιωτικό:
      Γεγονός Χ {Διάβασε Τ}
Δημόσιο:
      Τμήμα ΔεςΕδώ {
            \\ Διάβασε .Χ  - εδώ με μια γραμμή, χωρίς το Ν
            Διάβασε Ν
            .Χ<=Ν
      }
      Τμήμα ΚάνεΚάτι {
            Κάλεσε Γεγονός .Χ, Αριθμός \\ διαβάζει από το σωρό
      }
}
Γεγονός Μ {
      Διάβασε Τ
      Συνάρτηση {
            Τύπωσε Τ
      }
}
Κ.ΚάνεΚάτι 100 \\ δεν κάνει τίποτα γιατί το Χ δεν έχει συνδεθεί με μια συνάρτηση τουλάχιστον
Κ.ΔεςΕδώ Μ
Κ.ΚάνεΚάτι 100

Κυριακή 12 Φεβρουαρίου 2017

Νέο Μικρό Εγχειρίδιο!

Ανέβηκε ανανεωμένο το μικρό εγχειρίδιο της Μ2000. Δείτε δεξιά στις συνδέσεις, όπως και στο τέλος αυτής της ανάρτησης. Προστέθηκαν παραρτήματα, για την εγκατάσταση, μια λίστα με όλα τα αναγνωριστικά καθώς και το πρόγραμμα σε Μ2000 που διαμορφώνει κανείς την βάση δεδομένων για την βοήθεια, το μηχανισμό ενσωματωμένης βοήθειας του περιβάλλοντος Μ2000.
Το αρχείο pdf έχει και το odf ενσωματωμένο για να μπορεί κανείς να διορθώσει και αυτό, με το LibreOffice 5.

Μικρό εγχειρίδιο της Μ2000