Παρασκευή 10 Μαρτίου 2017

Αναθεώρηση 3 (Έκδοση 8.4)

Η αναθεώρηση 2 έμεινε αναρτημένη για λίγες ώρες και έφτασε η 3 γρήγορα.

Αλλαγές:
1. Στην αναθεώρηση 1 η εντολή Ομάδα είχε βγει από την λίστα "γνωστών" εντολών και δεν χρωματίζονταν στον διορθωτή!
2. Προστέθηκε η δυνατότητα να πατήσουμε Esc όταν κάνουμε αναζήτηση αλφαριθμητικού σε αρχεία...(για να μην περιμένουμε αν δώσουμε λάθος αναζήτηση...- μου έτυχε και το έβαλα και αυτό). Η εντολή Αρχεία ή Files παίρνει μια ή δυο παραμέτρους και στην περίπτωση των δύο, η δεύτερη είναι το αλφαριθμητικό που ψάχνουμε. π.χ. Files "gsb", "WithEvents" ψάχνει όλα τα αρχεία gsb με περιεχόμενο WithEvents. Έψαχνα και βρήκα αυτό: (έτρεχε και σε παλαιότερες εκδόσεις, απλά ήθελα να δω αν θα τρέξει με κάτι αλλαγές που έκανα).
Μπορούμε να το γράψουμε σε ένα τμήμα και να το εκτελέσουμε, αρκεί να έχουμε το Word. Θα μας ανοίξει το Word και μετά από δέκα δευτερόλεπτα θα το κλείσει εκτός και αν το κλείσουμε εμείς. Μετράει το χρόνο που το κλείσαμε! Ενδέχεται να μην μπορεί να το κλείσει γιατί μπορεί να έχουμε ανοίξει κάποια φόρμα διαλόγου.

ExitNow=false
Declare WithEvents Alfa "WORD.APPLICATION"
Title "Minimized", 0
Wait 300
Print "ok"
With Alfa, "Visible", True
Function alfa_quit {
            Print "Why you close Word?"
            ExitNow=True
}
M=0
Every 20 {
      If ExitNow then exit
      M++
      If M>500 then exit
}
Try {
      Method Alfa, "QUIT"
}
Declare Alfa Nothing
if ExitNow then {
      Print format$("Finish  {0:2} sec", M/1000)
} Else {
      Print "Close Word manually"
}
Title "ok",1

3. Διόρθωσα τις εντολές Προσθήκη και Επιστροφή (Append & Return) για τις καταστάσεις (Inventories), όπου τώρα μπορούμε να έχουμε στις εκφράσεις αναφορά στην ίδια κατάσταση.

group k {
      property M=500
}
inventory alfa=1:="alfa","alfa":=2,3:=4,4:=K, 100:=1
Return alfa, alfa$(alfa(100)):=alfa(alfa(3)).M
Print alfa("alfa"), alfa(alfa(3)).M

4. Στην αναθεώρηση 2 μπορούσε κανείς να πειράξει μια ιδιότητα ομάδας, επειδή είναι ομάδα και μπορεί να συγχωνευθεί με μια νέα. Το είχα αφήσει αυτό αλλά το σκέφτηκα και το έκοψα!

Ομάδα Άλφα {
      Ν=30
      Ιδιότητα Μ {αξία}=100
      Ιδιότητα Χ
      Ιδιότητα Όνομα$ {αξία}="Μοναδικό"
}
Άλφα.Χ=500
Τύπωσε Άλφα.Χ
\\ Η Ν δεν είναι ιδιότητα αλλά μπορεί να χρησιμοποιηθεί.
Άλφα.Ν+=100
Τύπωσε Άλφα.Ν
\\ μπορεί να πάρει +=, *= και άλλα
\\ όμως διάβασε παρακάτω!
Δες Οκ {
      \\ αυτό δεν γίνεται για τις ιδιότητες
      \\ εκτός και αν προσθέσουμε τον τελεστή
      Άλφα.Μ++
}
Αν όχι Οκ Τότε Τύπωσε Λάθος$


Ομάδα Άλφα {
      Ομάδα Μ {
            Τελεστής "++" {
                  Ένωσε γονικό [Μ] στη Μ
                  Μ++
            }
      }
}


\\ Τώρα η ομάδα Μ υποστήριζει τον τελεστή
Άλφα.Μ++
Τύπωσε Άλφα.Μ, Άλφα.Όνομα$



5. Για λόγους συμβατότητας, επειδή κάποια προγράμματα παλαιότερα χρησιμοποιούσαν ονόματα τμημάτων (όχι σε ομάδες, δεν υπήρχαν τότε) που σήμερα είναι εντολές, ο διερμηνευτής το βλέπει αυτό και βγάζει εκτός τις εντολές αυτές. Το πρόβλημα που έλυσα ήταν ότι από την γραμμή εντολών...η αλλαγή δεν πέρναγε! Μάλιστα μπορούμε σε ένα τμήμα να έχουμε αλλαγή ονόματος και στην έξοδο από αυτό να επιστρέψει το όνομα σε αυτό που ήταν (μια εντολή δηλαδή και όχι ένα τμήμα).

