Πέμπτη 17 Οκτωβρίου 2024

A zip function for lists

module zip_function {
const rightjustify=3, normaljustify=0
function zip(f) {
n=stack.size
if n=0 then =(,):exit
mL=infinity
// array to save arrays
dim a(1 to n)
for i=1 to n
read a(i)
ml=min.data(len(a(i))-1, ml)
next
if ml<0 then =(,):exit
// array for return value
dim b(0 to ml)
for k=0 to ml
for j=n to 1
push a(j)(k)
next
// [] is a function. return the current stack object,
// leave an empty stack object as the current stack object
// !s where s is a stack object in a parameter list leave all
// items of that stack to the parameter list (which is a stack object)
b(k)=f(![])
next
=b()
}

add=lambda ->{
sum=0
while not empty
if isnum then
sum+=number
else
drop
end if
end while
=sum
}
// double coma ,, at print list is a new line
? (1,2,3),, (10,20,30),, (2, 2, 200)
m=zip(add, (1,2,3), (10,20,30), (2, 2, 200))
//clipboard m#str$()
? m#str$()="13 24 233"
? m#str$()

concat=lambda ->{
string all
while not empty
if isnum then
all+=""+number
else
all+=letter$
end if
end while
=all
}
? $(rightjustify), (1,2,3),, (10,20,30),, (2, "X", 200),, ("aaa",2,3,4), $(normaljustify),,
m=zip(concat, (1,2,3), (10,20,30), (2, "X", 200), ("aaa",2,3,4))
? m#str$()="1102aaa 220X2 3302003"
? m#str$()
m=zip(add, (1,2,3), (10,20,30), (2, "X", 200), ("aaa",2,3,4))
? m#str$()="13 24 236"
? m#str$()
m=zip(add, (1,2,3))
? m#str$()
m=zip(add,(1,2,3), (,))
? Len(m)=0
m=zip(add)
? Len(m)=0
}
zip_function

Τρίτη 15 Οκτωβρίου 2024

New addition for M2000 at rosettacode.org

https://rosettacode.org/wiki/Append_numbers_at_same_position_in_strings#M2000_Interpreter 

There are 438 tasks for M2000 Interpreter. Look at the end of this page:

https://rosettacode.org/wiki/Category:M2000_Interpreter


This is a small program:

module testme {
List1=(1,2,3,4,5,6,7,8,9)
List2=(10,11,12,13,14,15,16,17,18)
List3=(19,20,21,22,23,24,25,26,27)
List=(,)
k=each(list1)
l=each(list2)
m=each(list3)
while k, l, m
append List, (array$(k)+array$(l)+array$(m),)
end while
print "list1 = ["+List1#str$(",")+"]"
print "list2 = ["+List2#str$(",")+"]"
print "list3 = ["+List3#str$(",")+"]"
print "list  = ["+List#str$(",")+"]"
}
TestMe

Variable List has color blue because there is a statement List. The editor use the blue color for known identifiers. So for Module testme list used as variable (pointer to array). We can use the statement List, which show variables. If we make a Module List inside testme then the command List skipped as module List. Run m2000.exe (the M2000 interpreter) and write: Edit C then press enter and copy these lines then press Esc and write C and press enter (c or C is the same for M2000)

global k=100
module testList {
A=100+k
module list {
? "this is module list"
}
list
@list
}
testlist
? "return from testlist"
list

We get this:

this is module list

K = 100, C.TESTLIST.A = 200

return from testlist

K = 100









Κυριακή 29 Σεπτεμβρίου 2024

Αλγόριθμοι – Προγραμματισμός (τεύχος 1)

 

Αλγόριθμοι – Προγραμματισμός


Εισαγωγή

 

Στόχος αυτού του δοκιμίου είναι «Η ανάπτυξη της αλγοριθμικής σκέψης του παιδιού με την διαδικασία της κατασκευής προγραμμάτων σε ηλεκτρονικό υπολογιστή».

