Σε αυτή την αναθεώρηση έκανα μια προσθήκη στους δείκτες για ομάδες ώστε να μπορεί να λειτουργήσει και το παράδειγμα Visitor Pattern.
Το Visitor Pattern, εδώ κάνει την όλη δουλειά στο who.a.accept &this. Αυτό που αλλάζει είναι το a, που μπορεί να είναι literal ή Add, όπου και τα δύο έχουν την accept. Η accept προκαλεί την κλήση πάλι της visitor, στο αρχικό Parser, αλλά γίνεται έλεγχος του τύπου του αντικειμένου. Η Μ2000 δεν έχει τύπους στις ομάδες (όλα είναι ένας τύπος), αλλά μπορούμε να βάλουμε μια μεταβλητή και αυτή να δηλώνει τον τύπο, με έλεγχο που κάνουμε με την Valid() ή Έγκυρο().
Κάθε φορά λοιπόν που θέλει να "προβληθεί" (εδώ να γραφτεί στο sb$ αλφαριθμητικό) ένα από τις δυο κλάσεις μας, θα καλέσει την visit και θα δώσει μια αναφορά σε αυτό, ώστε να υπάρχει τρόπος να πάρουμε περισσότερα στοιχεία. Έτσι η parser θα πάρει την τιμή του n και θα την γράψει στο sb$, αν η visit κλήθηκε από το accept της literal.
Πριν την προσθήκη λειτουργούσε μόνο με αναφορές:
Πρόγραμμα με χρήση αναφορών
Δίνει αυτό:
((100+200)+((100+200)+50))
Τώρα το ίδιο πρόγραμμα με χρήση δεικτών. Αυτό που δεν μπορούσε να γίνει στις προηγούμενες αναθεωρήσεις ήταν το m->This, ενώ το m->(This) μπορούσε να γίνει, αλλά βγαίνει δείκτης σε αντίγραφο του This (Αυτό). Επειδή οι κλάσεις επιστρέφουν ομάδα (χωρίς δείκτη), έχουμε δυο συναρτήσεις που γυρίζουν δείκτες (αντί για = έχουν το -> για επιστροφή τιμής).
Στο who=>a=>accept m έχουμε δυο δείκτες, το whο και το a, οπότε για να βρούμε το a δίνουμε το who=>a, και μετά επειδή ζητάμε το visit του a δίνουμε ξανά το =>visit m, ή όλο μαζί who=>a=>visit m
From version 10 we can use: If who is type literal1 then ....
We use operator: is type with the name of class.
Το Visitor Pattern, εδώ κάνει την όλη δουλειά στο who.a.accept &this. Αυτό που αλλάζει είναι το a, που μπορεί να είναι literal ή Add, όπου και τα δύο έχουν την accept. Η accept προκαλεί την κλήση πάλι της visitor, στο αρχικό Parser, αλλά γίνεται έλεγχος του τύπου του αντικειμένου. Η Μ2000 δεν έχει τύπους στις ομάδες (όλα είναι ένας τύπος), αλλά μπορούμε να βάλουμε μια μεταβλητή και αυτή να δηλώνει τον τύπο, με έλεγχο που κάνουμε με την Valid() ή Έγκυρο().
Κάθε φορά λοιπόν που θέλει να "προβληθεί" (εδώ να γραφτεί στο sb$ αλφαριθμητικό) ένα από τις δυο κλάσεις μας, θα καλέσει την visit και θα δώσει μια αναφορά σε αυτό, ώστε να υπάρχει τρόπος να πάρουμε περισσότερα στοιχεία. Έτσι η parser θα πάρει την τιμή του n και θα την γράψει στο sb$, αν η visit κλήθηκε από το accept της literal.
Πριν την προσθήκη λειτουργούσε μόνο με αναφορές:
Πρόγραμμα με χρήση αναφορών
Class
literal
{
Iamliteral
n
module literal (.n) {}
module accept(&visitor) {
visitor.visit &this
}
}
Class Add {
Group a
Group b
module Add (.a, .b) {}
module accept( &visitor) {
visitor.visit &this
}
}
M=Add(Add(literal(100), literal(200)), Add(Add(literal(100), literal(200)), Literal(50)))
Group Parser {
sb$
module visit (&who) {
If valid(who.Iamliteral) then {
.sb$<=.sb$+Str$(who.n,"")
} else {
.sb$<=.sb$+"("
who.a.accept &this
.sb$<=.sb$+"+"
who.b.accept &this
.sb$<=.sb$+")"
}
}
}
Parser.Visit &M
Print Parser.sb$
Iamliteral
n
module literal (.n) {}
module accept(&visitor) {
visitor.visit &this
}
}
Class Add {
Group a
Group b
module Add (.a, .b) {}
module accept( &visitor) {
visitor.visit &this
}
}
M=Add(Add(literal(100), literal(200)), Add(Add(literal(100), literal(200)), Literal(50)))
Group Parser {
sb$
module visit (&who) {
If valid(who.Iamliteral) then {
.sb$<=.sb$+Str$(who.n,"")
} else {
.sb$<=.sb$+"("
who.a.accept &this
.sb$<=.sb$+"+"
who.b.accept &this
.sb$<=.sb$+")"
}
}
}
Parser.Visit &M
Print Parser.sb$
Δίνει αυτό:
((100+200)+((100+200)+50))
Τώρα το ίδιο πρόγραμμα με χρήση δεικτών. Αυτό που δεν μπορούσε να γίνει στις προηγούμενες αναθεωρήσεις ήταν το m->This, ενώ το m->(This) μπορούσε να γίνει, αλλά βγαίνει δείκτης σε αντίγραφο του This (Αυτό). Επειδή οι κλάσεις επιστρέφουν ομάδα (χωρίς δείκτη), έχουμε δυο συναρτήσεις που γυρίζουν δείκτες (αντί για = έχουν το -> για επιστροφή τιμής).
Στο who=>a=>accept m έχουμε δυο δείκτες, το whο και το a, οπότε για να βρούμε το a δίνουμε το who=>a, και μετά επειδή ζητάμε το visit του a δίνουμε ξανά το =>visit m, ή όλο μαζί who=>a=>visit m
Class
literal1
{
Iamliteral
n
module literal1 (.n) {}
module accept(visitor) {
m->this
visitor=>visit m
}
}
Class Add1 {
Group a
Group b
module Add1 (.a, .b) {}
module accept( visitor) {
m->this
visitor=>visit m
}
}
Function Literal(a) {->literal1(a)}
Function Add(a, b) {->Add1(a, b)}
M=Add(Add(literal(100), literal(200)), Add(Add(literal(100), literal(200)), Literal(50)))
Group Parser {
sb$
module visit (who) {
If valid(who=>Iamliteral) then {
.sb$<=.sb$+Str$(who=>n,"")
} else {
m->This
.sb$<=.sb$+"("
who=>a=>accept m
.sb$<=.sb$+"+"
who=>b=>accept m
.sb$<=.sb$+")"
}
}
}
Parser.Visit M
Print Parser.sb$
Iamliteral
n
module literal1 (.n) {}
module accept(visitor) {
m->this
visitor=>visit m
}
}
Class Add1 {
Group a
Group b
module Add1 (.a, .b) {}
module accept( visitor) {
m->this
visitor=>visit m
}
}
Function Literal(a) {->literal1(a)}
Function Add(a, b) {->Add1(a, b)}
M=Add(Add(literal(100), literal(200)), Add(Add(literal(100), literal(200)), Literal(50)))
Group Parser {
sb$
module visit (who) {
If valid(who=>Iamliteral) then {
.sb$<=.sb$+Str$(who=>n,"")
} else {
m->This
.sb$<=.sb$+"("
who=>a=>accept m
.sb$<=.sb$+"+"
who=>b=>accept m
.sb$<=.sb$+")"
}
}
}
Parser.Visit M
Print Parser.sb$
From version 10 we can use: If who is type literal1 then ....