6.Είχα αφήσει εκτός το θέμα με τις αλφαριθμητικές ιδιότητες, και ειδικότερα στην Θέσε ή Set όπου μπορούμε πριν θέσουμε μια τιμή να την περιορίσουμε ή να σηκώσουμε λάθος (υπάρχει η εντολή Λάθος "μήνυμα", όπου μπορεί να πιαστεί με την Δες Οκ { } ...το Οκ είναι μεταβλητή, αλλά παίζει και το Λάθος ως μεταβλητή μετά την έξοδο από την Δες, καθώς και η Λάθος$ που είναι το μήνυμα.
Σε επόμενη αναθεώρηση τα value$ και  αξία$ θα χρωματίζονται μπλε! (Η Μ2000 έχει δυο σετ χρωμάτων για τις εντολές ανάλογα με την φωτεινότητα του φόντου, και αλλάζουν αυτόματα. Στις ρυθμίσεις όμως μπορούμε να ορίσουμε την Html αντιγραφή στο πρόχειρο αν θα είναι για φωτεινό ή σκοτεινό φόντο...Τον χρωματισμό τον κάνει ο διορθωτής που επίσης έχω γράψει,  και ανοίγει με τη εντολή Συγγραφή ή Σ ή Edit. Αν και στην γραμμή εργασιών δεν βλέπουμε χρωματισμένες εντολές (είναι πιο ρετρό στιλ) με μια εντολή Σ ή Edit χωρίς όνομα τμήματος ή συνάρτησης, θα ανοίξει το διορθωτή στις εντολές που έχει καταγράψει ο διορθωτής από τη γραμμή εντολών. Μπορούμε να τις διορθώσουμε, και στην έξοδο με Esc να τις επιλέξουμε με τα βελάκια, άνω και κάτω, και να τιε εκτελούμε μία κάθε φορά,.

group alfa {
      property a$ {
            value,
            set {
                        value$=left$(value$,5)
            }
      } ="Ok"
}


alfa.a$="111111111111111"
Τύπωσε alfa.a$


Και ελληνικά:

Ομάδα Άλφα {
      Ιδιότητα α$ {
            Αξία,
            Θέσε {
                        αξία$=αρισ$(αξία$,5)
            }
      } ="Ok"
}

Άλφα.α$="111111111111111"
Τύπωσε Άλφα.α$




7. Επίσης λύθηκε άλλη μια ασυμβατότητα με παλαιότερες εκδόσεις:. Στο παράδειγμα παρακάτω μπορούμε από ένα τμήμα ομάδας να αλλάξουμε ένα άλλο τμήμα. Πριν την διόρθωση, γίνονταν μεν αλλά στην έξοδο απο το τμήμα Μέσα, το τμήμα Κάπα γύρναγε στο προηγούμενο! Αυτό θα συμβαίνει πάντα με ομάδες που είναι σε πίνακες με δηλωμένη μια ομάδα για όλα τα στοιχεία. Εκεί τα τμήματα, οι συναρτήσεις και οι τελεστές βρίσκονται σε μια λίστα για όλα. Κάθε αλλαγή είναι πρόσκαιρη (για το αντικείμενο που την κάνει). Τα αντικείμενα αυτά για να εκτελέσουν εντολές πρέπει να γίνουν επώνυμα και αυτό το κάνει ο διερμηνευτής, και αυτό λέγεται "Ανοικτό αντικείμενο", το οποίο δύναται να περάσει τιμές με αναφορά. Όταν τελειώσει με την χρήση του ανοικτού πια αντικειμένου το γράφει ο διερμηνευτής πίσω, μαζεύοντάς το. Έτσι η λίστα ονομάτων παραμένει πάντα μικρή! Βέβαια υπάρχει κάποιο κόστος στο άνοιγμα-κλείσιμο και για το λόγο αυτό έχουμε τις εντολές Για  {} όπου ανοίγουμε αντικείμενα για πολλές εντολές. Εκτός από τα κλειστά βέβαια έχουμε και τα μόνιμα ανοικτά όπως η Ομάδα Άλφα στο παράδειγμα (μόνιμη μέχρι να τερματίσει το τμήμα που την περιέχει). Παρόλα αυτά μπορούμε να την σώσουμε από την "καταστροφή" του τμήματος, αν την αφήσουμε στο σωρό! Εκεί θα γίνει κλειστεί και θα περιμένει να ανοίξει μόνιμα ή να περάσει σε πίνακα (ή σε κατάσταση)

Ομάδα Άλφα {
      Τμήμα Κάπα { Τύπωσε 100}
      Τμήμα Μέσα {
        
            Ομάδα Μ {
                        Τμήμα Κάπα { Τύπωσε 200}
                  }
                  Αυτό<=Μ
                  \\ δουλεύει και έτσι: Αυτό=Μ
            .Κάπα
       }
}
Τμήματα ?
Άλφα.Μέσα
Άλφα.Κάπα


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


Οι εντολές Λίστα και Τμήματα ? δείχνουν μεταβλητές και Τμήματα/συναρτήσεις. Η εντολή Τμήματα χωρίς το αγγλικό ερωτηματικό δείχνει εκτός από τα τμήματα και τις συναρτήσεις και τα αρχεία GSB από όπου μπορούμε να φορτώσουμε και να σώσουμε. Η εντολή Κατάλογος μας δείχνει τα αρχεία και το όνομα φακέλου. Ενώ η εντολή Σύστημα Κατ$ ανοίγει το φάκελο αυτό σε παράθυρο File Explorer για επεξεργασία. Σύστημα Calc ανοίγει την αριθμομηχανή και γενικά η εντολή Σύστημα είναι ανάλογη της Run των Windows. Οι φόρμες έχουν ζουμ, δηλαδή μεγαλώνουν ή μικραίνουν όσο θέλουμε, μεγαλώνοντας τα γράμματα ανάλογα. Για το κείμενο υπάρχει κρυφή μπάρα ολίσθησης, αλλά δουλεύει και το σπρώξιμο, δηλαδή πάτημα του αριστερού πλήκτρου του ποντικιού και τράβηγμα προς τα κάτω για να φέρουμε από πάνω γραμμές και το ανάποδο για να φέρουμε από κάτω γραμμές!
Τα στοιχεία ελέγχου και τις φόρμες τα έχω γράψει και είναι μέρος της Μ2000.









Πέμπτη 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).