Κυριακή 22 Νοεμβρίου 2015

Εργασίες με ΣΤΟΚ, ή πώς αποφεύγουμε πολλές αντιγραφές!

(έχει γίνει χρωματισμός με την νέα αναθεώρηση 94 που κάνει εξαγωγή στο πρόχειρο και σε Html)
(η συνάρτηση ΒΑΛΕ.ΑΔΕΙΑ$() είναι της τελευταίας αναθεώρησης)
Στην προηγούμενη ανάρτηση αναφέρθηκε ο λόγος στο πόσα αντίγραφα βγαίνουν όταν πράγματι αντιγράφουμε μια μεταβλητή:
Στο παρακάτω έχουμε 3 αντιγραφές: Μια αντιγραφή ως αποτέλεσμα έκφρασης (εδώ η έκφραση ή να το ορίσουμε αλλιώς, η αριθμητική παράσταση είναι μόνο το Κ). Και μετά μια δεύτερη στο Α. Ενώ με το "μάτι" νομίζουμε ότι το Κ πάει άμεσα στο Α.
Α=Κ
Αν είχα να αντιγράψω ας πούμε εκατό στοιχεία από έναν πίνακα σε έναν άλλο τότε θα έπρεπε να κάνω 400 αντιγραφές το λιγότερο. Για κάθε στοιχείο, θα έβγαζα τι τιμή ως αποτέλεσμα έκφρασης και μετά θα την αντέγραφα στο προορισμό. Μάλιστα αν σκεφτούμε ότι θα έπρεπε να έχω μια ακόμα μεταβλητή που θα υποδήλωνε το πού θα πάει τι, τότε θα έπρεπε για κάθε εντολή Α(χ)=Κ(χ) να έχω και άλλες δυο εκφράσεις, άρα άλλες δυο αντιγραφές. Σύνολο δηλαδή τέσσερις αντιγραφές. Αν είχα αλφαριθμητικό τότε οι 200 θα ήταν για αλφαριθμητικό και οι άλλες 200 για αριθμό.
Η ιδέα λοιπόν λέει ότι για την μεταφορά πρέπει να αρκεί η τοποθέτηση ενός απαριθμητή εσωτερικά (άρα δεν θα καλούμε 200 φορές την ερμηνεία έκφρασης, αλλά θα κάνουμε μόνο αύξηση ενός αριθμού, του μετρητή μεταφοράς), και από μόνο το "επιπλέον" ή offset από την αρχή των δεικτών, για να γίνει η μια και μοναδική αντιγραφή για κάθε στοιχείο!


Υπάρχει λοιπόν μια εντολή που λέγεται ΣΤΟΚ (ή STOCK αγγλικά) και χρησιμοποιείται για γρήγορες αποθηκεύσεις/αντιγραφές τιμών. Βγάζει πάντα αντίγραφα τιμών, και πηγή και προορισμός είναι πάντα μεταβλητές ή πίνακες, αλλά οπωσδήποτε ένας πίνακας θα υπάρχει!
Ομάδες στην Μ2000 είναι τα αντικείμενα της Μ2000. Όταν χρησιμοποιούμε την εντολή ομάδα τότε φτιάχνουμε ένα αντικείμενο με όνομα.
Εδώ θα μπορούσαμε να φτιάχναμε μια κλάση (είναι μια συνάρτηση που φτιάχνει μια ομάδα)
Κλάση αλφα {
      χ=10
      Πίνακας α(10)=10
}
αλφα=αλφα()

Αλλά το έχουμε απλοποιήσει, και δεν χρησιμοποιούμε την Κλάση για να μας φτιάξει συνάρτηση αλφα().

