Δευτέρα, 24 Απριλίου 2017

Αναθ. 13 (Έκδοση 8.7)

1) Το Break δεν δουλεύει πια σε κώδικα που εκτελούν τα γεγονότα από τις φόρμες. Προτίμησα να το κόψω. Οι φόρμες κλείνουν από το κουμπί (τετράγωνο) πάνω αριστερά, και από το τίτλο, και με alt F4.
2) Στις ομάδες αν ορίζαμε ξανά μια συνάρτηση ή ένα τμήμα με λίστα παραμέτρων σε παρενθέσεις (και όχι απλά με μια διάβασε) έβγαινε λάθος. Διορθώθηκε
3) Διορθώθηκε η Μήκος.Εμφ() όπου για την διάρθρωση δίνει αριθμό δομών (έδεινε αλλά έδινε και το αντικείμενο και στην Τύπωσε έβγαινε λάθος).
4) Ένα παράδειγμα για την Let ή Στη
Η εντολή αυτή ειναι δυο εντολές στην ουσία. Το Στη βήτα=άλφα θα γίνει Βάλε άλφα : Διάβασε βήτα.
Εδώ   Let beta=alfa$("John"), πρώτα θσ βηάλει το αντικείμενο με όνομα john και μετά θα φορτωθεί στη beta (που είχε ήδη κάτι άλλο).

class alfa$ {
      Property name$ {value}
      Property Type$ {value}
      Property Length { Value }
      Set {
            .[name]$<=letter$
            .[Length]<=Doc.Len(.[name]$)
      }
      class:
      module alfa (.[name]$) {
            Document .[name]$
            .[Type]$<=Type$(.[name]$)
      }
}
beta$=alfa$("George")
Print beta.name$
Try {
      beta.name$="John"
}
Print beta.name$
Try {
      beta$=alfa$("John")
}
Print beta.name$
Print beta.Length \\ =6
\\ this can happen
\\ because Let   are two commands: a Push  and a Read command
Let beta=alfa$("John")
Print beta.name$ \\ now is john
Print beta.Length \\ =4
beta$ = " boy"
Print beta.name$ \\ now is "john boy"
Print beta.Length \\ =8
beta$ = " (ok)"
Print beta.name$ \\ now is "john boy"
Print beta.Length \\ =13
Print beta.type$ \\ Document



Σάββατο, 22 Απριλίου 2017

Αναθεώρηση 12 (Έκδοση 8.7) και δυναμικός προγραμματισμός

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

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

Δοκιμάστε με διάφορα n όπως 2 ή 4

\\ Fibonacci Numbers with Dynamic Process

Global PickNew=0
F=lambda A=(1,1) (x) ->{
      PickNew<=False
      if x<=0 then =Array(A) : Exit
      if x<=Len(A) then =Array(A,x-1) : Exit
      PickNew<=True
      For i=Len(A) to x-1 {
            A=Cons(A,(Array(A,i-1)+Array(A,i-2),))
      }
      =Array(A,Len(A)-1)
}
n=1
For i=1 to 20 step n {
      Print i, F(i), PickNew
}
For i=1 to 20 step n {
      Print i, F(i), PickNew
}
M=F
For i=1 to 20 step n {
      Print i, M(i), PickNew
}



Μπορεί να γίνει και έτσι.

F=lambda A=(1,1) (x) ->{
      Link A to A()
      if x<=0 then =A(0) : Exit
      if x<=Len(A) then =A(x-1) : Exit
      For i=Len(A) to x-1 {
            A=Cons(A,(A(i-1)+A(i-2),))
      }
      =A(Len(A)-1)
}
n=1
For i=1 to 20 step n {
      Print i, F(i)
}
For i=1 to 20 step n {
      Print i, F(i)
}
M=F
For i=1 to 20 step n {
      Print i, M(i)
}

 

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

Αναθεώρηση 11 (Έκδοση 8.7)

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

