Δευτέρα, 9 Ιουλίου 2018

Αναθεώρηση 19, Έκδοση 9,3

1. Αφαίρεση σφαλμάτων
1.1 Σε ομάδα γενική  το διάβασμα αριθμητικής μεταβλητής δημιουργούσε τοπική μεταβλητή, με συνέπεια να μην ενημερώνεται η γενική μεταβλητή, της ομάδας (προέκυψε από την 9.3 έκδοση, στις προηγούμενες αναθεωρήσεις)
Ως αποτέλεσμα δεν έτρεχε το παράδειγμα εδώ 
Τώρα έχει διορθωθεί!
 1.2 Βρέθηκε ένα πρόβλημα σύνθετο, το οποίο και αυτό λύθηκε.Όταν είχαμε μια συνάρτηση έστω Κ() και παράλληλα σε ένα τμήμα υπήρχε μια συνάρτηση Κ() η οποία καλούσε τον εαυτό της, αντί να καλεί τον εαυτό της καλούσε την προηγούμενη συνάρτηση. Αυτό το πρόβλημα υπήρχε στην έκδοση 8,8, όταν η συνάρτηση ήταν εντός μια συνάρτησης που επιστρέφει αντικείμενο, και ειδικότερα στο τμήμα του κατασκευαστή.
