Τρίτη 2 Φεβρουαρίου 2016

"Scope" ή αλλιώς εμβέλεια αναγνωριστικών!

Δείτε το παρακάτω πρόγραμμα σε C++. Στη C++ ότι είναι εκτός μπλοκ είναι γενική μεταβλητή. Αν θέλουμε να ξεχωρίσουμε κάτι πρέπει να το δηλώσουμε ή τοπικό (που σκιάζει το γενικό) ή με χρήση ονόματος χώρου.

// namespaces
#include <iostream>
using namespace std;

namespace foo
{
  int value() { return 5; }
}

namespace bar
{
  const double pi = 3.1416;
  double value() { return 2*pi; }
}

int main () {
  cout << foo::value() << '\n';
  cout << bar::value() << '\n';
  cout << bar::pi << '\n';
  return 0;
}


Στην Μ2000 έχουμε γενικές όταν αναθέτουμε τιμές σε επίπεδο γραμμής εντολών. Σε ένα τμήμα είμαστε ήδη σε μπλοκ, άρα όλα εκεί εξ ορισμού είναι τοπικά, εκτός αν τα δηλώσουμε γενικά (και μένουν γενικά (σκιάζοντας ότι προηγούμενο) για όσο χρόνο το τμήμα τρέχει (μετά διαγράφονται).
Για να αλλάξουμε γενική μεταβλητή πρέπει να δώσουμε αυτό <= γιατί το = δημιουργεί τοπική.

Ενώ στη C++ μπορούμε να ορίσουμε μεταβλητές τοπικές σε κάθε μπλοκ, στη Μ2000 μπορούμε να το κάνουμε όποτε θέλουμε με τη χρήση της εντολής τοπική (ή και τοπικές αν θέλουμε πολλές να δημιουργήσουμε) και αν υπάρχει ήδη μια τοπική τότε σκιάζεται. Για το λόγο αυτό τοπικές κάνουμε μόνο σε μπλοκ που κάνει ότι και η C++, δημιουργούν τις προϋποθέσεις για προσωρινές μεταβλητές. Αυτό λοιπόν γίνεται σε μπλοκ που κάνουμε με την Για, π.χ. Για Αυτό {  } και Για όνομα_ομάδας { } και Για Πίνακας_με_κλειστές_ομάδες(δείκτης)  {  }, καθώς και σε ρουτίνες.

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

Η C++ έλυσε το θέμα με τη χρήση των namespace. Φτιάχνεις δηλαδή ένα namespace και βάζεις μεταβλητές και συναρτήσεις μέσα! Η Μ2000 όμως έκανε τα namespace αντικείμενα!
Το παραπάνω πρόγραμμα σε M2000 (έχει επιπλέον μια γραμμή που δείχνει τη Pi ή Πι την σταθερά που γνωρίζει η Μ2000).
Η ομοιότητα είναι ότι τα Group (Ομάδα) μπορεί να έχουν και άλλα Group φωλιασμένα

Η διαφορά με τη Μ2000 είναι ότι τα group μπορούν να αντιγραφούν σε νέα Group...ή σε στοιχεία πίνακα ή να γυρίσουν ως αποτέλεσμα!
π.χ. Α=foo θα κάνει μια νέα συνάρτηση Α.value()
Σε ένα τμήμα έστω ΚΑΤΙ μπορούμε να περάσουμε με τιμή την foo
KATI foo
Η ομάδα foo θα βγει αντίγραφο σε μια κλειστή ομάδα στο σωρό τιμών του αντικείμενου εκτέλεσης της ΚΑΤΙ (που δημιουργείται όταν την καλέσουμε). Με μία Διάβασε FooInKati θα δημιουργηθεί η ομάδα FooInKati με τη συνάρτηση FooInKati,value()

Επίσης μπορούμε να τα περνάμε με αναφορά (ακόμα και τα γενικά). Π.χ, για ένα τμήμα ΑΛΦΑ το παρακάτω:
ΑΛΦΑ &bar
θα βάλει στη κορυφή στο σωρό τιμών της ΑΛΦΑ (στο αντικείμενο εκτέλεσης που θα δημιουργηθεί), το όνομα της bar (ισχνή αναφορά) και με μια:
Διάβασε &barInAlfa
θα έχουμε την ομάδα barInAlfa, την μεταβλητή barInAlfa.pi και την συνάρτηση barInAlfa.value()
Αν δηλώσουμε τοπική την Pi στο Group bar τότε στο πέρασμα με αναφορά δεν θα υπάρχει το barInAlfa.pi (ουσιαστικά τα αναγνωριστικά δείχνουν τις πραγματικές τιμές). Αν καλέσουμε την  barInAlfa.value()  π.χ. σε μια Τύπωσε τότε θα τρέξει σαν να είναι στην ομάδα bar και θα δει την pi παρόλο που δεν θα τη βλέπουμε στο ΑΛΦΑ,.


Η Μ2000 δεν χρειάζεται την Main για να τρέξει. Το παρακάτω το γράφουμε σε ένα τμήμα Α οπότε ήδη τρέχει...φτάνει στην κλήση της Main (απλά μπήκε εδώ για να φαίνεται...σαν την C++)

Μπορούμε να βγάλουμε τα global από τα group και να αφαιρέσουμε το Module main και την κλήση στη Main στο τέλος (και να αφήσουμε το μπλοκ δεν πειράζει)
Απλά σε ένα τμήμα δεν μπορεί να φανεί κάτι αν δεν είναι τοπικό ή δεν είναι γενικό. Αν υποθέσουμε ότι το παρακάτω είναι στο τμήμα Α, αν αφαιρέσουμε τα global στα group θα έχουμε τοπικές τις foo και bar. Τα αντικείμενα της Μ2000 έχουν όνομα χώρου και συμπληρώνουν το υπάρχον

\\ need to set groups to global to make global
\\ by default anything in a module is local

global group foo {
  function value { =5 }
}


global group bar {
      pi = 3.1416
      function value {=2*.pi} ' because a name has a . is a user id so is not the costant pi
}


Module main {
  Print foo.value()
  Print bar.value()
  Print bar.pi
  Print pi ' this is the M2000 costant pi
}
main


εδώ χωρίς Module main (μπήκε για ομορφιά)

group foo {
  function value { =5 }
}


group bar {
      pi = 3.1416
      function value {=2*.pi} ' because a name has a . is a user id so is not the costant pi
}


{
      Print foo.value()
      Print bar.value()
      Print bar.pi
      Print pi ' this is the M2000 costant pi
}


και εδώ με πέρασμα με αναφορά

group foo {
  function value { =5 }
}


group bar {
      pi = 3.1416
      function value {=2*.pi} ' because a name has a . is a user id so is not the costant pi
}


Module Other {
      Read &foo1, &bar1
      Print foo1.value()
      Print bar1.value()
      Print bar1.pi
      Print pi ' this is the M2000 costant pi
}
Other &foo, &bar


Πέρασμα με αντιγραφή, και επιστροφή με ένωση! H Push ή Βάλε, βάζει τιμές στο σωρό τιμών. Τα τμήματα καλούν άλλα τμήμα δίνοντας στο αντικείμενο εκτέλεσης του νέου τμήματος το σωρό τιμών του και βάζοντας στη κορυφή του τις τιμές που δίνουμε ως παραμέτρους. Στην επιστροφή λοιπόν θα υπάρχει στο σωρό του τμήματος ότι αφήσει το τμήμα που καλούμε! Για το λόγο αυτό τα τμήματα δεν προκαθορίζουν τι θα πάρουν αλλά οργανώνεται στο κώδικα το τι ακριβώς θα πάρουμε και το τι θα αφήσουμε! Οι συναρτήσεις ξεκινούν με δικό τους σωρό τιμών που περιέχει τις τιμές που περνάμε στη κλήση και στο πέρας της κλήσης τους ότι υπάρχει στο σωρό τους διαγράφεται μαζί με το αντικείμενο εκτέλεσης. Οι ρουτίνες είναι μέρη των τμημάτων και των συναρτήσεων και δεν έχουν δικό τους αντικείμενο εκτέλεσης, δεν έχουν δικό τους όνομα χώρου και δικό τους σωρό τιμών. Για το λόγο αυτό όταν δηλώνουμε σε ρουτίνες μεταβλητές για εισαγωγή ουσιαστικά δηλώνουμε νέες τοπικές με τις τιμές που δίνουμε.

Οι στατικές μεταβλητές στη Μ2000  είναι εκτός από το σύστημα ονομάτων χώρου και ανήκουν στα αντικείμενα εκτέλεσης...(το πατρικό κρατάει πακέτο των στατικών του κάθε "παιδιού" αντικείμενου εκτέλεσης).

group foo {
  checkme=1000
  function value { =5 }
}

group bar {
      pi = 3.1416
      function value {=2*.pi} ' because a name has a . is a user id so is not the costant pi
}


Module Other {
      Read foo1, bar1
      Print foo1.value()
      Print bar1.value()
      Print bar1.pi
      Print pi ' this is the M2000 costant pi
      foo1.checkme+=100
      bar1.pi=pi
      Push bar1, foo1
}
Other foo, bar
\\ union new foo with old one
Read foo, bar
Print foo.checkme, bar.pi





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

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

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