Όσο και να προσπαθούμε να πείσουμε τα παιδιά να «προγραμματίσουν» δεν θα βρούμε εύκολα ανταπόκριση.  Το πραγματικό πρόβλημα είναι η έλλειψη αφαιρετικής σκέψης. Με την αφαιρετική σκέψη το παιδί αντιλαμβάνεται το γενικό ενώ η αλγοριθμική σκέψη σπάει το πρόβλημα από το γενικό στο επιμέρους. Ο προγραμματισμός είναι η επιλογή εντολών μιας γλώσσας προγραμματισμού που εκτελεί αυτό που σε γενικές γραμμές λέει ο αλγόριθμος. Μπορούμε να δούμε τον αλγόριθμο ως το προσχέδιο του προγράμματος. Η γλώσσα προγραμματισμού αποτελεί το εργαλείο, που πραγματοποιεί τη σκέψη μας κατά την εκτέλεση στην υπολογιστική μηχανή, τον προσωπικό υπολογιστή (ορισμός από τη δεκαετία του ’80), ή ηλεκτρονικό υπολογιστή (ορισμός προ της δεκαετίας του ’80).

Για το σκοπό του δοκιμίου, την ανάπτυξη της αλγοριθμικής σκεψης του παιδιού,  θα προταθεί μια μέθοδος εκπαίδευσης, που στηρίζεται πρώτα στην αφαιρετική σκέψη, μετά στην αλγοριθμική σκέψη και τέλος στον προγραμματισμό.

Το δοκίμιο στοχεύει σε ενήλικες που θέλουν να δοκιμάσουν τρόπους μαθησιακής προσέγγισης ειδικότερα στον όρο της Αλγοριθμικής Σκέψης. Ο προγραμματισμός θα χρησιμοποιηθεί για την τεκμηρίωση της σκέψης.

Αφαιρετική Σκέψη

Κάθε παιδί την κάθε στιγμή έχει ένα βαθμό αφαιρετικής σκέψης, μια ικανότητα αφαίρεσης της λεπτομέρειας προς το γενικό, σ' αυτό που ταιριάζει. Όταν το παιδί παίζει με ένα «ψεύτικο» όπλο μάχη, φαίνεται σε μας σαν αφαίρεση, βάζοντας τον εαυτό του ως πολεμιστή, σ' αυτό που νομίζει ότι είναι πολεμιστής. Τι είναι «πολεμιστής» για το παιδί; Η απλή του σκέψη είναι ότι αυτός που έχει όπλο είναι πολεμιστής! Το παιδί δεν έχει καμία ιδέα περί εχθρού, απλά γενικά καθένας που μπαίνει στο χώρο του παιχνιδιού του μπορεί να του φανεί εχθρός!  Η αντίληψη του παιδιού περιορίζεται από την έλλειψη πληροφορίας ή και στοιχείων που του καθορίζουν την τωρινή κατάσταση.  Αυτή η έλλειψη δεν αποτελεί «Αφαίρεση». Όταν όμως ζητήσουμε από το παιδί να μας φέρει από τα παιχνίδια του να δούμε ό,τι παιχνιδι έχει με ρόδες, και αφού το κάνει, του πούμε πώς όλα αυτά τα λέμε οχήματα, τότε έχει ιδέα μιας γενικότητας, του όρου 《οχήματα, κι αυτό γίνεται άμεσα μέρος της δικής του αφαιρετικής σκέψης.

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

Πρόβλημα - Παράδειγμα

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

Αφαιρετική Σκέψη περί Ακέραιων

Πρώτα πρέπει να ορίσουμε τι είναι ακέραιος αριθμός. Εδώ ο ορισμός λέει ότι οι ακέραιοι αριθμοί ανήκουν σε ένα σύνολο, όπου για κάθε Ν αριθμό υπάρχει ο Ν+1και ο Ν-1, με κεντρικό αριθμό το 0, ώστε για Ν=0 το Ν-1 είναι το -1 και το Ν+1 είναι το +1. Ο αριθμός 3 ανήκει στο σύνολο, γιατί βγαίνει με το 0+1+1+1 ή +3, ή απλά 3 (το + λέμε ότι εννοείται). Υπάρχουν αριθμοί που δεν ανήκουν στο σύνολο αυτό, όπως για παράδειγμα το μισό του 3, δηλαδή το ένα και μισό (όπου δυο φορές γίνεται: ένα και μισό και ένα και μισό άρα τρία), επειδή από το 0, για το σύνολο των ακεραίων, μπορούμε να προσθέτουμε μονάδες αλλά όχι μισή μονάδα!  Αυτός ο βαρύς, για τα παιδιά, ορισμός είναι προϋπόθεση για την κατανόηση της λύσης του προβλήματος. Η αφαίρεση εδώ είναι ότι το εκατό θα είναι 0+1+1….+1, δηλαδή εκατό φορές από το 0 αυξάνουμε κατά ένα, και δεν χρειάζεται να το αποδείξουμε, μας αρκεί το ότι δουλεύει η απόδειξη για 1, 2, 3. Επίσης, το συμπέρασμα του ορισμού είναι ότι για κάθε ξεχωριστό ακέραιο υπάρχει ο προηγούμενος κατά ένα και ο επόμενος κατά ένα, όπου και οι δυο είναι μοναδικοί! Έτσι για το 5 υπάρχει το 4 και το 6, ως προηγούμενος και επόμενος ακέραιος αντίστοιχα.