Στο παράδειγμα, ο κατασκευαστής Modue Alfa, της κλάσης alfa, έχει την συνάρτηση k(), και ενώ στην Prtint k(3)*n ο διερμηνευτής καλούσε την τοπική k(), εντός της k() η κλήση στο ίδιο όνομα καλούσε την εξωτερική k(), ενώ αν αλλάζαμε όνομα στην εξωτερική πχ k2() τότε δεν υπήρχε πρόβλημα. Λύθηκε το ζήτημα και για τους δυο παραλλαγέ0 του διερμηνευτή, το εξορισμού "ασφαλείας" και το μη ασφαλή. (επιλέγονται με την switch "+scc" και switch "-scc" από την γραμμή εντολής της κονσόλας (και αλλάζει καθολικά την συμπεριφορά, εκτός από του ήδη φορτωμένους διερμηνευτές που τρέχουν άλλα προγράμματα σε Μ2000. Σε ελληνικές εντολές είναι το Διακόπτες "+sec" και Διακόπτες "-sec". Η εντολή εντός κώδικα πρέπει να δοθεί με το Θέσε, αλλά καλό είναι να μην το αλλάζουμε, εκτός από την αρχή (τα γενικά τμήματα είναι το ίδιο σε κάθε τύπο διερμηνευτή, το sec αναφέρεται στο secure names, δηλαδή έναν τρόπο να γίνονται μοναδικά τα ονόματα των μεταβλητών/τμημάτων/συναρτήσεων, ενώ εμείς τα βλέπουμε ίδια στο κώδικα (αλλά σε διάφορες θέσεις, σε διαφορετικές συναρτήσεις,τμήματα κ.α.).

Function k (x) {
      if x<1 then =1: exit
      =k(x-1)*x*2
}
Class alfa {
      Module alfa (n){
            function k (x){
                  if x<1 then =1: exit
                        =k(x-1)*100*x
                  }         
            Print k(3)=n
      }
}
Print k(3)

function kk (x){
      if x<1 then =1: exit
            =kk(x-1)*100*x
      }         
m=alfa(kk(3))



1.2 Διόρθωση πάλι σε κατασκευαστή σε ομάδα. Στο παράδειγμα το διάβασμα της M.R  στο κατασκευαστή του Κύκλου, πήγαινε σε τοπική μεταβλητή και όχι στο R του M. Οι κατασκευαστές είναι τμήματα που καλούνται όταν καλούμε την συνάρτηση που γυρνάει μια ομάδα. Ουσιαστικά είναι ο κώδικας που  θα κληθεί αντί κάποιας συνάρτησης. Η διαφορά κλήσης του κατασκευαστή με την κλήση άλλων τμημάτων, είναι ότι εδώ ότι αλλαγές/προσθήκες κάνουμε στο Αυτό ή This θα μείνουν και θα δοθούν ως επιστροφή από τη συνάρτηση τύπου Class (Κλάση). Οι κλάσεις όταν ορίζονται εκτός ομάδων είναι γενικές, δηλαδή μπορούν να κληθούν από παντού, εφόσον βέβαια δεν τερματίσει για κάθε κλάση το τμήμα που την δημιούργησε. Στη Μ2000 φτιάχνουμε αντικείμενα με απλή αντιγραφή..

Στο παράδειγμα η Circle, έχει την R και ένα τμήμα Print. Στον κατασκευαστή, φτιάχνουμε το M ως σημείο (PointA) χρησιμοποιώντας την κλάση PointA και βάζοντας δυο σημαία, το Χ και Y,  Πάνω στο M συγχωνεύουμε το Αυτό (This), έτσι προσθέτουμε το R και γράφουμε νέο ορισμό για την Print. που δίνει το "Circle". Τώρα το M to συγχωνεύουμε στο Αυτό (This). Στο τέλος φτιάχνουμε το Α ως σημείο, με τα Χ, Υ και Print, και το κύκλο με τα X, Υ και Print. καθώς και την R. Το αντικείμενο Circle είναι PointA γιατί έχει ότι έχει το PointA και έχει και επιπλέον, που σημαίνει ότι το αντίθετο δεν ισχύει!.





Class PointA {
      Property x
      Property y
      Module Print {
             Print "Point"     
      }
Class:
      \\ [x] is the private variable behind property
      Module PointA (.[x], .[y]) {}
}
Class Circle {
      Property R
      Module Print {
            Print "Circle"
      }
Class:
      Module Circle {
            M=PointA(Number, Number)
            M=This
            Read M.R
            This=M
       }
}
A=PointA(10,3)
A.Print
Print A.x, A.y
C=Circle(20,10,5)
Print  C.r
Print C.x,C.y, C.r
C.Print





Παρακάτω είναι μια παραλλαγή του προηγούμενου με χρήση υπερκλάσης. Τώρα το σημείο και ο κύκλος έχουν ακόμα μια συνάρτηση την Super.Print, η οποία τυπώνει και στα δυο αντικείμενο το "Point". Οι υπερκλάσεις στη Μ2000 μπορούν να έχουν μοναδικά μέλη και να τα καλούμε/χρησιμοποιούμε από όλες τις ομάδες που έχουν συνδεθεί με αυτές. Κάθε ομάδα μπορεί να συνδεθεί με μια υπερκλάση, αλλά αυτό ισχύει και για τις ομάδες εντός των ομάδων, έτσι αν θέλουμε μια δεύτερη υπερκλάση, αρκεί να φτιάξουμε μια ομάδα σε ομάδα και μετά να δώσουμε μια υπερκλάση σε αυτήν. Φυσικά κάθε φορά που θα αντιγράφουμε (συγχωνεύουμε) την ομάδα, θα περνάνε και οι υπερκλάσεις από κάθε ομάδα εντός της ομάδας (δεν υπάρχει όριο για το βάθος υποομάδων)


Function Extend {
      SuperClass PointA {
            Property x
            Property y
            Module Print {
                   Print "Point"     
            }
            Module Super.Print {
                  For SuperClass {
                         .Print
                  }
            }
            Function GetXY (.[x], .[y]) {
                  =This
            }
      }
      =lambda A=PointA (x, y) ->{
            =A.GetXY(x,y)
      }
}
Class Circle {
      Property r
      Module Print {
            Print "Circle"
      }
Class:
      Module Circle (Extend) {
            M=Extend(Number, Number)
            M=This
            Read M.r
            This=M
          
      }
}
\\ PointA is a lambda function, holding a pointer to SuperClass
PointA=Extend()
P=PointA(10,2)
Print P.x, P.y
P.Print   'Point
P.Super.Print  'Point
C=Circle(PointA, 20,10,5)
Print C.x,C.y
C.Print    ' Sircle
C.Super.Print   ' Point
Print C.x, C.y, C.r


Ο ορισμός της Υπερκλάσης δημιουργεί δυο ομάδες, μια κενή και μια κλειστή ομάδα. Η κενή έχει ένα σύνδεσμο (δείκτη) στην κλειστή ομάδα.  Όταν θέλουμε να κατασκευάσουμε μια ομάδα από την Υπερκλάση, τότε κάνουμε συγχώνευση. Κατά την συγχώνευση, θα γίνουν δυο πράγματα, από την κλειστή ομάδα θα βγουν αντίγραφα όλα τα μη μοναδικά μέλη, με τις τρέχουσες τιμές και θα γίνουν μια νέα ομάδα. Σε αυτήν την νέα ομάδα θα γραφτεί ένας δείκτης στη κλειστή ομάδα. Κάθε φορά που καλούμε την υπερκλάση, ανοίγει η ομάδα αυτή και έχουμε πρόσβαση και στα μοναδικά της μέλη.

Παρακάτω είναι ένα πιο προχωρημένο παράδειγμα. Σε ένα τμήμα CheckIt, έχουμε μια κλάση, την Mama, και από αυτήν φτιάχνουμε μια στατική ομάδα Z, δηλαδή να υπάρχει στο τμήμα μέχρι αυτό να τερματίσει. Επίσης έχουμε φτιάξει το γεγονός Print, και έχουμε αποφασίσει η Ζ να χρησιμοποιηθεί ΜεΓεγονότα (WithEvents). Θέλουμε η Mama να δίνει τα δικά της Childs, τα οποία θα τα κρατάει με δείκτες και σε ένα πίνακα εσωτερικό σε αυτήν. Επίσης σε κάθε παιδί θα υπάρχει ένας δείκτης που θα δείχνει την Mama. Όλα τα παιδιά θα έχουν πρόσβαση στα δημόσια μέλη της μαμάς. Επιπλέον θα χρησιμοποιούν την MyPrint της μαμάς η οποία στέλνει το αλφαριθμητικό στο γεγονός "Print", το οποίο μπορεί να μην είναι χρησιμοποιημένο, ή αν το δούμε πιο σωστά, δεν ενδιαφέρει το αντικείμενο το πώς θα χρησιμοποιήσουμε στη εξυπηρέτηση του γεγονότος την πληροφορία που μας γυρίζει..
Τέλος έχουμε ένα τμήμα Inner, στο οποίο θα βάλουμε την μια φορά το δείκτη στη μάνα, και την άλλη φορά το δείκτη στο παιδί. Και σε κάθε περίπτωση, θα δημιουργήσουμε εντός της Inner, μέσω της parent (την οποία έχει και η Mama, ως αναφορά στην εαυτό της). ένα νέο παιδί και σε αυτό θα καλέσουμε το τμήμα  Hello  το οποίο καλεί δυο φορές το γεγονός "Print" αν είναι σε παιδί, ή μια φορά αν είναι στην Mama.
Στο τέλος καθαρίζουμε όλους τους δείκτες.


Module CheckIt {
      Class Mama {
      Event "Print"
      Private:
            Dim Base 1, Mem()
      Public:
            Group Parent
            Class Child {
                  Group Parent
                  Module Hello {
                        .Parent=>MyPrint "Hello from Child Using Mama' Event"
                        .Parent=>Hello
                  }
                  Class:
                   module Child (p){
                        .Parent<=p
                  }     
            }
            Module MyPrint (what$){
                   Call Event "Print", what$
            }
            Module Hello {
                  Call Event "Print", "Hello from Mama"
            }
            Function NewChild {
                   Dim .Mem(len(.Mem())+1)
                   p->This
                   .Parent<=p
                  .Mem(len(.Mem()))=.Child(p)
                  ->.Mem(len(.Mem()))
            }
            Module Clear {
                  \\ we need this to dereference all childs
                  .parent->0&
                  If len(.Mem())>0 then {
                        For i=1 to len(.Mem()) {
                              .Mem(i)=0&
                        }
                  }
            }
      }
      \\ Z is a static group with events
      Group WithEvents Z=Mama()
      Function Z_Print (a$) {
            Print a$
      }
      Z.Myprint "ok"
      Z.Hello
      \\ k is a poinrer to a child class, which have a pointer to Z
      \\ all childs use mama event.
      K=Z.NewChild()
      K=>Hello
      Module Inner (w){
            Group M
            For w {
                  .Hello
                  M=.parent=>NewChild()
            }
            M=>Hello
      }
      Print "Inner z"
      Inner z
      Print "Inner k"
      Inner k
      Z.Clear
}
Checkit



2. Προσθήκη: Δημιουργία δείκτη σε αντικείμενο ομάδα, γενικής εμβέλειας (για όσο το τμήμα που τον έφτιαξε τρέχει). Ουσιαστικά το Global K->alfa() είναι η προσθήκη, ενώ θα έπρεπε να κάναμε αυτό:
Function  getpointer(x) {
      ->(x)
}
Global k=getpointer(alfa())

Δείτε στην επιστροφή από την getpointer έχουμε το -> και μετά το (χ). Αν δεν βάζαμε τις παρενθέσεις τότε θα γύρναγε δείκτη ως ισχνή αναφορά στο x και το x θα διαγραφεί στην επιστροφή από την συνάρτηση. To (x) δίνει  αντίγραφο, ένα κλειστό αντικείμενο, οπότε ο δείκτης κρατάει ένα κλειστό αντικείμενο (το οποίο λέγεται και float group, γιατί πάει παντού, είναι μεταφέρσιμο, ενώ το x είναι επώνυμο, στατικό).


Το πέρασμα του K στο Inner είναι με τιμή, αλλά επειδή έχουμε δείκτη, φαίνεται σαν πέρασμα με αναφορά. Όμως η διαφορά είναι στο ότι το m αν πάρει δείκτη σε άλλο αντικείμενο, το K δεν θα αλλάξει.



Class alfa {
      x=10
      Module p10 {
            Print .X
      }
}
Global k->alfa()
Print k=>x=10
Module Inner (m as pointer) {
      \\ m is local pointer, Optional we can use as pointer, to check if we  take  a group pointer
      m=>x++
      Print m=>x=11
      k=>x++
      k=>p10 ' print 12
}
Inner k
Print k=>x=12



Μπορούμε λοιπόν να χρησιμοποιήσουμε πέρασμα με αναφορά. Εδώ αλλάζει το λεκτικό μετά το as σε group και όχι pointer.


Module Inner (&m as group) {
      \\ m is local pointer, Optional we can use as group, to check if we  take  a group  or a pointer to group
      m=>x++
      Print m=>x=11
      k=>x++
      k=>p10 ' print 12
}
Inner &k

Αν φτιάξουμε στην Inner, την m να διαβάζεται με μια Για (For) μπορούμε να χρησιμοποιούμε μέλη με τελεία και όχι με => για δείκτες, και έτσι οι ίδιες "εντολές" κάνουν και για δείκτη σε ομάδα και σε ομάδα.

Module Inner (&m as group) {
      For m {
            .x++
            Print .x=11
      }
      k=>x++
      k=>p10 ' print 12
}