2) Διορθώθηκε το Match("A") ή Ταύτιση("Π")  για να δίνει -1 (Αληθές) αν έχουμε πίνακα στη κορυφή του σωρού.
Τώρα παίζει το παρακάτω χωρίς την ListLit (δες προηγούμενο μήνυμα)
Το () είναι κενός πίνακας, το (1,) είναι πίνακας με ένα στοιχείο, το (1,2) πίνακας με δυο
Το ((1,2),(3,4)) είναι πίνακας με δυο στοιχεία πίνακες με δυο στοιχεία).  Στη γραμμή παρακάτω ζητάμε από το πίνακα το δεύτερο στοιχείο (το πρώτο είναι στο 0) και παίρνουμε τον πίνακα (4,5) και από αυτόν ζητάμε το δεύτερο στοιχείο, και παίρνουμε το 5.

Τύπωσε Πίνακας(Πίνακας(((1,2,3),(4,5)),1),1)
 Το x=(Number,) παίρνει τον αριθμό από το σωρό (αν δεν έχει θα βγει λάθος) και τον βάζει σε έναν πίνακα ενός στοιχείου στην θέση 0. Προσέξτε το κόμμα. Αν δεν υπήρχε θα ήταν απλά η έκφραση, αλλά με το κόμμα ξέρει ο διερμηνευτής ότι η προηγούμενη έκφραση θα πάει σε πίνακα, και συνεχίζει, δεν βρίσκει άλλο και το αφήνει έτσι!



Range =lambda (x) -> {
      L=Lambda M=1 ->{=M:M++}
      Dim A(x)<<L()
      =A()
}