Για την επίλυση του προβλήματος, το άθροισμα των ακεραίων μεταξύ δυο ακεραίων, πρέπει να σκεφτούμε ότι από τον Α ακέραιο στον Β ακέραιο, εφόσον ο Α είναι μικρότερος του Β, θα υπάρχουν τόσοι ακέραιοι όσες μονάδες πρέπει να βάλουμε στον Α για να φτάσουμε στον Β χωρίς την τελευταία μονάδα. Αν ο Α είναι μεγαλύτερος του Β, τότε μπορούμε να αλλάξουμε τις τιμές τους και να έχουμε τον Α μικρότερο του Β.

Αλγοριθμική Σκέψη - Σχεδιασμός

Ένας τρόπος να ξεμπερδεύουμε γρήγορα με τον αλγοριθμικό σχεδιασμό είναι να κάνουμε μικρά βήματα ελέγχου, πριν ολοκληρώσουμε τη σκέψη μας. Αυτά τα βήματα ελέγχου γίνονται με την επιλογή των αρχικών συνθηκών. Έστω ότι έχουμε Α=4 και Β=5, πόσοι ακέραιοι είναι μεταξύ Α και Β (χωρίς τα Α και Β); Λέμε ότι από το Α στο Β χρειαζόμαστε μόνο μια μονάδα, και το σκεπτικό μας είναι να αφαιρέσουμε την τελευταία μονάδα, άρα το Α+1 είναι το Β, άρα οι μονάδες έχουν σύνολο 1 (είναι μια) και αφαιρούμε ένα, άρα έχουμε 0 ακέραιους. Έστω ότι έχουμε Α=2 και Β=5, τότε θα έχουμε τους 2+1, 2+1+1 ή 3 και 4 μεταξύ των 2 και 5, και με τον υπολογισμό μας θα έχουμε από το Α στο Β συνολικά Α+1+1+1 ή τρεις μονάδες και αφαιρούμε μια, άρα έχουμε δυο ακέραιους (3 και 4).

Τώρα μας ενδιαφέρει να προσθέσουμε τους ακέραιους. Στο προηγούμενο παράδειγμα για  Α=2 και Β=5 βρίσκουμε διαδοχικά τα 3 και 4 και κάθε φορά τα προσθέτουμε στη ΣΟΥΜΑ. Η ΣΟΥΜΑ έχει αρχική τιμή 0 (δεν έχουμε αθροίσει τίποτα). Κάθε φορά που βγαίνει ένας ακέραιος (από όσους υπάρχουν μεταξύ Α και Β) θα τον προσθέτουμε στη ΣΟΥΜΑ, δηλαδή στη ΣΟΥΜΑ βάζουμε νέα τιμή το άθροισμα ΣΟΥΜΑ συν Ακέραιος.

Τέλος στην αλγοριθμική μας σκέψη πρέπει να σκεφτούμε πότε ο αλγόριθμος δεν μπορεί να εκτελεστεί! Αν έχουμε Α=Β, για παράδειγμα, Α=4 και Β=4 δεν μπορούμε να ικανοποιήσουμε τη συνθήκη Α<Β (ή αν ήταν Β<Α θα αλλάζαμε τιμές μεταξύ τους στα Α και Β για να βγουν με τη σωστή σειρά, Α<Β). Η αντίθετη της Α=Β είναι η Α<>Β (το Α διάφορο του Β, είτε μεγαλύτερο, είτε μικρότερο)

