Ο συλλέκτης σκουπιδιών μπήκε για να βρίσκει τις κυκλικές αναφορές, δηλαδή αν ένα αντικείμενο έχει στα περιεχόμενά του αναφορά στο ίδιο, ή έχει αναφορά σε άλλο και το άλλο στο πρώτο. Η εντολή Λίστα μας δείχνει εκτός από τις τρέχουσες μεταβλητές και τον αριθμό αντικειμένων που έχει ο συλλέκτης (αν έχει δείχνει). Υπάρχει εντολή Άδειασε Σκουπίδια η οποία κάνει το εξής: Πρώτα μαζεύει σε ένα δεύτερο αντικείμενο "συλλέκτη σκουπιδιών" μόνο τους δείκτες χωρίς να είναι "ενεργοί", δηλαδή απλά τους κάνει κλειδιά, και για κάθε αντικείμενο δίνει τον καθαρισμό τους. Μόλις τελειώσει το μάζεμα, κοιτάει τον κανονικό συλλέκτη σκουπιδιών, και καθαρίζει ότι έχει μείνει. Επειδή την εντολή θα την δώσουμε μέσα από τμήμα, ενδέχεται κάποια αντικείμενα να μην μπορούν να καθαρίσουν, γιατί υπάρχει στο χώρο μεταβλητών, ή στο σωρό του τμήματος μια αναφορά τους. Με την επιστροφή από το τμήμα οι αναφορές από το χώρο μεταβλητών θα διαγραφούν (και όπως το έφτιαξα θα διαγραφεί και η τελευταία αναφορά από το συλλέκτη). Και η Καθαρό (Clear) καθαρίζει τον συλλέκτη σκουπιδιών, αλλά εδώ με ένα πέρασμα, όχι με το διπλό όπως η Άδειασε Σκουπίδια (Flush Garbage). Αν γνωρίζουμε ότι κάποιες Καταστάσεις έχουν αναφορές σε άλλες, τότε μπορούμε να δίνουμε το Καθαρό όνομα_κατάστασης και αυτή καθαρίζει με τρόπο όλα τα στοιχεία. Αυτή η εντολή καθαρίζει στοχευμένα τα αντικείμενα, ενώ η Άδειασε Σκουπίδια και η Καθαρό καθαρίζουν τα αντικείμενα, απ΄όποιο τμήμα και αν φτιάχτηκαν. Όπως και να έχει τα "σκουπίδια" καθαρίζονται στο τερματισμό της εφαρμογής, μια φορά από το συλλέκτη σκουπιδιών (και αυτός είναι αντικείμενο).
Βρήκα επίσης και ένα σφάλμα που είχε να κάνει με τους τελεστές και μέσα σε ένα μπλοκ Για Αυτό {} δεν λειτουργούσαν! Διορθώθηκε και αυτό.
Παρακάτω έχω δυο προγράμματα στα αγγλικά. Ένα δείχνει πώς μια λάμδα συνάρτηση με κλείσιμο ενός αντικειμένου σωρού, μπορεί να λειτουργήσει για να παίρνει και να δίνει στοιχεία! Στο παράδειγμα παίρνει και δίνει και αντικείμενα! (σε αυτό βρήκα το θέμα με τους τελεστές).
α=Δείκτης()
β->0&
Τύπωσε α είναι τύπος Μηδενικός
Τύπωσε β είναι τύπος Μηδενικός
Κλάση ΚάτιΆλλο {
Ζ=100
}
Ομάδα δ {
Τύπος: ΝΑΣΑ
Χ=12345678
}
Τύπωσε δ είναι τύπος ΝΑΣΑ=Αληθές
δ=δ με α ' δεν γίνεται συγχώνευση με μηδενικό τύπο
Τύπωσε δ είναι τύπος Μηδενικός=Ψευδές
α->ΚάτιΆλλο()
Τύπωσε α=>Ζ
δ=α ' εδώ έγινε συγχώνευση με αντίγραφο από το α. ίδιο με το δ=δ με α
Τύπωσε δ.Ζ=100
Τύπωσε δ είναι τύπος ΚάτιΑλλο=Αληθές
Τύπωσε δ είναι τύπος ΝΑΣΑ=Αληθές ' δεν έχααε τον τύπο που ήδη είχε
κ=ομάδα(β) ' δεν δίνουμε το δείκτη αλλά το αντίγραφο του β (αλλά είναι μηδενικός)
Τύπωσε κ είναι τύπος Μηδενικός=Ψευδής ' δεν υπάρχουν εώνυμες ομάδες με μηδενικό τύπο.
Ομάδα κ {
Τύπος: Πρώτος ' μπορώ να δώσω και τύπο!
κλμ=11 ' στην επώνυμη μπορώ να προσθέσω
}
μ=κ
Τύπωσε μ.κλμ, μ είναι τύπος Πρώτος=Αληθές
Λίστα
Flush \\ empty stack of value
\\ using Stack to process data in Lambda function
a=Lambda st (cmd as stackop) -> {
\\ Select case need one statement in next line from a Case
\\ (no second in row allowed), otherwise use { } for any code
Select Case cmd
Case 0
st=Stack
Case 1 ' is empty
=Len(st)=0
Case 2 ' len
=Len(st)
Case 3 ' merge To bottom
{
N=[] \\ get current Stack, and leave it empty
Stack st {
Stack N
}
=True
}
Case 4
=Stackitem(st, Number) \\ second parameter passing to lambda, read from function stack.
Case 5
Stack st {=[] } \\ return a Stack object by swaping st and an empty one.
Case 6
Stack st { Stack } : =True \\ display Stack (current, is st)
Case 7 '' change item (we can put one line of code or a block of code only)
Stack st : Read Where:Shift Where+1 : Drop:Shiftback Where:st=[]
Case 8
Stack st {Flush}
Case 9 ' copy2new
st=Stack(st)
Case Else
=False
End Select
}
Enum stackop {
new_stack=0
is_empty, show_len, merge_stack, show_item
get_stack, show_stack, change_item, empty_stack
copy2new
}
m=a(new_stack)
m=a(merge_stack,1,2,3,4,5)
m=a(merge_stack,11,12,13,14,15)
m=a(show_stack)
For i=1 To a(show_len)
Print a(show_item, i),
Next
For This {
\\ block for temporary definitions
Class Alpha {
x=1, y=2
Operator "<>" (N) {
Push N.x<>.x or N.y<>.y
}
Operator "++" {
.x++
.y++
}
}
m=a(merge_stack,Alpha())
}
pos_alpha=a(show_len)
Print "position of alpha", pos_alpha
beta=a(show_item, pos_alpha)
Print Type$(beta)
Print beta.X, beta.y
beta.x+=100
m=a(change_item, pos_alpha, beta)
For i=9 To a(show_len)
For this {
Local N=a(show_item, i)
Print Type$(N), i
}
Next
For beta {.x=0 : .y=0}
delta=a(show_item, pos_alpha)
Print Type$(delta)
For delta {
Print .x, .y
}
a2=a
\\ now [a2] and [a] reference same Stack
m=a2(copy2new)
\\ but not now.
Print a2(show_len), a(show_len)
\\m=a(empty_stack)
\\Print a2(show_len), a(show_len)
m=a(change_item, pos_alpha, beta)
For This {
\\ block for temporary variables/modules/functions
delta10=a2(show_item, pos_alpha)
delta20=a(show_item, pos_alpha)
Print delta10 is type Alpha ' true
Print delta20 is type Alpha ' true
Print delta20 is delta10 ' false
Print delta20<>delta10 ' true
\\ Also now work for items in evaluator only
Print a2(show_item, pos_alpha)<>a(show_item, pos_alpha) ' true
delta10++
delta20++
Print delta10.x, delta10.y
Print delta20.x, delta20.y
delta10=delta20
Print delta20 is delta10 ' false
Print delta20<>delta10 ' false
// Pointers to groups (Version 9 and 10)
pointer_to_deltaXX->delta10
Print pointer_to_deltaXX is delta10 ' true
pointer_to_deltaXX->delta20
Print pointer_to_deltaXX is delta10 ' false
Print pointer_to_deltaXX <> delta10 ' false
delta10++
Print pointer_to_deltaXX <> delta10 ' true
Print delta20<>delta10 ' true
pointer_to_deltaXX=>++
Print pointer_to_deltaXX <> delta10 ' false
Print delta20<>delta10 ' false
Print pointer_to_deltaXX is delta20 ' true
}
.
Το δεύτερο λέγεται Funny Loops. Και εδώ έχουμε λάμδα συναρτήσεις, και κάνουμε το εξής: Θέλουμε κώδικας από λάμδα συνάρτηση να τρέξει σε μια άλλη λάμδα συνάρτηση μαζί με μια τρίτη που θα κανονίζει το πόσες φορές θα τρέχει (με αρχική τιμή, τελική και βήμα, το βήμα προαιρετικό). Δεν μιλάμε για απλές επαναλήψεις. Είναι τέσσερις "ειδικές". Στην πρώτη έχουμε μια διακοπή βάσει ενός ορίου (ας το θεωρήσουμε ως γεγονός), και μετά συνέχιση από το σημείο που σταμάτησε, συνεχίζοντας να χρησιμοποιούμε το αντικείμενο επανάληψης (τη λάμδα για τον σκοπό αυτό). Η δεύτερη πάλι με το όριο, το αναπρογραμματίζει σε κάθε εκτέλεση και έτσι κάνει βηματική εκτέλεση. Η τρίτη δεν ενδιαφέρεται για την μεταβλητή που απαριθμεί το αντικείμενο επανάληψης, αλλά έχει μια εσωτερική στατική μεταβλητή και αυτή αλλάζει σε κάθε επανάληψη. Στην τέταρτη περίπτωση έχουμε ένα αντικείμενο που δίνει μια δική του συνάρτηση με αναφορά και σε κάθε χρήση της εσωτερικά στην λάμδα "μηχανή επανάληψης", αλλάζει μια μεταβλητή του αντικειμένου που ανήκει η συνάρτηση. Ταυτόχρονα όπως είναι η δομή While (Ενώ) σε κάθε επανάληψη εκτελείται και το μπλοκ εντός της While (ενώ ο κώδικας που εκτελείται για να βγάλει το τι θα κάνει η While, εκτελεί το κώδικα της συνάρτησης του αντικειμένου). Οπότε σε αυτό το μπλοκ έβαλα να περιστρέφεται ένα αντίγραφο που βγάζει άμεσα ο διερμηνευτής της εικόνας με διαφάνεια στο ματζέντα (5) 100% και μερική διαφάνεια στο υπόλοιπο, και μπορούμε με το ποντίκι καθώς περιστρέφεται να το μετακινήσουμε ενώ το νούμερο από το μετρητή τον βλέπουμε σε μια "μπάρα πλήρωσης" όπου το φωτεινό μέρος θα καλύψει το σκούρο στο 100%.
Clear \\ clear static too
FKey 1, "Cls, 0 : Edit "+module$
FKey 5, module$
Font "Verdana"
Form 70,35
Cls 3
Pen 14
Double
Report 2, "Funny Loops.."
Normal
Cls 5,2
old_italic=Italic
Italic 1
Pen 15 {Report 1, {Look how we can mix proportional font with same font as monospace font} }
Italic old_italic ' restore italic to old value
\\ iterator
ForEach=lambda (x, x1) -> {
st=1 \\ this is optional
read ? st
=lambda x ,x1, st (&n) -> {
=true
if x<=x1 then {
n=x : x+=st
} else =false
}
}
\\ execution of a lambda function by iterator
\\ get more parameters, from stack (using call statement)
Lcode=lambda i (&m) -> {
\\ choose to use a lambda by value
\\ or any function by reference, using islet (is letter)
\\ check head of stack if is string (function references in M2000 are strings)
If islet then { read &cd() } else read cd
=false
if m(&i) then {
Try ok {
call cd(i)
}
if not ok then exit
=true
}
}
Z=Foreach(60,80,2)
CodeW=lambda (i) -> {
Let limit=1 \\ this is optional
Read ? limit
Print i, limit
if i>limit then =i ' error
}
\\ print prints with transparent background for fonts
\\ Print Over erase a line before, and set all line one field (temporary)
Print Over "Try iterate code using an iterator and a secondary limit, if limit break then recalibrate iteration using other data, here other limit"
\\ but Print Over leave one line, so we can fill this line with Print Unter (also change line)
Print Under
\\ Print Over, Print Part and Print Under can be used for making columns with diffrent width
\\ Here is the first loop (empty block)
While Lcode(&z, CodeW,75) {}
n=error
If n>75 then {
Print "out of scope...recalibrate"
while Lcode(&z, CodeW,100 ) {}
}
Print Under
Print Over "Example of step by step execution"
Print Under
Z=Foreach(10,15)
n=0
\\ Pen { } change temporary pen to black
\\ using loop we mark block for loop at the end of block execution
\\ Calling a function with Call return error if function return non zero value.
\\ so here we get Error and if is not zero then we do next loop
Pen 0 {
Print Over ~(0,7,14),$(0,8), "Step"+str$( n+1),@(tab),
\\ also here we have an empty block
while Lcode(&z, CodeW,n) {}
n=error
if n<>0 then loop
}
\\ here is the lambda with static variable
\\ static variables are per execution object (attached to parent object), no per function (as code)
\\ so if this lambda ...moved to another execution object, passing as parameter
\\ then static i get 1 and start new count.
CodeW=lambda -> {
Static i=1
Print Over ~(14,8),$(4,8),"just run, no need iteration number ", i
i++
}
Z=Foreach(1,5)
Print Over "Simple iteration , using static counter inside code"
\\ Here we have a repeat {} until block
Repeat {Print Under} Until Not Lcode(&Z,Codew)
Print Over "Iteration using group's function, passing by reference, altering group member counter"
Print Under \\ print underline and change line too
Group Alfa {
counter
Function M {
.counter++
}
}
Z=Foreach(200,499)
y=row
\\ we use a$ for image holder
a$=""
Mouse.icon Hide
Print $("0.00%"),
\\ and here is the "game"
While Lcode(&Z, &Alfa.M()) {
FeedBack(y, Alfa.counter/300, " press space to exit early")
Move 0, 0
copy scale.x,scale.y to a$
Move mouse.x, mouse.y
Sprite A$,, Alfa.counter,40,80 \\ leaving 2nd parameter, to automatic match the paper color for 100% transparent
If keypress(32) then exit
Refresh 5000 \\ rfefresh now and reset counter for next refresh 5 sec later (never happen)
Sprite Sprite$ \\ when Sprite write, altered background saved to Sprite$, so now sprite erased
\\ Hold take all screen, and Release restore screen to that we take with Hold. But here we use Sprite Sprite (we have only one)
Wait 5+Random(1,11-Alfa.counter/30)*2
}
Print $(""),
Print "Counter:";Alfa.counter
Cls ,Row
Mouse.Icon Show
Sub FeedBack(y, val, msg$)
local N
Pen 15 {
Cursor 0, y
N=round(val*100,0)
Print Over $(0,8), val, @(tab),$(4), ~(7);string$("[]",50);msg$;@(tab), ~(11),string$("[]", N div 2)+string$("[", N mod 2);
}
End Sub
Δεν υπάρχουν σχόλια:
Δημοσίευση σχολίου
You can feel free to write any suggestion, or idea on the subject.