Ομάδα αλφα {
      χ=10
      Πίνακας α(10)=10
}
Πινακας α(10)
α(0)=αλφα
Τύπωσε α(0).χ, α(0).α(3)
\\ εδώ λέμε για 1 στοιχείο αντιγραφή
Στοκ α(0για 1, α(3)
α(0).χ=100
α(0).α(3)=1234
Τύπωσε α(3).χ, α(3).α(3)   \\10
Τύπωσε α(0).χ, α(0).α(3)   \\1234


Όπως βλέπουμε δεν αντέγραψε η εντολή ΣΤΟΚ απλά το δείκτη του αντικειμένου, αλλά όλο το αντικείμενο σε ένα νέο. Τα αντικείμενα στην Μ2000 εντός των στοιχείων πίνακα είναι "πτητικά" ή "χωρίς όνομα", και παίρνουν το όνομα του στοιχείου που βρίσκονται. Λέγονται "πτητικά" γιατί μπορούμε να τα βάλουμε σε χώρους που θα μείνουν και μετά το πέρας του τμήματος που τα δημιούργησε. Ενώ η ομάδα άλφα, που δεν είναι πτητική, θα διαγραφεί στο πέρας εκτέλεσης του τμήματος. Φυσικά αν δεν αντιγράψουμε κάπου τον πίνακα που κρατάει τη πτητική ομάδα, θα χαθεί και αυτός και ότι έχει μέσα.

Δείτε εδώ το παράδειγμα.
Τμημα κ {
      ομαδα αλφα {
            χ=10
            Πίνακας α(10)=10
      }
      Βάλε αλφα
}
Πίνακας κ(10)
κ
Πάνω 
Διαβασε βήτα
Διαβασε Κ(3)
Τύπωσε βήτα.α(4), Κ(3).α(4)
Λιστα


Η εντολή Πάνω βγάζει αντίγραφο την κορυφή του σωρού, και εδώ επειδή είναι ομάδα κάνει αντίγραφο της ομάδας. Αν την είχαμε δυο φορές θα είχαμε δυο αντίγραφα. Και αν είχαμε δυο φορές την Διάβασε βήτα θα είχαμε ένωση στη δεύτερη φορά. Όταν ένα αναγνωριστικό είναι ομάδα και του δίνουμε μια ομάδα, τότε γίνεται ένωση. Το βήτα αν το κάνω ομάδα δεν μπορώ να το αλλάξω. Δείτε γιατί από την έξοδο της εντολής Λίστα που δείχνει ότι ουσιαστικά το σύστημα έχει φτιάξει την βήτα.χ και τον πίνακα βήτα.α(). Η ομάδα υπάρχει ως "κατάλογος" αλλά υπάρχουν όλα τα στοιχεία της ξεχωριστά! Δείτε όμως πως η ομάδα στο Κ(3) δεν φαίνεται στην λίστα. Αυτό σημαίνει Ενθυλάκωση στη Μ2000. Το στοιχείο πίνακα Κ(3) έχει μια πτητική ομάδα, που σημαίνει ότι φέρει ότι και το βήτα αλλά σε κλειστή μορφή. Ανοίγει μόνο για το διάστημα που καλούμε ένα στοιχείο του, όπως το Κ(3).α(4). Η έννοια της επέκτασης των αντικειμένων στην Μ2000 έχει να κάνει με δυο πράγματα, με την ένωση μιας άλλης ομάδας, μιας διαφορετικής αλλά και με την ένωση μιας συνάρτησης ή ενός τμήματος που ενώ υπήρχε έρχεται τώρα με άλλο κώδικα.  Υπάρχει ένας τρόπος να "απαγορέψουμε" την αλλαγή των συναρτήσεων τουλάχιστον ή για την ακρίβεια να απαγορέψουμε την μόνιμη αλλαγή, ενώ προσωρινά να την επιτρέπουμε. Αυτό γίνεται αν ορίσουμε ένα πίνακα να έχει βάση μια κλάση. Τότε ο πίνακας κρατάει τις μεθόδους και τις συναρτήσεις της κλάσης μια φορά για όλα τα στοιχεία. Π.χ.
 Πίνακας Κ(10)=Αλφα() 
θα έκανε τον πίνακα να έχει δέκα ομάδες από τον κατασκευαστή Άλφα().

Αν θέλουμε προσθέτουμε 10 ακόμα στοιχεία χωρίς να σβήσουμε τα 10 πρωτα
 Πίνακας Κ(20)
Όμως τώρα έχουμε και δέκα άδεια στοιχεία. Η εντολή Πίνακας δεν έβαλε στοιχεία. Αν έβαζα το Πίνακας Κ(20)=Αλφα() τότε δεν θα διατηρούσα στοιχεία.
Για να γίνει κατανοητό αυτό στο παρακάτω παράδειγμα χρησιμοποιώ την εσωτερική συνάρτηση Τυπος$() που μας λέει (στα αγγλικά) τι τύπος είναι η μεταβλητή μας. Στις ομάδες λέει Group. Αν όμως δεν έχουμε δώσει τιμή σε ένα στοιχείο πίνακα λέει Empty. Αν το διάβαζε ο ερμηνευτής εκφράσεων θα έκανε το Empty ως 0. Ενώ αν ήταν αλφαριθμητικό θα το έκανε "" που σημαίνει κενό αλφαριθμητικό. Εδώ λοιπόν τυπώνουμε μια φορά Empty και δυο φορές Group. Τη δεύτερη φορά έχουμε αλλαγή τιμής. Η εντολή Στοκ κάνει αντιγραφές, αλλά δεν κάνει "ένωση", δηλαδή θα καθαρίσει την περιοχή και θα βάλει τις τιμές που έχουμε κανονίσει.

Κλάση αλφαβητα {
      χ=10
      Πίνακας α(10)=10
}
τμημα κ {
      ομαδα αλφα {
            χ=10, ψ=12
            Πίνακας α(10)=10
      }
      Βάλε αλφα
}
Πίνακας Κ(10)=αλφαβητα()
κ
Πάνω 
Διαβασε βήτα
Διαβασε Κ(3)
Πίνακας Κ(20)
Τύπωσε βήτα.α(4), Κ(3).α(4)
Τύπωσε τύπος$(Κ(15))
Κ(15)=Κ(3)
Κ(15).χ=1500
Τύπωσε Κ(15).ψ
Τύπωσε τύπος$(Κ(15))
Στοκ Κ(10θεσε 10,αλφαβητα()
Τύπωσε τύπος$(Κ(19))
Τύπωσε Κ(15).χ   \\ έγινε 10 όπως το θέσαμε παραπάνω στην εντολή Στοκ
Τύπωσε Έγκυρο(Κ(15).ψ)
Λιστα


Δείτε λοιπόν πως η ψ υπάρχει στην Κ(15)  όταν αντιγράψαμε την Κ(3), αλλά μετά η Στοκ την καθάρισε και έβαλε την άλφαβητα() που μοιάζει με την άλφα() του τμήματος κ αλλά χωρίς το ψ. Η συνάρτηση Έγκυρο() δίνει 0. Εκτός από τις συναρτήσεις που γυρνούν ομάδες, μια οποιαδήποτε ομάδα γυρνάει επίσης ομάδα! Μπορεί να είναι δηλαδή ένας κατασκευαστής. Εδώ ο κατασκευαστής είναι από στοιχείο πίνακα (βάλτε τις τρεις γραμμές για συνέχεια του προηγούμενου)

Στοκ Κ(15θεσε 1, Κ(3)
Τύπωσε τύπος$(Κ(15))
Τυπωσε Κ(15).ψ  \\ τυπώνει 12


ή αυτές τις γραμμές

Στοκ Κ(15θεσε 1, βήτα
Τύπωσε τύπος$(Κ(15))
Τυπωσε Κ(15).ψ   \\τυπώνει 12


Άλλες "εκφάνσεις" της εντολής ΣΤΟΚ είναι οι παρακάτω (δείτε πώς σε ένα πίνακα "αριθμών" βάζουμε και αλφαριθμητικά)

Πίνακας Α(10), Β(20)
Α$="οκ"
Κ=10
ΣΤΟΚ Α(0από Α$, Κ
ΣΤΟΚ Α(0για 2, Β(15)
καθαρο ΑΑ$, κκ
ΣΤΟΚ Β(15σε ΑΑ$, κκ
Τυπωσε ΑΑ$, κκ


Πώς γίνεται να βάζουμε αλφαριθμητικά σε έναν πίνακα αριθμών; Γίνεται γιατί ουσιαστικά οι πίνακες παίρνουν τιμές που το λειτουργικό σύστημα τις λέει Variant. Είναι θέμα μετά το πως θα τις προσπελάσουμε. Δηλαδή Αν το Α$="1234" τότε το Α(0) θα ήταν το 1234 και ως αριθμός.
Αρχικά δεν είχα καμία ιδέα για αυτή την "ανωμαλία". Αλλά όταν έφτιαξα τις αναφορές τότε βγήκε πρώτη φορά αυτό:
Αλφα$="1234"
Βάλε &Αλφα$
Διάβασε &Β
Τύπωσε Β
Β++
Τύπωσε Αλφα$

Τυπώνει το αλφαριθμητικό 1235
Πραγματικά δεν το είχα σχεδιάσει έτσι, απλά βγήκε! Μετά είδα και το άλλο:
Πίνακας Αβγ(100)=1000
Βάλε &Αβγ()
Διάβασε &Βγδ$()
Αβγ(4)+=100
Τύπωσε Βγδ$(3),Βγδ$(4)

Δίνει 1000 και 1100 ως αλφαριθμητικά!

Εδώ θα θυμηθούν οι παλιοί προγραμματιστές ότι στον Clipper (βασίζονταν στη dBase III) οι μεταβλητές ήταν διπρόσωπες, και αλφαριθμητικές και αριθμητικές.
Αρχικά σχεδίασα αυτό (δείτε την χρήση του διπλού συμβόλου":="):

Τύπωσε $(4)   ' αναλογική γραφή - μπορούμε να την διαγράψουμε!
Πίνακας Δ$(100)
Δ$(0):="ΑΒ11",1.567,3,"ναι","ΚΛ23",5,6,"όχι"
Για Ι=0 εως 4 ανά 4 
      Τύπωσε μορφη$("ύφασμα {0} με {1:2} μέτρα, παραγελία {2}"Δ$(Ι),τιμη(Δ$(Ι+1))Δ$(Ι+3))
Επόμενο Ι


Δείτε τώρα πως γίνεται πιο όμορφο με έναν δεύτερο πίνακα που δείχνει τα ίδια στοιχεία, είναι αναφορά αλλά έχει διαφορετική προσαρμογή (interface):

Τύπωσε $(4)
Πίνακας Δ$(100)
Δ$(0):="ΑΒ11",1.567,3,"ναι","ΚΛ23",5,6,"όχι"
Ένωσε Δ$() στο Τ()
Για Ι=0 εως 4 ανά 4 
      Τύπωσε μορφη$("ύφασμα {0} με {1:2} μέτρα, παραγελία {2}"Δ$(Ι)Τ(Ι+1)Δ$(Ι+3))
Επόμενο Ι


Η εντολή Ένωσε κάνει ακριβώς αυτό:
Βάλε &Δ$() : Διάβασε &Τ() 
Φτιάχνει τον πίνακα Τ() να δείχνει τα ίδια στοιχεία αλλά τώρα ο ερμηνευτής εκφράσεων "τραβάει" τιμές από τα στοιχεία.

Βέβαια ένα ερώτημα πλανάται και πρέπει να απαντήσω. Πώς γίνεται ο ερμηνευτής εκφράσεων να γυρνάει αντικείμενα;  Είναι πολύ απλό όταν σου το πουν (έκανα χρόνια να το καταλάβω, γιατί δεν μου το είπε κανείς), γυρνάει και τιμή π.χ. 0 και αντικείμενο και είναι θέμα της λειτουργίας "αντικατάστασης" να δει τι μπορεί να κάνει, να δει αν υπάρχει αντικείμενο και εκεί που θα το βάλει αν υπάρχει άλλο αντικείμενο!
Αντικείμενα είναι το Έγγραφο, η Ομάδα, το αντικείμενο COM (έχει διάφορα ονόματα, μπορεί να είναι το Word, και τα ορίζουμε με την Όρισε), η ιδιότητα αντικειμένου (σχετίζεται με το προηγούμενο).
Εδώ ένα παράδειγμα με ένα αντικείμενο MSComDlg.CommonDialog στην παραλλαγή για άνοιγμα αρχείου! Το αντικείμενο πρέπει να το "χαλάσουμε" με το να ορίσουμε τη μεταβλητή MsComDlg  ως τίποτα. Τα αντικείμενα αυτά "χαλάνε" όταν η τελευταία αναφορά "φύγει". Δεν μπορούμε να τα αντιγράψουμε όπως τις ομάδες. Θα αντιγραφεί μόνο το ψεύτικο 0 και όχι το αντικείμενο, γιατί ο διερμηνευτής ελέγχει τι είναι ένα αντικείμενο και αν μπορεί να το αντιγράψει (αν ξέρει πώς).

ΑΝ ΒΑΛΕ.ΑΔΕΙΑ$("MSComDlg.CommonDialog")<>"" ΤΟΤΕ {
      Συνάρτηση ΠάρεΑρχειο$ {
            Διάβασε Που$
            Όρισε  MsComDlg  "MSComDlg.CommonDialog"
            Δες {
                  Με MsComDlg, "Flags", 0x1804, "FileName" ως ιδιότητα.όνομα$,"DialogTitle", "Άνοιξε ένα αρχείο εικόνας"
                  Με MsComDlg, "Filter",  "Αρχεία jpg (*.jpg)|*.jpg", "InitDir", Που$
                  Μέθοδος MsComDlg "ShowOpen"
                  Δες { 
                  =ιδιότητα.όνομα$
                  }
            }
            Όρισε   MsComDlg  Τίποτα
      }
      MyPictures = 0X027
      CSIDL_COMMON_PICTURES=0x36
      α$=ΠάρεΑρχειο$(τόπος$(CSIDL_COMMON_PICTURES)+"Sample Pictures\")
      αν α$<>"" τότε {
      θέση 0,0
      \\ Εικόνα α$, χ.σημεία
      Εικόνα α$, χ.σημεία, υ.σημεια
      }
      ΔΙΑΓΡΑΦΗ ΑΔΕΙΑΣ "MSComDlg.CommonDialog"
}



Κανονικά με αυτές μόνο τις εντολές είμαστε ΟΚ..Δείτε ότι εδώ θέλει ο φάκελος το \ στο τελος.

MyPictures = 0X027
CSIDL_COMMON_PICTURES=0x36
Ανοιγμα.Εικόνας "", τόπος$(CSIDL_COMMON_PICTURES)+"Sample Pictures\"
διαβασε α$
αν α$<>"" τότε {
θέση 0,0
\\ Εικόνα α$, χ.σημεία
Εικόνα α$, χ.σημεία, υ.σημεια
}



Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου

You can feel free to write any suggestion, or idea on the subject.