Προγραμματισμός

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

Προϋποθέσεις για την ετοιμασία του προγράμματος είναι:

  1. Να έχουμε επιλέξει τα ονόματα των μεταβλητών, δηλαδή αυτών που θα κρατάνε τιμές. Εδώ οι μεταβλητές μας θα έχουν τα ονόματα Α, Β, Σούμα και μια ακόμα Ι όπου θα τη χρειαστούμε για να πάρει τιμές διαδοχικά από το Α+1 μέχρι και το Β-1.
  2. Να έχουμε επιλέξει τι θα εμφανιστεί ως πρώτο μήνυμα. Σε αυτό το βήμα: «Εύρεση αθροίσματος ακεραίων μεταξύ δυο ακεραίων Α και Β».
  3. Να έχουμε επιλέξει τις εντολές για εισαγωγή των Α και Β, μαζί με τις λεζάντες τους, όπως «Τιμή στο Α:» και «Τιμή στο Β:».
  4. Να κάνουμε έλεγχο, αν Α=Β και τοτε αν είναι Αληθής η σύγκριση, να τυπώσουμε «Αδύνατον, δεν έχουμε διαφορετικούς ακεραίους Α και Β» και μετά να κάνουμε Έξοδο από το πρόγραμμα.
  5. Να δούμε, αν το Β<Α (το Β μικρότερο του Α) και αν είναι Αληθής η σύγκριση, τότε να αλλάξουμε τιμές στα Α και Β και να το δείξουμε με τις λεζάντες όπως στο (3).
  6. Να κάνουμε έλεγχο Α+1=Β και αν είναι Αληθής η σύγκριση, να τυπώσουμε «Δεν υπάρχουν μεταξύ <τιμής Α> και <τιμής Β> ακέραιοι.  Εδώ μπορούμε να τυπώσουμε τη Σούμα που θα είναι μηδέν. Αν είναι Ψευδής ο έλεγχος, τότε πάμε στο (7), αλλιώς τερματίζει το πρόγραμμα
  7. Στο βήμα αυτό διατρέχουμε τις τιμές από Α+1 έως Β-1 μέσω της Ι, στην εντολή: Για Ι=Α+1 έως Β-1, και βάζουμε το κάθε Ι στη Σούμα με το Σούμα+=Ι (που είναι ίδιο με το Σούμα=Σούμα+Ι).
  8. Στο τέλος βάζουμε την εντολή Τύπωσε, η οποία θα μας δώσει τη Σούμα. Επίσης ενώ δεν το ζητάει η άσκηση, εδώ έχουμε βάλει το αποτέλεσμα χωρίς να διατρέχουμε τις τιμές και να τις αθροίζουμε, απ’ ευθείας με μαθηματικό τύπο.

Επισημάνσεις

Ο υπολογισμός με τον τύπο ((Β-Α)/2+Α)*(Β-Α-1) δε λειτουργεί, αν Α=Β ή Α>Β. 

Ο υπολογισμός βασίζεται στο σκεπτικό ότι το άθροισμα όλων των ακέραιων αριθμών από 1 έως Ν είναι το Ν*(Ν+1)/2. Για παράδειγμα το άθροισμα των 1, 2, 3 είναι το 3*4/2, και σχετίζεται με το μισό εμβαδόν ενός παραλληλόγραμμου  3 Χ 4.