Goal=Lambda (op) ->{
       'Goal take three parameters, but 2nd and 3rd can be number or Array object
      If Match("N") Then {
            x=(Number,)
      } Else.If Match("A") Then {
             Read x
       } Else Error "(second argument Not a number Or Array)"
   
      If Match("N") Then {
            y=(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,(1,2,3),3)
Print Goal(Mult,Range(30),3)
Print Goal(Mult,Range(10),5)
Print Goal(Mult,5,Range(10))
Print Goal(Mult, Goal(Mult,5,Range(10)),(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,(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),(3,6,9), (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))


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

4) Η φόρμα έλεγχος τώρα δείχνει αν κάτι είναι συνάρτηση ή όχι, αν έχουμε λάμδα δείχνει τον κώδικα (παλιότερα δεν το έδειχνε), αν είναι νήμα δείχνει το κώδικα και η βηματική εκτέλεση τα σταματάσει σε αναμονή (σταματάει τον εσωτερικό TaskManager) και με συνεχόμενο πάτημα, βλέπουμε όλα τα νήματα να τρέχουν (πιο αργά) και φαίνεται και ο κώδικάς τους καθώς τρέχουν.
Η φόρμα πήρε περισσότερο χώρο για το αριστερό πάνω μέρος (γράφεται το τμήμα/συνάρτηση/Νήμα, αμέσως από κάτω η εντολή που εκτελείται και αμέσως από κάτω το υπόλοιπο της εντολής.
Η μεταβλητή τικ ή tick δίνει το ρολόι του TaskManager. Κάθε νήμα έχει έναν αριθμό και το βλέπουμε στη φόρμα έλεγχος. Και το Main.Task είναι νήμα.
(σε προηγούμενες εκδόσεις όταν έτρεχαν νήματα δεν βλέπαμε κώδικα)



test "here"
A$=lambda$ -> {
      Print 10201
      print 455, tick
      ="ok"
}
N$=""
thread {
      aa()
      N$= A$()
} as M interval 100


Main.Task 50 {
      If keypress(32) then exit
}


Sub aa()
      Print "Wow"
End Sub


Τετάρτη, 19 Απριλίου 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))


Τρίτη, 18 Απριλίου 2017

Εγχειρίδιο της Μ2000 - Τεύχος 30ο

17.2 Πλήκτρο (Button)

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

Η γραμματοσειρά, το μέγεθος των γραμμάτων,  και αν θα είναι φαρδιά ή όχι (bold) προγραμματίζονται με την μέθοδο "FontAttr"

Ένα πλήκτρο έχει ένα τίτλο, "Caption" που εμφανίζεται αρχικά με άσπρο χρώμα, και έχει δυο χρώματα, ένα καφέ και ένα πράσινο, για φόντο, ανάλογα αν είναι επιλεγμένο ή όχι. Τα χρώματα μπορούν να αναπρογραμματιστούν (μέθοδος "Colors") και να επανέλθουν στην αρχική τους τιμή (μέθοδος "ColorsReset") κατά βούληση

Κάθε φορά που επιλέγουμε το button παίρνει την εστίαση εκτός και αν το έχουμε ανενεργό (Ιδιότητα "enabled") ή το έχουμε κλειδωμένο (Ιδιότητα "locked").

Κάθε πλήκτρο είναι μια παραλληλόγραμμη επιφάνεια, που σχεδιάζεται με παραλληλόγραμμο με γωνίες κανονικές ή στρογγυλεμένες (μέθοδος "curve" με τιμή αναλογία  διαστάσεων και καμπύλης), αλλά μπορεί να είναι και διάφανο (μέθοδος "transparent"). Η διαφάνεια δουλεύει με αντιγραφή του φόντου, άρα αν έχουμε πλήκτρο πάνω σε πλήκτρο δεν θα βλέπουμε το σκεπασμένο πλήκτρο αλλά το επίπεδο της φόρμας κάτω από τα πλήκτρα. Αφαιρούμε την διαφάνεια με το "transparentoff"

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

Μπορούμε να ορίσουμε αναδίπλωση λέξεων "WrapText" στο κείμενο που γράφουμε για Caption, αλλά το αναδιπλωμένο κείμενο ακουμπάει στην άνω πλευρά, και όχι το κέντρο, οπότε φέρνουμε τον παίκτη στο μέγεθος που θέλουμε.

Με χρήση του "transparent" και χωρίς να χρησιμοποιούμε τo γεγονός Click() μπορούμε να χρησιμοποιήσουμε το στοιχείο ως ετικέτα (label). Το ίδιο μπορούμε να κάνουμε αν χρησιμοποιήσουμε το "Locked" με τιμή 1 (μη μηδενική), θα μπορεί να αλλάζει "Caption" αλλά δεν θα δέχεται γεγονότα (κλικ).

Κάποια φορά θέλουμε το πλήκτρο να είναι σκιασμένο, και αυτό γίνεται με την "Shadow" και ένα χρώμα για τα γράμματα (για να φαίνεται μη ενεργό). Επαναφέρουμε το στοιχείο με τη "ShadowOff"

Κάθε πλήκτρο έχει έναν χρονιστή ο οποίος αν πάρει τιμή μεγαλύτερη του 0 τότε στέλνει ένα γεγονός όταν τα χιλιοστά δευτερολέπτου που του δώσαμε περάσουν, και συνεχίζει στο επόμενο διάστημα να στέλενει ένα γεγονός. Το γεγονός λέγεται Blink(), και γυρνάει 0 την μια φορά και -1 την άλλη.

Ένα πλήκτρο συνδέεται με τα άλλα στοιχεία με το tab (shift-tab), και δέχεται με τρεις τρόπους το "πάτημα" ή κλικ: Με το Enter όταν έχει την εστίαση, με αριστερό κλίκ εφόσον έχει την εστίαση, και με σύρσιμο της ετικέτας του δεξιά.

στο παράδειγμα που ακολουθεί, έχουμε τέσσερα πλήκτρα, το Ένα, Δϋο, Τρία και Τέσσερα. Όταν κάνουμε κλικ στο Ένα ή το σύρουμε δεξιά τότε σκιάζεται το Δύο και κλειδώνει, το Τρία έχει διάφανο φόντο και  ξεκλειδώνει το Δύο. Το Τέσσερα έχει αναδίπλωση κειμένου, και παράλληλα έχει το χρονιστή ενεργό και αλλάζει το χρώμα του Ένα και επιπλέον βάζει στο τίτλο της φόρμας την ώρα.
Όταν το Δύο κλειδώνει τότε το Tab το αφήνει για το επόμενο, όταν το ξεκλειδώνουμε το βάζει πάλι στη σειρά του. Το τρία έχει διάφανο φόντο και γίνεται χρήση των GotFocus/LostFocus.


Όρισε Άλφα Φόρμα
\\ η φόρμα θα είναι σταθερή, δηλαδή χωρίς γεγονός resize

Σημ 1 : Με Άλφα, "Title", "Φόρμα Άλφα"
\\ Το τ$ αν και φαίνεται σαν μεταβλητή αλφαριθμητική
\\ είναι αντικείμενο που συνδέεται με την ιδιότητα Title
\\ το συγκεκριμένο και διαβάζεται για γράφεται.
Με Άλφα, "Title" ως τ$
τ$="Φόρμα Άλφα"
Επίπεδο Άλφα {
      \\ αντί να χρησιμοποιήσουμε την Μέθοδο Άλφα, "move"....
      \\ χρησιμοποιούμε την Παράθυρο.
      \\ ο αριθμός 12 είναι το μέγεθος χαρακτήρων πάνω στο επίπεδο
      Παράθυρο 12,8000,8000
      Φόντο 1,5
      θέση 4000,4000
      Κύκλος Γέμισμα 7, 3000,1.5,7
}
Όρισε Ένα Πλήκτρο Φόρμα Άλφα
Όρισε Δύο Πλήκτρο Φόρμα Άλφα
Όρισε Τρία Πλήκτρο Φόρμα Άλφα
Όρισε Τέσσερα Πλήκτρο Φόρμα Άλφα
Μέθοδος Ένα,"move", 300, 1000, 3000, 600
Μέθοδος Δύο,"move", 300, 2000, 3000, 600
Μέθοδος Τρία,"move", 300, 3000, 3000, 600
Μέθοδος Τέσσερα,"move", 300, 4000, 3000, 700
Με Τέσσερα,"Caption",{Είμαι το Τέσσερα
---------------}
Με Τέσσερα,"WrapText", 1
\\ Με Τέσσερα, "Blink", 500
\\ και εδώ συνδέουμε μια μεταβλητή με την ιδιότητα
Με Τέσσερα, "Blink" ως Ρυθμός
Ρυθμός=500
Μέθοδος Δύο, "curve", 2.5
Μέθοδος Τρία,"transparent"
Μέθοδος Τρία,"Colors", 7
Στοπ_Blink=Ψευδες
Συνάρτηση Ένα.Click {
      τ$="Φόρμα Άλφα: Ένα"
            Μέθοδος Δύο,"Shadow", 7
}
Συνάρτηση Δύο.Click {
      τ$="Φόρμα Άλφα: Δύο"
}
Συνάρτηση Τρία.GotFocus {
      Μέθοδος Τρία, "Colors", 15
}
Συνάρτηση Τρία.LostFocus {
      Μέθοδος Τρία, "Colors", 7
}
Συνάρτηση Τρία.Click {
      τ$="Φόρμα Άλφα: Τρία"
      Μέθοδος Δύο,"ShadowOff"
}
Συνάρτηση Τέσσερα.Click {
      τ$="Φόρμα Άλφα: Τέσσερα"
      Στοπ_Blink~
      Ρυθμός=-500*Στοπ_Blink \\ 0 ή -1
}
\\ Μπορούμε με το γεγονός Blink να ελέγχουμε άλλα στοιχεία
\\ λειτουργεί σαν Timer σε φόρμα, και δεν έχει να κάνει με νήματα
\\ κάθε φορά που το Timer ολοκληρώνει το μέτρημα δίνει το γεγονός
\\ Αν μηδενίσουμε το Timer τότε δεν στέλνει γεγονός Blink
Συνάρτηση Τέσσερα.Blink {
      Διάβασε ΆλλαγηΧρ
      τ$="Φόρμα Άλφα: Τέσσερα "+Γραφή$(Τώρα,"hh:mm:ss")
      Αν ΆλλαγηΧρ Τότε {
            Μέθοδος Ένα,"Colors", #ff7700
      } Αλλιώς Μέθοδος Ένα,"Colors", #0077ff
      Μέθοδος Ένα,"Show"
}
\\ Ανοίγουμε τη φόρμα ως Modal, και θα κλείσει από το πάνω αριστερό τετραγωνάκι
Μετα 2000 {
      Μέθοδος Τρία,"ColorsReset"
      Μέθοδος Τρία,"transparentOff"
}
Μετα 4000 {
      Μέθοδος Τρία,"transparent"
}
Μέθοδος Άλφα, "Show",1
Όρισε Άλφα Τίποτα




Γεγονότα του Πλήκτρου:
Blink(κ) όπου κ μια φορά 0 και μια φορά -1 (εναλλαγή αληθές-ψευδές)
Click
GotFocus και LostFocus (όταν έχει φόντο διάφανο, νέο στο 8.7 αναθ. 8)

Ιδιότητες
Caption  κείμενο (διαβάζεται και αλλάζει)
WrapText  τιμή 0 (Ψευδής) ή μη μηδενική (Αληθής) για αναδίπλωση λέξης (διαβάζεται και αλλάζει)
Blink παίρνει τιμή το χρονικό διάστημα ανά χιλιοστά δευτερολέπτου (μόνο αλλάζει)
Top θέση άνω (διαβάζεται και αλλάζει)
Left θέση αριστερά (διαβάζεται και αλλάζει)
Locked με Αληθές κλειδώνει το πλήκτρο (το κάνει και η μέθοδος "Shadow") (διαβάζεται και αλλάζει)
Enabled με Ψευδές πριν ανοίξει η φόρμα δεν εμφανίζεται το πλήκτρο (διαβάζεται και αλλάζει)
Index ο αριθμός του πλήκτρου αν ανήκει σε πίνακας πλήκτρων.

Μέθοδοι
Move παίρνει δυο θέση Άριστερά, θέση Άνω και προαιρετικά Πλάτος και Ύψος (σε twips)
Curve παίρνει μια παράμετρο έναν αριθμό κινητής υποδιαστολής μεγαλύτερο από 0,08
Colors  παίρνει χρώμα γραμμάτων και προαιρετικά χρώμα φόντου και χρώμα φόντου για την επιλογή.
ColorsReset φαίρνει τα χρώματα στα εξ ορισμού.
FontAttr γραμμαοσειρά και προαιρετικά μέγεθος, φαρδιά
Show ανανεώνει το πλήκτρο
Transparent προσθέτει την διαφάνεια φόντου
TransparentOff αφαιρεί την διαφάνεια φόντου
Shadow Χρώμα_Γραμμάτων βάζει και το Locked=Αληθές
ShadowOff βγάζει το Locked και βάζει το επιλεγμένο χρώμα κειμένου.

Στις παρακάτω εικόνες έχει μπει η Επιφάνεια 200 (διάφανη η κονσόλα στο 200/255*100%)
Και στα τρία λειτουργικά έχουμε την ίδια μορφή παραθύρου! Οι κονσόλες έχουν διαφορετικές γραμματοσειρές από επιλογή. Τα Windows και στις δυο περιπτώσεις δεν έχουν υποστήριξη ελληνικών για μη Unicode προγράμματα. Τα αρχεία προγραμμάτων της M2000 είναι σε UTF-8, και διορθώνονται και από το WordPad, επειδή αναγνωρίζει αυτόματα τη κωδικοποίηση.
Και τα τρία λειτουργικά έτρεξαν μαζί, σε έναν υπολογιστή (με βάση το Ubuntu Studio 16.04).

Εικόνα από Windows 8, 64 Bit (σε Virtual Box)

Εικόνα από Windows 7, 32 Bit (Virtual Box)
Εκτέλεση με Wine,  σε Ubuntu Studio 16.04 64 bit.
Εκτέλεση σε XP