Τετάρτη 22 Ιουνίου 2016

Η ώρα της BASIC - Παράδειγμα από το 1964.

Σήμερα η ανάρτηση έχει να κάνει με την γλώσσα BASIC. Η Μ2000 έχει στοιχεία της BASIC και εδώ θα δούμε ένα πρόγραμμα από το εγχειρίδιο της πρώτης BASIC του 1964:


Εδώ με μερικές αλλαγές για να λειτουργήσει σωστά (δείτε ότι δεν έχουμε πολλές αλλαγές, μόνο η εντολή DATA πήγε στην αρχή (στη Μ2000 έχει σημασία που είναι), και στο τέλος μπήκε ένα IF που ελέγχει αν έχουμε στοιχεία ακόμα και αν ναι κάνει επιστροφή. Υποψιάζομαι ότι η παλιά Basic όταν δεν είχε στοιχεία, απλά τερμάτιζε! Επίσης υπήρχε ένα θέμα με τη ρίζα. Η Μ2000 δεν δέχεται όρισμα μηδέν ή αρνητικό. Όπως είναι γραμμένο στο εγχειρίδιο ο έλεγχος της D γίνεται αφού τρέξει η εντολή με τον υπολογισμό της ρίζας. Στη Μ2000 δεν μπορούμε να δώσουμε μηδέν άρα αλλάζουμε τη σειρά εντολών, και επιπλέον βάζουμε την συνάρτηση ABS() που δίνει το απόλυτο νούμερο (δηλαδή αφαιρεί το πρόσημο).

Δείτε τους αριθμούς γραμμών. Ο διορθωτής βάζει αυτόματα αριθμούς αν δει ότι η προηγούμενη γραμμή ξεκινάει με αριθμό (ανά παράγραφο ελέγχει όχι ανά γραμμή, οπότε σε αναδίπλωση λέξης, δεν έχουμε θέμα. Με F1 βάζουμε ή βγάζουμε την αναδίπλωση λέξης στον διορθωτή). Στη εικόνα κάτω έχω δώσει τις εντολές CLS, ROW-1 και μετά το EDIT B και άνοιξε έτσι ο διορθωτής:



\\ basic
  1 FORM 80,40
  2 DATA 1, -2, -3, 1, -4, 4, 1, 0, 2
  5 PRINT "QUADRATIC EQUATION"
  6 PRINT
10 READ A, B, C
20 LET D = B * B - 4 * A * C
30 LET S = - B / ( 2 * A )
40 IF D = 0 THEN GOTO 100
50 LET T = SQRT(ABS( D) ) / (2 * A)
60 IF D < 0 THEN GOTO 200
70 PRINT A, B, C, " TWO REAL ROOTS"
80 PRINT "ROOTS =";S+T, S-T
90 GOTO 300
100 PRINT A, B, C, " ONE ROOT"
110 PRINT "ROOT ="; S
120 GOTO 300
200 PRINT A, B, C, " COMPLEX ROOTS"
210 PRINT "REAL PART ="; S, " IMAGINARY PART ="; T
300 PRINT
310 IF NOT EMPTY THEN GOTO 10


Με λίγες αλλαγές έχουμε και το πάνω δεξιά πρόγραμμα της σελίδας τους εγχειριδίου του 1964
\\ LN() natural logarithm
\\ Log() base 10 logarithm
010 S=0
020 DEF FNL(X)=LN(X)/LN(10)
030 FOR I=1 TO 100
040 S+=FNL(I)
050 NEXT I
060 PRINT S/100
070 S=0
080 FOR I=1 TO 100
090 S+=LOG(I)
100 NEXT I
110 PRINT S/100



Σε Wine (Ubuntu Studio)

Σε πιο νέες εκδόσεις της Μ2000 μπορούμε να χρησιμοποιήσουμε αριθμό γραμμής αμέσως μετά το Then. Αν όμως το Goto γίνεται σε ετικέτα τότε πρέπει να χρησιμοποιηθεί το Goto. Σε αριθμούς γράφουμε εντολή ακριβώς δίπλα. Σε ετικέτες πχ αλφα:  δεν γράφουμε εντολή δίπλα, μόνο σημειώσεις με ' ή \
Οι αριθμοί μπορούν να έχουν μηδενικά στην αρχή. Πχ το 0010 είναι το 10 και το Goto 10 θα πάει σε αυτό. Η σειρά των αριθμών δεν παίζει ρόλο. Μπορούμε το 1000 να το έχουμε στην αρχή! Οι αριθμοί μπορεί να είναι από 00001 εως 99999. Αν δεν χρησιμοποιούμε την εντολή Ένθεση (Inline) που παρεμβάλει κώδικα μέσα σε μπλοκ κώδικα, τότε με την πρώτη χρήση Goto/Gosub (Προς/Διαμέσου) ο αριθμός, ή η ετικέτα, καταγράφεται, και την επόμενη φορά θα βρεθεί άμεσα (μέσω συνάρτησης κατακερματισμού και ειδική λίστας καταγραφής). Η λίστα καταστρέφεται στο πέρας εκτέλεσης του τμήματος/συνατησης, ή μετά από εντολή ένθεσης.

\\ basic
  1 FORM 80,40
  2 DATA 1, -2, -3, 1, -4, 4, 1, 0, 2
  5 PRINT "QUADRATIC EQUATION"
  6 PRINT
10 READ A, B, C
20 LET D = B * B - 4 * A * C
30 LET S = - B / ( 2 * A )
40 IF D = 0 THEN 100
50 LET T = SQRT(ABS( D) ) / (2 * A)
60 IF D < 0 THEN 200
70 PRINT A, B, C, " TWO REAL ROOTS"
80 PRINT "ROOTS =";S+T, S-T
90 GOTO 300
100 PRINT A, B, C, " ONE ROOT"
110 PRINT "ROOT ="; S
120 GOTO 300
200 PRINT A, B, C, " COMPLEX ROOTS"
210 PRINT "REAL PART ="; S, " IMAGINARY PART ="; T
300 PRINT
310 IF NOT EMPTY THEN 10


Επίσης μπορούμε να θέσουμε μερικούς διακόπτες για να έχουμε το For όπως στην Basic (πχ το For i=1 to 0 :   Print "ok": Next i δεν θα τρέξει γιατί το βήμα είναι 1, θετικό, και το πρόσημο τέλος-αρχή είναι 0-1= -1, αρνητικό. Ενώ εξ ορισμού το βήμα το χρησιμοποιεί η Μ2000 ως απόλυτο νούμερο και την κατεύθυνση την δίνουν τα νούμερα αρχή και τέλος.
Επίσης μπορούμε να ορίσουμε οι πίνακες να ορίζονται όπως στην Basic, όπου το DIM A(10) δίνει 11 στοιχεία, από 0 έως 10. Εδώ το +DIM δεν θα ισχύσει αν έχουμε δώσει BASE 1 (ή ΒΑΣΗ 1) όπου το DIM A(10) ή Πίνακας Α(10) θα δώσει στοιχεία από 1 έως 10 (ορισμένες basic έχουν το 1 ως βάση)
Set Switches "+FOR +DIM"
Θέσε Διακόπτες "+FOR +DIM"

Μπορούμε να βγαίνουμε με goto από For/Next (δηλαδή FOR χωρίς αγκύλες) αλλά πρέπει να γίνεται με το exit for. Η exit for αν έχει αριθμό ή λέξη μετά εκτελεί την έξοδο σωστά (ρυθμίζει τη στοίβα επιστροφής) και εκτελεί το Goto στον αριθμό ή στην ετικέτα που δείχνει η λέξη. Προσοχή αν δεν υπάρχει ο αριθμός ή η ετικέτα είναι σαν έξοδος από το τμήμα, δεν γίνεται επιστροφή λάθους.

Επίσης δείτε ότι η ετικέτα είναι σε δική της γραμμή μόνη της! Στις ετικέτες μπορούμε να βάλουμε μόνο σημειώσεις δίπλα με ' ή / χαρακτήρες στην αρχή.
Οι αριθμοί και οι ετικέτες αναζητούνται μια φορά και καταγράφονται. Αλλά μόνο στο σώμα ενός τμήματος ή μιας συνάρτησης. Σε ορισμούς τμημάτων και συναρτήσεων εντός τμήματος ή συνάρτησης αποφεύγουμε να βάζουμε ίδιες ετικέτες ή αριθμούς γραμμών γιατί ο διερμηνευτής στν αναζήτηση κοιτάει γραμμές δεν κοιτάει το που είναι αυτές, και οι ορισμοί είναι και αυτοί γραμμές του τμήματος.

Module TestThis {
      For j=1 to 3
            For i=1 to 10
                  If i=5 Then Exit For alfa
            Next
            Print "bad"
alfa:
            Print "ok"
      Next
      For j=1 to 3
            For i=1 to 10
                  If i=5 Then Exit For 100
            Next
            Print "bad"
100      Print "ok"
      Next
}
TestThis


Μπορούμε να χρησιμοποιούμε ρουτίνες και συναρτήσεις όπως στην BASIC γράφοντάς της στο τέλος του τμήματος ή της συνάρτησης που ανήκουν. Η κλήση της Alfa() γίνεται με όνομα ή με την Διαμέσου ή GOSUB.

Module TestThis {
      i=100
      Alfa(3)
      Gosub Alfa(3)
      Print @p(10)=3628800
      Print i=100
      Sub Alfa(x)
            Local i=x**2
            Print i, x
      End Sub
      Function p(i as long)
            If i<2 Then =1&: Exit Function
            =@p(i-1)*i
      End Function
}
TestThis

Οι συναρτήσεις που συνδέουμε στο τέλος καλούνται με το @ πριν. Δεν μπορούμε να τις περάσουμε με αναφορά και δεν έχουν δικό τους σωρό τιμών (όπως έχουν οι κανονικές και οι λάμδα).
Και οι ρουτίνες με παρενθέσεις και οι συναρτήσεις με @ έχουν αναδρομή. Όμως οι ρουτίνες με παρενθέσεις έχουν τεράστια δυνατότητα αναδρομή, και μπορούμε να το ορίσουμε, πχ με την Όριο.Αναδρομής 100000 βάζουμε το όριο στις 100 χιλιάδες κλήσεις. Οι συναρτήσεις έχουν περίπου 3500 βάθος κλήσεων.

Επίσης μια διαφορά αυτών των δομών Sub/End Sub και Function/End Function με τα τμήματα και τις κανονικές συναρτήσεις και τις λάμδα συναρτήσεις είναι ότι οι πρώτες έχουν θέαση κοινή με το τμήμα ή τη συνάρτηση που ανήκουν. Για το λόγο αυτό αν θέλουμε να ορίσουμε τοπικές μεταβλητές τις ορίζουμε με Local (ή Τοπικές ή Τοπική). Στην p() η i είναι τοπική και φτιάχνεται κάθε φορά που καλούμε αναδρομικά τη p() και διαγράφεται κάθε φορά που επιστρέφουμε από την συνάρτηση.

H GOSUB ;ή ΔΙΑΜΕΣΟΥ έχει και μια παραλλαγή για κλήση απλή ρουτίνας, με μια εντολή Επιστροφή στο τέλος, χωρίς να περάσουμε παραμέτρους (δίνουμε το όνομα ετικέτας ή τον αριθμό γραμμής).
Rem {
      Multiline Rem
      16bit Integer
      Try Long, Decimal, Currency, Double, Single
      Not try Boolean here.
}
DEF INTEGER K=10
WHILE K>0
      GOSUB 1000
      K--
END WHILE

END
1000 PRINT "K=";K, TYPE$(K)="Integer"
1010 RETURN



Υπάρχουν τα ON GOTO και ON GOSUB  (ΑΠΟ ΠΡΟΣ και ΑΠΟ ΔΙΑΜΕΣΟΥ)

Do
      X=Random(-3,4)
      Print X
      if x<=0 then Print "Exit now from block", X
      On X Goto 100, 200, 300
      Print "X>3", X
      Exit
      100 Print "ok 1" : Exit
      200 Print "ok 2" : Exit
      300 Print "ok 3" : Exit
Always
Print "finish"





Δευτέρα 20 Ιουνίου 2016

Μικρή αναθεώρηση 9 (Έκδοση 8.2) και παραδείγματα

1. Η αναθεώρηση 9 έλυσε ένα παλιό bug, όπου δεν άφηνε να αλλάξουμε απευθείας μια συνάρτηση ή ένα τμήμα μιας ομάδας. Η λύση μέχρι πριν την αλλαγή ήταν η συγχώνευση με μια νέα ομάδα με ίδια ονόματα στα τμήματα που θέλαμε να αλλάξουμε. Το παρακάτω παράδειγμα βγάζει λάθος στις παλαιότερες εκδόσεις.
Ομάδα Άλφα {
      Τμήμα Οκ {
            Τύπωσε "Οκ"
      }
}
Άλφα.Οκ
Τμήματα ? \\ εμφανίζει και το Άλφα.Οκ
Ομάδα Άλφα {
      Τμήμα Οκ {
            Τύπωσε "Εντάξει"
      }
}
Άλφα.Οκ
Τμήματα ? \\ εμφανίζει και το Άλφα.Οκ

2. Ετοιμάζω το εγχειρίδιο της Μ2000, ένα εγχειρίδιο που στόχο έχει να βάλει στην ιδέα της Μ2000 το αναγνώστη παρά να του μάθει προγραμματισμό, ή να εμφανίσει όλες τις εντολές τις γλώσσας.
Το blog έχει αρκετά παραδείγματα και μερικά τεύχη ενός μεγάλου εγχειριδίου εδώ

Παρακάτω είναι ένα παράδειγμα που δείχνει την "Επίλυση Αριστερής Έκφρασης" που κάνει ο διερμηνευτής Μ2000 όταν σε μια κατάσταση που έχει ζεύγη κλειδιών και τιμών βάλουμε σε μια τιμή πίνακα. Κανονικά αλλαγές τιμών στην κατάσταση γίνεται με εντολή όταν πρόκειται για "όλη" την τιμή. Αλλά μια τιμή όπως ένας πίνακας έχει και επιμέρους τιμές. Στις επιμέρους τιμές δρα η επίλυση αριστερής έκφρασης.

(στο Α=12+3 το 12+3 είναι δεξιά έκφραση, ενώ στο Α(2*Χ)=10 το 2*Χ είναι αριστερή έκφραση. Η αριστερή έκφραση υπολογίζει το Που θα μπει κάτι, ενώ η δεξιά το Τι θα μπει)


Επιπλέον στο παράδειγμα φαίνεται και η χρήση του χειριστή << για τους πίνακες, όπου εκτελείται για κάθε στοιχείο η συνάρτηση Β() (η οποία είναι μια λάμδα συνάρτηση και έχει ένα αντίγραφο της από_που (εδώ υπάρχει διαφορά με την Python, οι non local μεταβλητές μένουν στην λάμδα, και δεν αλλάζουν τιμές έξω από αυτήν, αλλά στην εισαγωγή μπαίνουν ως αντίγραφο)

Αυτό είναι ένα παράδειγμα από το εγχειρίδιο

κατάσταση αλφα=1,2,3
\\ βοηθητική συνάρτηση για να παράγουμε πίνακες
\\ με τιμές που γεμίζουμε με μια εσωτερική λάμδα συνάρτηση
Α=Λάμδα ->{
      Διάβασε Πόσα, από_που
      Β=Λάμδα από_που ->{
         =από_που
        από_που++
      }
      Πίνακας αλφα(Πόσα)<<Β()
      =Αλφα()
}
\\ η Α() παίρνει τον αριθμό στοιχείων και το νούμερο που θα βάλει στο πρώτο
\\ δηλαδή  στο στοιχείο 0
Επιστροφή αλφα, 1:=Α(20,155), 2:=Α(20,100), 3:=Α(10,200)
Για ι=0 έως 19
      Τύπωσε αλφα(1)(ι),
Επόμενο ι
Τύπωσε
Για ι=0 έως 19
      Τύπωσε αλφα(2)(ι),
Επόμενο ι
Τύπωσε
Για ι=0 έως 9
      Τύπωσε αλφα(3)(ι),
Επόμενο ι
Τύπωσε
\\ επίλυση αριστερής έκφρασης
αλφα(1)(0)++
Τύπωσε αλφα(1)(0) \\ 156
Τύπωσε διάσταση(Αλφα(1)) \\ 1 είναι μονοδιάστατος ο πίνακας στο κλειδί 1
Τύπωσε διάσταση(Αλφα(1),1) \\ 20 έχει είκοσι στοιχεία στη διάσταση 1

Κυριακή 19 Ιουνίου 2016

Μικρή Αναθεώρηση 8 (έκδοση 8.2)

Ένα φτιάξιμο στην Εντολή Δρομέας. Μετακινούσε το δρομέα "λογικά", όχι πραγματικά, και σε μια εντολή που εμφανίζει κείμενο σε περιοχή στην οθόνη δημιουργούσε θέμα. Η Τύπωσε @(10,10); κάνει την ίδια δουλειά με την Δρομέας. Η Δρομέας ( Cursor) έχει μια διαμόρφωση με θαυμαστικό Δρομέας! η οποία συγχρονίζει τον δρομέα γραφικών με αυτόν του κειμένου.


Άλλα νέα:
Διέκοψα την συμμετοχή μου στο Insomnia.gr. Ζήτησα να κλείσουν τον λογαριασμό μου. Ζήτησα επίσης να αφαιρεθεί οποιαδήποτε αναφορά σε κείμενό μου και τα κείμενά μου. Αυτό δεν έγινε ακόμα. Ίσως γίνει αργότερα.
Δυστυχώς το επίπεδο συζήτησης ήταν απογοητευτικό. Εκεί ορισμένα άτομα υποστηρίζουν, με μανία όλους τους λόγους που η Μ2000 είναι άχρηστη. Ενώ στην ουσία πρέπει κανείς να έχει την εξυπνάδα και να καταλάβει τι χρησιμότητα έχει καθετί, όπως και η Μ2000.
Μειονεκτήματα που αναφέρθηκαν:

  • Είναι εφαρμογή και όχι γλώσσα  (δεν μπορώ να κατανοήσω εδώ τι θέλουν να πουν. Ναι ο διερμηνευτής είναι εφαρμογή, που αντικείμενο έχει την Γλώσσα Μ2000)
  • Ο διερμηνευτής είναι γραμμένος σε VB6 η οποία δεν υποστηρίζεται (Προφανώς δεν υποστηρίζεται το IDE της VB6, αλλά υποστηρίζονται προγράμματα γραμμένα σε αυτήν ακόμα και στα Windows 10)
  • Η χρήση ελληνικών εντολών αποπροσανατολίζει και δεν προσφέρει γνώση όπως αν είχαμε χρήση αγγλικών εντολών (Παραβλέπουν το γεγονός ότι έχει δυο λεξικά η Μ2000, αλλά ακόμα και να είχε ένα, δεν θα υπήρχε πρόβλημα να μάθουν τις έννοιες στο προγραμματισμό και όχι τα ονόματα εντολών - κάθε γλώσσα ακόμα και στα αγγλικά έχει διαφορετικό τρόπο σύνταξης και χρήση διαφορετικών λέξεων, αν όχι σε όλα σίγουρα στα περισσότερα)
  • Η ομοιότητά της (έχει ελληνικά) με την Γλώσσα του σχολείου (καμία σχέση δεν έχει, εκτός από τη χρήση ελληνικών), "σίγουρα" την κατατάσσει σε "ψευδογλώσσα", και τα προγράμματα που δείχνω, σε κώδικα και σε βίντεο (την έξοδο των προγραμμάτων), δεν είναι πραγματικά! Απολαμβάνω μια πλήρη αμφισβήτηση. Σε άλλα site, όπως το dwrean.net εδώ και χρόνια από τις προηγούμενες εκδόσεις, δίνεται σύνδεσμος προς τη γλώσσα και δεν είδα ποτέ να έχει παράπονο κανείς. Αντίθετα μόνο θετικά μηνύματα βλέπω.
  • Κάποιοι ζήτησαν TCP/IP και άλλα πράγματα τα οποία δεν περιλαμβάνει η γλώσσα. Όχι επειδή τους άρεσε η γλώσσα αλλά για να "γελάσουν" πάνω στην "αδυναμία μου" να ανταποκριθώ. Προφανώς το "γελοίο" του αιτήματος είναι να λες σε κάποιον να κάνει κάτι αρκετά δύσκολο για να αποδείξει στον αιτούντα ότι δεν είναι "ικανός" να το κάνει. Αυτή η κόντρα περί ικανών και μη δεν ήταν σκοπός μου, αλλά φάνηκε πως στο συγκεκριμένο site, Insomnia, μια ομάδα μελών έχει την συνήθεια να "επιβάλλει" αυτήν την γραμμή, την κόντρα, και ένας λόγος που ακύρωσα τη συνδρομή μου ήταν για να αποφύγω αυτές τις ανούσιες κόντρες. 
  • Επιπλέον πολλοί παραγνωρίζοντας ή το έκαναν εσκεμμένα ότι εργάζομαι από χόμπι στο έργο αυτό, δηλαδή αποτελεί ένα προσωπικό έργο, έφεραν ζήτημα ότι "δεν έχω εργαστεί με άλλα άτομα πάνω σε προγραμματισμό" και αυτό φαίνεται στο κώδικα του διερμηνευτή. Γιατί πρέπει να αποδείξω ότι ο κώδικας έχει γραφτεί με συνεργασία, αφού είναι προσωπική εργασία; Μπορεί να σκέφτηκαν την πρότερη έλλειψη συνεργασίας (μη εμπειρία από συνεργασία) από την κατάσταση του κώδικα (μα ποιοι είναι οι Πουαρώ του Insomnia). Αυτή η λεπτομέρεια (ότι είναι προσωπική εργασία), δεν τους ενοχλεί, ούτε τη βλέπουν σημαντική.  Αυτό τώρα γιατί να γίνει θέμα; To 2006 στο Μαθηματικό του Πανεπιστημίου Αθηνών έχω αναρτήσει σχετικά για την Μ2000 και μέχρι τώρα ενώ φαίνεται ένα ενδιαφέρον ως προς το διερμηνευτή, δεν φαίνεται ενδιαφέρον για να αναλάβει νεολαία να το φέρει στα δικά της μέτρα, ενώ έχω κάνει την πρόταση για συμμετοχή στην ανάπτυξη! Ευθέως ζητάω μια ομάδα να αναλάβει την ανάπτυξή της. Από τότε μέχρι σήμερα έχω προβεί μόνος μου σε αναβαθμίσεις.
Φταίνε τα μέλη λοιπόν του Insomnia, ή οι moderators ή ο κάτοχος του τόπου; Δεν ξέρω! Απλά όπως είναι η κατάσταση τώρα στο site, οι θαμώνες στο φόρουμ Προγραμματισμός είναι απαράδεκτοι. Έγραψα σε κάποια φάση για δυο "κοπρόσκυλα" και αυτό θεωρήθηκε ύβρις. Με αποτέλεσμα να μου αφαιρέσουν την πρόσβαση για δέκα μέρες. Ενώ συνέχιζαν άλλα άτομα να γελοιοποιούν και εμένα και τη γλώσσα. Με αυτήν την πρακτική δεν συμφωνώ και για το λόγο αυτό ζήτησα να διαγραφεί ο λογαριασμός μου και ότι έχω γράψει εκεί ακόμα και αυτά που αντιγράφονται σε quote.
Γ.Κ.

Υ.Γ.
Μετά από email που έστειλα...επιτέλους κλειδώθηκε το θέμα Ενημέρωση για την Μ2000. Είδαν άλλα μέλη ότι έφυγα από το φόρουμ και παρόλα αυτά συνέχιζαν να γράφουν χαζομάρες και προσβολές.

Τρίτη 14 Ιουνίου 2016

Μικρή αναθεώρηση 6 (δεν αλλάζει κάτι στη γλώσσα)

Σε αυτήν την αναθεώρηση έβγαλα μια λειτουργία που ποτέ δεν γίνονταν (να φορτώσει μια συγκεκριμένη γραμματοσειρά που δεν είναι φορτωμένη στις γραμματοσειρές του συστήματος).
Επίσης δεν βγαίνει πια μήνυμα ότι δεν υπάρχει MIDI (όταν δεν υπάρχει driver) με msgbox (είχε μείνει καιρό αυτό), και τώρα δίνει λάθος (οπότε μπορούμε να το πιάσουμε με Try {} )
Αυτό το τελευταίο το είδα όταν έκανα δοκιμές σε Windows 10, σε VirtualBox μια δοκιμαστική έκδοση χωρίς ήχο όμως!


Αναθεώρηση 5 (Έκδοση 8.2)

1. Λάθος που δημιούργησα από αβλεψία στη προηγούμενη (3) αναθεώρηση
Κατάσταση κα1
Προσθήκη κα1,2:="αλφα"
Τύπωσε κα1$("2"), κα1$(2), κα1$(0!), εκφρ$(κα1,0)
από λάθος σε  ένα νούμερο στο κώδικα (έκανα μια μετατροπή στην αναθεώρηση 3)  δεν έβγαινε το άλφα στα δυο πρώτα

2. Μια μικρή διόρθωση στο Modules ? (Τμήματα ?) όπου μετά από θερμή επανεκκίνηση (Αρχή "" ή Start "") όταν δίναμε την εντολή αντί να δούμε τα τμήματα κράσσαρε ο διερμηνευτής.
3. Μια μικρή διόρθωση στην εντολή Σωρός όπου εμφανίζονται όλα τα αντικείμενα σωστά στο σωρό τιμών (με την εμφάνιση είχαμε θέμα όχι με την λειτουργία:

Άδειασε
Πίνακας Α(10)
Κατάσταση Αλφα=1,2,3
Διάρθρωση Κενή Βήτα ως Μακρύς *10
Ομάδα Δέλτα {Χ=10}
Συνάρτηση Ζήτα {=100}
Γεγονός Κ {Διάβασε Χ}
Βάλε "οκ",Α(), Αλφα, Βήτα,Κ, Δελτα, Ζήτα()
Τύπωσε Μέγεθος.Σωρού
Σωρός
Τύπωσε Φάκελος$(), Ταύτιση("NGEBIAS"), Ταύτιση("ΑΟΕΔΚΠΓ") \\ Ε για γεγονός

Εδώ  είναι μια δεύτερη περίπτωση. Πάλι στο θέμα της εμφάνισης λέμε. Γιατί εδώ βάζουμε στο σωρό ένα αντικείμενο που δείχνει έμμεσα το αντικείμενο φόρμα, ώστε αν τύχει και βγούμε από το τμήμα και μείνει το αντικείμενο στο σωρό να μην δείξει φόρμα. Βέβαια υπάρχει το ρίσκο εδώ να δημιουργήσουμε κάτι άλλο και να δείχνει αυτό το άλλο, γατί το αντικείμενο που δημιουργεί είναι έμμεσο αλλά δεν ταυτίζεται με άλλο τρόπο, είναι ένας δείκτης σε μια θέση στο πίνακα μεταβλητών.
Άδειασε
Τμήμα κκ {
      όρισε φόρμα1 φορμα
      βάλε φόρμα1
      σωρός
      όρισε φόρμα1 τίποτα
}
κκ
Τύπωσε μέγεθος.σωρού
σωρός

Δηλαδή αυτό θα κάνει το αντικείμενο στο σωρό να δείχνει την φόρμα1 του εξωτερικού τμήματος (δημιουργήθηκε ακριβώς μετά την εκτέλεση του κκ άρα έπεσε στο ίδιο νούμερο). Ο λόγος που δεν θέλω να κρατήσω αναφορά στη φόρμα1 είναι γιατί θέλω να μην μένει φορτωμένη με το πέρας του τμήματος και το όρισε φόρμα1 τίποτα του κάνει unload και το καταργεί. Αν όμως το κράταγε μια άλλη μεταβλητή, δηλαδή μια αναφορά στην φόρμα, τότε δεν θα γίνονταν unload. Κύρια βέβαια με ενδιαφέρει η επιστροφή από συνάρτηση. Αν γίνει επιστροφή από συνάρτηση της Φόρμα1 τότε θα πάρει το τίποτα ως επιστροφή. Αν την φόρμα1 την αντιγράψουμε σε άλλο όνομα (παλιά δεν γίνονταν) θα αντιγραφεί πάλι ένα έμμεσο αντικείμενο, έτσι ώστε ποτέ δεν θα κρατάει δεύτερη αναφορά μια φόρμα ή άλλο αντικείμενο που ορίσαμε με την όρισε.


Άδειασε
Τμήμα κκ {
      όρισε φόρμα1 φορμα
      βάλε φόρμα1
      σωρός
      όρισε φόρμα1 τίποτα
}
κκ
Όρισε φόρμα1 φορμα
Τύπωσε μέγεθος.σωρού
σωρός

ορισε φόρμα1 τίποτα

Κυριακή 12 Ιουνίου 2016

Αναθεώρηση 3 (έκδοση 8.2) Μικρό Bug

Μικρό Bug,
Το παρακάτω τύπωνε δυο φορές το 1212, ενώ έπρεπε την δεύτερη φορά να δώσει 0, αφού επιστρέψαμε τιμή 0 (ενώ αρχικά δεν είχαμε δώσει τιμή και τότε μόνο παίρνουμε σαν τιμή το κλειδί
κατάσταση αλφα
αα=0
αρ=1212
προσθήκη αλφα, αρ
Τύπωσε αλφα(αρ)
Επιστροφή αλφα, αρ:=0
Τύπωσε αλφα(αρ)


Αν το κλειδί είναι αριθμός θα ζητάμε αριθμό με το αλφα(), αν δεν ξέρουμε τι είναι μπορούμε να πάρουμε το κλειδί βάσει σειράς εσωτερικής, για ι= 0 έως Μήκος(αλφα)-1 θα πάρουμε το κλειδί  εκφρ$(αλφα, ι) ως αλφαριθμητικό (ό,τι να είναι)

Σάββατο 11 Ιουνίου 2016

Αναθεώρηση 2 (έκδοση 8.2)

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


Ε λέχθηκαν οι ρουτίνες για την αναδρομή, Εδώ ορίζουμε μέγεθος 100 χιλιάδων κλήσεων. (οι συναρτήσεις έχουν μέγιστο 14500 περίπου, γιατί χρησιμοποιούν τον Stack που ορίζεται στο πρόγραμμα που φορτώνει το αντικείμενο της Μ2000 - είναι ActiveX)

recursion.limit 100000
alfa(100000)


sub alfa(x)
if x>0 then alfa(x-1)
print x
end sub

Παρασκευή 10 Ιουνίου 2016

Η Κοινότητα της Μ2000

Από σήμερα ξεκινάει η κοινότητα της Μ2000.
είναι ένα φόρουμ φτιαγμένο στο Forumotion.com
Θα γίνονται συζητήσεις για την ανάπτυξη της γλώσσας, βοηθήματα, αλλά και κυρίως προγράμματα γραμμένα σε αυτήν.
Ο σύνδεσμός είναι:
http://m2000.forumgreek.com
και είναι ανοικτό για το κοινό!

Πέμπτη 9 Ιουνίου 2016

Μια μικρή αναθεώρηση στην 8.2 - και Διάρθρωση Παράδειγμα

Μια μικρή αναθεώρηση στην 8.2
Αν φτιάχναμε μια γενική συνάρτηση από τη γραμμή εντολών δεν την έβρισκε  ο διερμηνευτής. Τώρα είναι οκ. Είναι ένα bug που δεν σου περνάει από το μυαλό, αλλά επειδή αντιλαμβάνομαι τι περιμένω από τη Μ2000, με το που δω κάτι που δεν το περίμενα...το βρίσκω..και το διορθώνω. Το Bug, εδώ είναι στο τι περιμένουμε να γίνει "όταν" έχουμε την Χ κατάσταση και ο διερμηνευτής είχε αλλαχθεί στο βαθμό που αυτή την κατάσταση δεν την εξυπηρετούσε και γύρναγε μήνυμα λάθους, (όταν δεν έχει κάτι να κάνει με το κώδικα βγάζει "συντακτικό λάθος" ή "δεν έχει υλοποιηθεί αυτό")

Να και ένα μικρό πρόγραμμα (να έχει κάτι αυτή η ανάρτηση...)
Θα δούμε την Διάρθρωση Μνήμης (Buffer)
Η διάρθρωση είναι μέρος μνήμης, με συγκεκριμένη έκταση. Έχει και αλλαγή μεγέθους (resize), αν θέλουμε αλλάζουμε τον αριθμό στοιχείων και αν είναι περισσότερα διατηρεί τα υπάρχοντα και αν είναι λιγότερα πετάει τα παραπανίσια Προσοχή εδώ γιατί στην αλλαγή μεγέθους (resize) αλλάζει βάση, μπορεί να είναι αλλού η πραγματική μνήμη, από εκεί που γνωρίζαμε.

Φτιάχνουμε μια δομή με έναν ακέραιο 20 Χ 2 bytes (ή Ψηφία όπως τα λέμε στη Μ2000), και τρεις διπλούς (με υποδιαστολή και εκθέτη, double, 8 bytes)
Μετά φτιάχνουμε δυο διαρθρώσεις μνήμης, μια με μια μόνο δομή beta, και μία με 100 δομές (συνεχόμενες). Τα Χ Υ Ζ είναι offset, ή το "επιπλέον" που προσθέτουμε στη βάση, και αυτή η βάση είναι η βάση της δομής. Δείτε όμως ότι το 30!Ζ είναι η 31η δομή beta (ξεκινούν από 0) και το Ζ μεταθέτει τη διεύθυνση στη θέση του Ζ
Το Μήκος(beta) μας λέει πόσο μήκος έχει η δομή σε bytes
To beta("X") μας λέει την θέση του Χ ως το επιπλέον (offset) από την αρχή που είναι το 0.
Δημιουργούμε το b ως άθροισμα 30 δομών (που αφήνουμε μπροστά, άρα πάμε πίσω στην 31) και στο Χ. Μας δίνει το b ως το συνολικό επιπλέον (offset) που θα προστεθεί στη διεύθυνση της alfa, (αυτή είναι η αλφα(0), εκεί είναι το πρώτο byte στην μνήμη)
Γεμίζω το μικρό small με τιμές δίνοντας το επιπλέον με +8 και +16 για τα δυο επόμενα του Χ.

 Αυτή η έκφραση  κάνει casting, δηλαδή παίρνει το επιπλέον (offset) στο a, και τη δομή small  και επιστρέφει έναν διπλό Έκφρ(small, a Ως Διπλός)
θα δούμε παρακάτω το:
Επιστροφή alfa, b ! := 4234.234 Ως Διπλός
όπου καταχωρούμε στο επιπλέον (offset) b, έναν αριθμό ως διπλό.
Δηλαδή μπορούμε να γράψουμε και να διαβάσουμε με το τρόπο που θέλουμε, χωρίς να λογαριάζουμε τα προκαθορισμένα επιπλέον (offset)

Το  eval$(small) γυρνάει όλα τα byte του Small σαν αλφαριθμητικό, και η εντολή:
Επιστροφή alfa, 30 := eval$(small)
κάνει εκχώρηση της τιμής του small στο 31 στοιχείο του πίνακα. (δουλεύει με ζυγό αριθμό bytes)

άλλες συνδέσεις για τις διαρθρώσεις:
Γενικά, Ένωση (Union), Χρήση διάρθρωσης σε κλήση ρουτίνας σε C

Στα Ελληνικά

Δομή beta {
      KLM Ως Ακέραιος*20
      X Ως Διπλός
      Y Ως Διπλός
      Z Ως Διπλός
}
Διάρθρωση Κενή small Ως beta
Διάρθρωση Κενή alfa Ως beta*100
Επιστροφή alfa, 30!X :=2.00534, 30!Y:=1.123, 30!Z:=-3.34343
Τύπωσε Έκφρ(alfa, 30!X), Έκφρ(alfa, 30!Y), Έκφρ(alfa, 30!Z)
b=Μήκος(beta)*30+beta("X")
Τύπωσε b, alfa(30), beta("X")
a=Μήκος(beta)*0+beta("X")
Επιστροφή small, a! := 4234.234 Ως Διπλός, a+8! :=121.212 Ως Διπλός, a+16! :=-12.212 Ως Διπλός
Τύπωσε Έκφρ(small, a Ως Διπλός), Έκφρ(small, a+8 Ως Διπλός), Έκφρ(small, a+16 Ως Διπλός)
Επιστροφή alfa, b ! := 4234.234 Ως Διπλός
Τύπωσε Έκφρ(alfa, 30!X)
Επιστροφή alfa, 30 := eval$(small)
Τύπωσε Έκφρ(alfa, b Ως Διπλός), Έκφρ(alfa, b+8 Ως Διπλός), Έκφρ(alfa, b+16 Ως Διπλός)




Στα Αγγλικά (με χρήση του F5 κάνουμε μαζικές αλλαγές λέξεων στο κείμενο, στον ενσωματωμένο διορθωτή της Μ2000)

Structure beta {
      KLM As integer*20
      X As Double
      Y As Double
      Z As Double
}
Buffer Clear small As beta
Buffer Clear alfa As beta*100
Return alfa, 30!X :=2.00534, 30!Y:=1.123, 30!Z:=-3.34343
Print Eval(alfa, 30!X), Eval(alfa, 30!Y), Eval(alfa, 30!Z)
b=len(beta)*30+beta("X")
Print b, alfa(30), beta("X")
a=len(beta)*0+beta("X")
Return small, a! := 4234.234 As Double, a+8! :=121.212 As Double, a+16! :=-12.212 As Double
Print Eval(small, a As Double), Eval(small, a+8 As Double), Eval(small, a+16 As Double)
Return alfa, b ! := 4234.234 As Double
Print Eval(alfa, 30!X)
Return alfa, 30 := eval$(small)
Print Eval(alfa, b As Double), Eval(alfa, b+8 As Double), Eval(alfa, b+16 As Double)


Τετάρτη 8 Ιουνίου 2016

Νέα έκδοση 8.2

Συνήθως βλέπουμε αναθεωρήσεις αλλά όταν κάτι αλλάζει κάτι εσωτερικό, όπως τώρα, αλλάζει η έκδοση.
Αυτό που προστέθηκε είναι ο χειριστής σε εκφράσεις  <<  δείτε (1) και (2) καθώς επίσης έγινε αλλαγή στην Random ώστε να μπορούμε να παράγουμε σταθερές επαναλαμβανόμενες τυχαίες σειρές και υπάρχει και ένα επίπεδο για να διακόψουμε τη παραγωγή να ξεκινήσουμε μια άλλη και να επανέλθουμε στη προηγούμενη (έχει μόνο push-pop)

1. Χρήση σε έκφραση:
Αδειασε
\\ η εντολή Σειρά βάζει στο τέλος του σωρού
\\ έτσι έχουμε FIFO (διαβάζουμε πάντα από κορυφή)
\\ η εντολή Βάλε βάζει στην κορυφή (LIFO)
Σειρά 1,2,3,4
Σωρός  \\ εμφανίζει τα 1 2 3 4  (το 1 στην κορυφή)
Άδειασε
Σειρά 1<<2<<3<<4
Σωρός  \\ εμφανίζει τα 1 2 3 4  (το 1 στην κορυφή)
\\ ακριβώς το ίδιο γιατί το << κάνει την προηγούμενη τιμή...
\\ ..να μπει στο σωρό με Σειρά
Άδειασε
\\ ομοίως
Σειρά "Α"<<"Β"<<"Γ"<<"Δ"
Σωρός
\\ Υπάρχει διαφορά
Άδειασε
\\ αυτό γίνεται
Σειρά 1,"Α",2,"Β"
Δες οκ {
      \\ Αυτό δεν γίνεται
      \\ πρέπει να έχουμε ίδιο είδος
      Σειρά 1<<"Α"<<2<<"Β"
}
Αν όχι οκ Τότε Τύπωσε Λάθος$ \\ Συντακτικό λάθος
Σωρός


Αυτός ο χειριστής καθώς και η εντολή Try Stream ή Δες Ρεύμα. δημιουργούν προγραμματιστικά κολπάκια, όπως εδώ όπου:

Η a1 είναι μια λάμδα συνάρτηση (function factory) που δίνει έξοδο μια άλλη λάμδα που κρατάει μια τιμή στο χ και κάθε φορά που θα την καλέσουμε θα μειώνεται. Κανονικά μια συνάρτηση δέχεται ένα σωρό με τιμές για εισαγωγή, και τους διαβάζει με διάβασε ή read, αλλά αν υπάρχει ο χειριστής << τότε η Try Stram τρέχει το αριστερό μέρος του χειριστή με τρόπο ώστε να παίρνει την εξαγωγή του στο σωρό, είτε είναι ένα νούμερο είτε έχουν μπει με Data (πάντα στο τέλος του σωρού, έχει σημασία).
Φτιάχνουμε τρεις γεννήτριες την a, b και k με διαφορετική τιμή εκκίνησης.
Επίσης φτιάχνουμε μια ομάδα με μια συνάρτηση που και αυτή χρησιμοποιεί το "ρεύμα" αν υπάρχει.
Κάθε φορά που δέχεται ένα νούμερο για εισαγωγή αλλάζει μια ιδιότητα counter της ομάδας
Αξίζει να δει κανείς της εξαγωγή:
Θα πάρουμ 10+4+3 17 τεμάχια αλλά με τρόπο:
Πρώτα θα πάρουμε ένα από το καθένα, μετά το 3ο το k() δεν θα ξαναδώσει, μετά το 4ο το b() δεν θα ξαναδώσει, και μετά το 10ο το a() δεν θα ξαναδώσει και θα τερματίσει η εισαγωγή!
Αυτός είναι ο χειριστής Insert ή Εισαγωγή.

\\ generator
a1 =lambda -> {
      read x
      =lambda x ->{
            try stream
            if x>0 then = x
            x--
      }
}
\\ stream input

group alfa {
      counter
      function receive {
      {
            try stream
              if empty then exit
                     read X
                     .counter++
                     print x
                     loop
          }
           =.counter
      }
}
a=a1(10)
b=a1(4)
k=a1(3)

mm= alfa.receive() << a() << b() << k()
print mm \\ get 17 items



Στο δεύτερο παράδειγμα καθορίζουμε τη μέγιστη εισαγωγή. Το read ? many σημαίνει φτιάξε το many αν δεν υπάρχει και δώσει 0 αν δεν υπάρχει τιμή στο σωρό (δίνει δυνατότητα για προαιρετική (optional) εισαγωγή).

Clear
Function a {
      k=0
            {
            try stream
                  Read ? b
                  k+=b*30
                  =k
      }
}
Function Stream1 {
read ? many
k=0
Print "many=";many
if empty then many++
try stream
{
      if many=0 then exit
         read ? m
           k+=m
        many--
      if not empty then loop
      }
  =k
}
flush
Print a(), a(3), a(1,2,3,4,5), a(10)
k= stream1(100) << a(1,2)<<3<<4
Print 1*30+2+3+4
Print k
Print stream1(2) <<5<<6

στο παρακάτω δίνουμε 10Χ8 στοιχεία, το 3 στο f δεν κάνει τίποτα, αλλά ας υποθέσουμε ότι είναι αριθμός χειριστής αρχείου  για εξαγωγή

aa=lambda k=10 -> {
      if k<1 then exit
      data 1,2,3,4,5,6,7,8
      k--
}
flush
function holder {
      read f
      p=0
      Repeat {
           try stream
            if empty then exit
              read X : p+=X
      } Always
       =p
}

Print holder(3) << aa()


Παρόμοιο αλλά εδώ δίνουμε μια σειρά αριθμών ενώ ορίζουμε το μέγιστο

k=lambda->{read k1, k2 : for i=k1 to k2 { data i }}
sum=lambda->{
      p=0 : max=1
      Read ? max
        try stream
        {
            if empty then =0 : exit
            read ? x
            p+=x
            max--
            if max>0 then loop
      }
      =p
}
Print sum(100) << k(1,100) \\ 5050


Αυτό τώρα είναι πιο προχωρημένο! Ο χειριστής << είναι διπλή ενεργείας! Στο παρακάτω παράδειγμα η holder διαβάζει από το ρεύμα μόνο αν έχει το σωστό κλειδί.
Και στις δυο περιπτώσεις δίνουμε το κλειδί στη Holder, την πρώτη φορά το λάθος κλειδί, την δεύτερη το σωστό. Και στις δυο περιπτώσεις δοκιμάζει το ρεύμα.Πριν το κάνει όμως στέλνει στο σωρό το κλειδί, το οποίο διαβάζει η "γεννήτρια" και αν είναι το σωστό δίνει απάντηση αλλιώς τίποτα! Σημειώστε ότι θα δουλέψει ακόμα και αν δεν υπάρχει ρεύμα να πάρει τιμές.
Ο σωρός στις συναρτήσεις είναι πάντα φρέσκος και στο τέλος χάνεται, αλλά δεν συμβαίνει αυτό στην κλήση μετά το <<

aa=lambda k=10 -> {
try {
      read k$
      if k$ = "Key1" then {
            if k<1 then exit
            data 1,2,3,4,5,6,7,8
            k--
      }
      }
}
bb=lambda-> {
      data 1,2,3
}
flush
Group beta {
      counter
      function holder {
            read mkey$
            p=0
            Repeat {
                 push mkey$ \\ send back
                 try stream
                 if empty then exit
                 if not isnum then exit
                  read X : p+=X
                  .counter++
            } Always
             =p
      }
}
Print Beta.holder("Key1") << bb()
Print Beta.counter \\0
Print Beta.holder("Key1") << aa()
Print Beta.counter \\ 80 numbers

Beta.counter=0
Print Beta.holder("Key1")
Print Beta.counter \\ 0

2. Χρήση σε πίνακες
Εδώ αντί να βάλουμε = για σταθερή τιμή βάζουμε << που σημαίνει εκτέλεσε για κάθε στοιχείο (χειρίζεται τον πίνακα πάντα ως μονοδιάστατο)

c=lambda X=2 ->{=X: X+=3}
dim a(8,8)<<c()
for j=0 to 7 {
      for i=0 to 7 {
            print a(i, j),
      }
      print
}

3. Νέα Random με χρήση του Wichmann-Hill αλγόριθμου (κώδικας γραμμένος σε VB6 από το μέλος Merri στο VbForums, από πρώτη εγγραφή του μέλους anhn)
Αν γράψουμε το πρόγραμμα στο τμήμα Α τότε με Α σκέτο δείχνει την σειρά των 10 ζευγών τυχαίων. Με Α 1 ή άλλο μη μηδενικό νούμερο τότε έχουμε δέκα άλλους τυχαίους ενδιάμεσα, μετά τους πρώτους 5 και μετά συνεχίζουν οι επόμενοι 5 όπως έχουν και χωρίς τους ενδιάμεσους.
Τυχαίος() κάνει τυχαία αρχή (δεν γυρίζει νούμερο)
Τυχαίος(!133123) κάνει νέα αρχή από γνωστό νούμερο (γυρίζει το νούμερο αυτό) ενώ σώνει πρώτα τη θέση της γεννήτριας τυχαίων
Τυχαίος(!) κάνει pop την παλιά θέση της γεννήτριας
Τυχαίος(10)  από 0 έως 10
Τυχαίος(-5, 5) από -5 έως 5
Τυχαίος     δίνει έναν αριθμό από >=0 έως <1


read ? partial
K=random(!123)
for I=1 TO 5
      print random(1, 20), rnd
next I
if partial then {
      K=random(!112145)
      print K
      for I=1 TO 10
            print random(1, 20), rnd
      next I
      k=random(!)
}
for I=1 TO 5
      print random(1, 20), rnd
next I