Ο τύπος ((Β-Α)/2+Α)*(Β-Α-1) γράφεται (Β-Α)*(Β-Α-1/2+Α*(Β-Α-1), έτσι αν Α=3 και Β=6 τότε έχουμε (6-3)*(6-3-1)/2+3*(6-3-1), ή 3*2/2+3*2 ή 3+6 ή 9, και πράγματι μεταξύ Α και Β είναι οι ακέραιοι 4 και 5, με άθροισμα το 9.

Για Α=-3 και Β=11  θα έχουμε ((11--3)/2-3)*(11--3-1), ή (14/2-3)*13 ή 4*13 ή 52. Πράγματι αν προσθέσουμε -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 θα πάρουμε το 52.

 

Κώδικας σε διερμηνευτή Μ2000

 

Ακέραιος Α, Β, Ι
Μακρύς Σούμα
Τύπωσε "Εύρεση αθροίσματος ακεραίων μεταξύ δυο ακεραίων Α και Β"
Εισαγωγή "Τιμή στο Α:", Α
Εισαγωγή "Τιμή στο Β:", Β
Αν Α=Β Τότε Τύπωσε "Αδύνατον, δεν έχουμε διαφορετικούς ακέραιους Α και Β": Έξοδος
Αν Β<Α τότε
             Άλλαξε Α, Β
             Τύπωσε "Τιμή στο Α:"+Α
             Τύπωσε "Τιμή στο Β:"+Β
Τέλος Αν
Αν Α+1=Β Τότε
             Τύπωσε "Δεν υπάρχουν μεταξύ "+Α+" και "+Β+" ακέραιοι"
Αλλιώς
             Για Ι=Α+1 έως Β-1
                         Σούμα+=Ι
             Επόμενο
Τέλος Αν
Τύπωσε "Άθροισμα:"+Σούμα
Τύπωσε "Υπολογισμός:"+(((Β-Α)/2+Α)*(Β-Α-1))

 

Κώδικας σε διερμηνευτή Python


Α = Β = Ι = Σούμα = 0
print("Εύρεση αθροίσματος ακεραίων μεταξύ δυο ακεραίων Α και Β")
Α=int(input("Τιμή στο Α:"))
Β=int(input("Τιμή στο Β:"))
if Α==Β:
    print("Αδύνατον, δεν έχουμε διαφορετικούς ακέραιους Α και Β")
    exit()
if Β<Α:
    Α, Β = Β, Α
    print("Τιμή στο Α:", Α)
    print("Τιμή στο Β:", Β)
if Α+1==Β:
    print("Δεν υπάρχουν μεταξύ", Α, "και", Β, "ακέραιοι")
else:
    for Ι in range(Α+1, Β):
        Σούμα+=Ι
print("Άθροισμα:", Σούμα)
print("Υπολογισμός:", int(((Β-Α)/2+Α)*(Β-Α-1)))

Run python program here


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


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

Version 12, Revision 36

A small bug fixed (one line of code), so now a copy of an event object copy the enable state (which we can alter using the keywords Hold and Release)

The example bellow didn't print number a, because the hold state copied to c.

event a {
read a
function {
print a
}
}
event a hold
c=a
call event c, 4


This is an example of use of an event object as a visitor. The pointer()  (used without parameter) return the null object (is a group with type Null, which we can't add anything, and we can merge to). Using the Null object we always have pointer to point something. This example has no use of Hold or Release on event, but we can insert Event PrintAnum Hold after the Event PrintAnum New PrintThis() to see what happen.

Report {
      Tree traversal
             1
            / \
           /   \
          /    \
         2      3
        / \    /
       4   5   6
      /      / \
     7      8   9

}
Pen 15 {Print "OOP - Event object as visitor"}
Module OOP {
    Class Node {
    Public:
        x, LeftNode=pointer(), RightNode=pointer()
        Module preorder (visitor){
            T->This
            printtree(T)
            sub printtree(T as pointer)
                If T is type Null then Exit sub
                call event visitor, T=>x
                printtree(T=>LeftNode)
                printtree(T=>RightNode)
            end sub
        }
        Module inorder (visitor){
            T->This
            printtree(T)
            sub printtree(T as pointer)
                If T is type Null then Exit sub
                printtree(T=>LeftNode)
                call event visitor, T=>x
                printtree(T=>RightNode)
            end sub
        }
        Module postorder (visitor) {
            T->This
            printtree(T)
            sub printtree(T as pointer)
                If T is type Null then Exit sub
                printtree(T=>LeftNode)
                printtree(T=>RightNode)
                call event visitor, T=>x
            end sub
        }
        Module level_order (visitor){
            T->This
            Stack New {
                printtree(T)
                if empty then exit
                Read T
                Loop
            }
            sub printtree(T as pointer)
                If T is type Null else
                  call event visitor, T=>x
                  Data T=>LeftNode, T=>RightNode
                end if
            end sub
        }
        remove {
          Print "Node removed ";.x
        }
    Class:
        \\ after class:  anything exist one time,
        \\ not included in final object
        Module Node {
            Read .x
            \\ read ? for optional values
            Read ? .LeftNode, .RightNode
        }
    }
    \\ NodeTree return a pointer to a new Node
    Function NodeTree {
        \\ ![] pass currrent stack to Node()
        ->Node(![])
    }

    Tree=NodeTree(1, NodeTree(2,NodeTree(4, NodeTree(7)), NodeTree(5)), NodeTree(3, NodeTree(6, NodeTree(8), NodeTree(9))))
    Event PrintAnum {
        read x
    }
    Function PrintThis(x) {
          Print x;" ";
    }
    Event PrintAnum New PrintThis()
    printnum=lambda PrintAnum (title$) -> {
        Print
        Print title$;
        =PrintAnum
    }
    Tree=>preorder printnum("preorder:  ")
    Tree=>inorder printnum("inorder:   ")
    Tree=>postorder printnum("postorder:   ")
    Tree=>level_order printnum("level-order: ")
    Print
    Print "Removing nodes like a preorder traversal"
}
OOP


Σάββατο 28 Σεπτεμβρίου 2024

M2000 - How to Call code (part 2)

This example has an old style, the use of lables/numbers, plus a modern one, call modules from Groups, like calling members of objects.

We have two examples:

The simple example without objects. Statement Goto jump to a line number (is a numeric label not actual the line number at editor), or a named label. Statement Gosub call code and expect a Return statement. Statement Return with parameters is a different statement from simple Return, and used to return items to specific data containers/tables of databases.

The module.name$ is the name of the current module, but not the actual inner name (which we can find it using module$, and is a compact string of the name space of current scope). 


Module UseOfLineNumbers {
Print module.name$
Goto 10
Print "You can't see this..."
// we can use line numbers, like numeric labels
10 A=5
20 Gosub 1000
30 A--
40 If A>0 then 20
50 End


1000 Print "Code at line number 1000", A : return
}
Module UseOfLineLabels {
Print module.name$
Goto StartLine
Print "You can't see this..."
// we can use line numbers, like numeric labels
StartLine:
10 A=5
again:
20 Gosub mysubroutine
30 A--
40 If A>0 then goto again
50 End
mysubroutine: // only comments in same line with label
1000 Print "Code at line number 1000", A : return
}
Module UseOfLineLabels2 {
Print module.name$
Goto StartLine
Print "You can't see this..."
// we can use line numbers, like numeric labels
StartLine:
A=5
again:
Gosub mysubroutine
A--
If A>0 then goto again
End
mysubroutine: // only comments in same line with label
Print "Code at line number 1000", A : return
}
UseOfLineNumbers
UseOfLineLabels
UseOfLineLabels2



The advanced example with objects. We have the Beta object, as a Group in the current module. The modules of Group Beta ara modules of the current module (they have .beta. between the current module name and the calling module's name. The modules of Delta exist in a closed area, and for use them we have to attach the object temporary, then call, then deattach it. We can use For object { }  block and do the attach once, then we call any number of modules, then at the exit of this block the deattach perform. The attach means that the inner lists of interpreter knows the modules,, by installing like those of Beta, and deattach means that the modules erased and the inner lists restored before th For object {}. 

Also we see the deconstructor of a group, which automatic executed when the object lost the last pointer to it. Also we see that the Beta, the group without a usable pointer (has a hidden one), erased at a Clear or at the exit of Module/Function etc, without call the constructor, unless we use Clear Beta as tbe last statement for Beta,

Class Alfa {
Module UseOfLineNumbers {
Print module.name$
Goto 10
Print "You can't see this..."
// we can use line numbers, like numeric labels
10 A=5
20 Gosub 1000
30 A--
40 If A>0 then 20
50 End

1000 Print "Code at line number 1000", A : return
}
Module UseOfLineLabels {
Print module.name$
Goto StartLine
Print "You can't see this..."
// we can use line numbers, like numeric labels
StartLine:
10 A=5
again:
20 Gosub mysubroutine
30 A--
40 If A>0 then goto again
50 End
mysubroutine: // only comments in same line with label
1000 Print "Code at line number 1000", A : return
}
Module UseOfLineLabels2 {
Print module.name$
Goto StartLine
Print "You can't see this..."
// we can use line numbers, like numeric labels
StartLine:
A=5
again:
Gosub mysubroutine
A--
If A>0 then goto again
End
mysubroutine: // only comments in same line with label
Print "Code at line number 1000", A : return
}
remove {
Print "I am an Alfa, and I just deleted"
}
}
// Beta is a Group Object
// All named members exist on interpreter lists.
// this object deleted at the end of scope
Beta=Alfa()
For Beta {
.UseOfLineNumbers
.UseOfLineLabels
// .UseOfLineLabels2
}
Beta.UseOfLineLabels2
// Delta is a pointer to an object of type of Group
// This object deleted when no pointer point to it.
Delta->Alfa()
For Delta {
// at this point the object attach as Group, like Beta, but using a hidden name
.UseOfLineNumbers
.UseOfLineLabels
}
// Now object deattach from interpreter lists (for modules/variables)
// No use of . but => for pointers
// yhis call do attach/call/deattacb in one go
Delta=>UseOfLineLabels2
Print Delta is type Alfa
// Pointer() return the Null object (is an object of type Null)
Delta=Pointer()
// The previous object deleted but call the remove module (if exist any)
Print Delta is type Null
// Now Delta point to Beta, which is a Group
Delta=Pointer(Beta)
Print Delta is type Alfa
// Interpreter just change Delta=> with Beta
// So now we don't have attach/call/deattach but only call
Delta=>UseOfLineNumbers
Delta=>UseOfLineLabels
Delta=>UseOfLineLabels2
// now we erase all variables
REM :
Clear
// Beta group can't call the remove module
// We can call it using Clear Beta (but has to be the last statement for Beta)
REM : Clear Beta // hide the Clear statement above, unhide this line (press enter after :)




M2000 - How to Call code (part 1)

In this part we will see how we can call code ffor exedcution rom code. This part has the calling for modules, functions and lambda functions, plus subs and simple functions.

Also we will see the use of Variant variable. The return type of a function depend of the type of result, which return through the statement = (the sign of equal as statement is the return from function, and isn't an exit from function, we can execute more commands after the return value passed to an internal buffer. Also we can pass more times a value, and the last one survives for return value)

Just copy these lines in a module A and then press esc and write A and press enter to get the results.


module TestModule (that, num1) {


// the names ThisIsAModule, ThisIsAFunction, ThisIsALambdaFunction, A
// aren't exist before interpreter found as interpret
module ThisIsAModule (that) {
Print "("+that+")"
}
function ThisIsAFunction(that) {
=that
}
ThisIsALambdaFunction = lambda (that) -> {
=that
}
Variant A
A=that
A+="..."
Print A=that+"..."
Print @ThisIsASimpleFunction()=that+"..."
Print ThisIsAFunction(A)=that+"..."
Print ThisIsALambdaFunction(A)=that+"..."
ThisIsASubroutine()
// calling a Module we don't use parenthesis for parameter list
// parameters can be put in stack before call also
ThisIsAModule A
Push A
ThisIsAModule
// we can change type from string to number (by default 100 is a double - 8byte)
A=num1
A++
Print A=num1+1
Print @ThisIsASimpleFunction()=num1+1
Print ThisIsAFunction(A)=num1+1
Print ThisIsALambdaFunction(A)=num1+1
ThisIsASubroutine()
ThisIsAModule A
Push A
ThisIsAModule
// sub or function without {} is an END
// so interpreter at the next statement exit from module
// subs and simple functions run on same namespace as the calling namespace
// so A is not local here
// we have to use LOCAL to define local variables.
sub ThisIsASubroutine()
Print "("+A+")"
end sub

function ThisIsASimpleFunction()
=A
end function
}
ClS 5, 0
PEN 15


TestModule "ok", 100


Module ByPassDeclaration (B) {
Print "This is a ByBass:";B
}
// 50% is a 16bit integer, 50& is 32bit integer
// 50# is Currency type, 50@ is Decimal type, 50! is single
// try those too


// this call has a decoration, which tell that the call has a predefined module
// ThisIsAModule using code from ByPassDeclaration.
// The inner code for ThisIsAModule skipped at execution
// We can do the normal call after this without decoration
TestModule "George", 50%; ThisIsAModule as ByPassDeclaration

// 100&& is long long literal (64bit signed integer)
TestModule "George", 100&&