Μετατροπή Δομών Επανάληψης

Ξεκίνησε από evry, 12 Απρ 2011, 09:08:12 ΜΜ

« προηγούμενο - επόμενο »

Αθανάσιος Πέρδος

Θα συμφωνήσω με τον alkisg σε σχέση με το τι είναι συντακτικό και τι σημασιολογία.
Δεν ξέρω αν βοηθάει το επόμενο παράδειγμα σε C++. Συντακτικά οι εντολές είναι σωστές. Όμως η εκτέλεση δίνει ατέρμονα βρόχο.

#include <cstdlib>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
 
    for(int i=1; i<=5; i--)
    {
             cout<<i<<endl;
    }
   
    system("PAUSE");
    return EXIT_SUCCESS;
}

Αν γράφαμε όμως σε ΓΛΩΣΣΑ τότε η εντολή θα ήταν

Για ι από 1 μέχρι 5 με_βήμα -1
   Εμφάνισε ι
Τέλος_επανάληψης

Η οποία όμως εκτελείται καμία φορά.

Συντακτικά λοιπόν έχουμε δύο ίδιες εντολές οι οποίες όμως δεν παράγουν ίδια αποτελέσματα. 'Αρα διαφορετική σημασιολογία.


evry

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

Θα ήθελα όμως να μου απαντήσεις σε μια ερώτηση. Πως θα περιγράψεις συντακτικά. δηλαδή να φαίνεται στην γραμματική η απαγόρευση της αλλαγής του μετρητή μέσα στην for?
Δίνω ένα παράδειγμα για να καταλάβεις τι εννοώ

for (int i=1; i <= 100; i++) {     
     (* increment)( i )
}


η increment δεν είναι συνάρτηση που ορίζεται στο ίδιο αρχείο με το πρόγραμμα. Είναι δείκτης σε συνάρτηση που παίρνει σαν παράμετρο έναν ακέραιο αριθμό. Αυτό σημαίνει ότι θα ξέρεις αν μεταβάλλεται ο δείκτης i μόνο κατά την εκτέλεση (ούτε καν κατά τη σύνδεση), άρα δεν είναι δυνατόν να λες ότι ένα τέτοιο λάθος είναι συντακτικό και να το πιάνεις κατά την εκτέλεση.
What I cannot create I do not understand -- Richard Feynman
http://evripides.mysch.gr

evry

Νομίζω ότι κάνεις λάθος, τι θα πει συντακτικά ίδιες εντολές? :-\
μήπως εννοείς συντακτικά σωστές?
Παράθεση από: aperdos στις 14 Απρ 2011, 12:29:25 ΠΜ
Συντακτικά λοιπόν έχουμε δύο ίδιες εντολές οι οποίες όμως δεν παράγουν ίδια αποτελέσματα. 'Αρα διαφορετική σημασιολογία.
What I cannot create I do not understand -- Richard Feynman
http://evripides.mysch.gr

Αθανάσιος Πέρδος

Προφανώς έχεις βγάλει και την εφαρμοσμένη και ξέρεις καλύτερα από μένα τι συμβαίνει στη σχολή και στα θέματα των εξετάσεων. Σαφέστατα υπάρχουν πρωτότυπα θέματα αλλά υπάρχουν όμως και θέματα που είναι απλή εφαρμογή συγκεκριμένων αλγορίθμων. Δες και τις εξετάσεις στην Πάτρα. Δεν απαιτείται απομνημόνευση αλγορίθμων για να λυθούν έστω κάποια από τα θέματα των εξετάσεων (Αλγόριθμοι Prim, Krusκal, Dijkstra); Πίστεψε με το συγκεκριμένο τμήμα της Εφαρμοσμένης πληροφορικής για πολλούς και διάφορους λόγους δεν το υποτιμάω καθόλου. Άλλοι πήγαν να το υποτιμήσουν και τώρα το παίρνουν πίσω.

Όσο για το παράδειγμα της C ή της C++, δείξτο μας ολοκληρώμενο να το τρέξουμε να δούμε τι συμβαίνει. Εγώ από ότι ξέρω επιτρέπεται από το συντακτικό η αλλαγή της μεταβλητής μέσα στο σώμα της for. Αν λοιπόν γράψεις το προγραμματάκι και το τρέξεις θα το διαπιστώσεις και εσύ.  Μάλλον έχεις μπερδέψει την ΓΛΩΣΣΑ με τη C.

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

Άντε να δούμε τι άλλο θα μας πεις αύριο.
Καλυνύχτα.

pgrontas

Αυτό που δεν μπορώ να καταλάβω σε σχέση με το συντακτικό και την σημασιολογία είναι το εξής:
Η ΓΙΑ συντακτικά ορίζεται ως:
ΓΙΑ ...
<σωμα εντολών>
ΤΕΛΟΣ_ΕΠΑΝΑΛΗΨΗΣ

όπου το σώμα εντολών είναι οποιαδήποτε εντολή μπορεί να επιτραπεί και στο κυρίως πρόγραμμα και μέσα σε ένα αν κτλ.
Πώς μπορείς να να απαγορέψεις εκεί την αύξηση του μετρητή;
Ακόμα και αυτό με το r-value που λέει ο Άλκης δεν το καταλαβαίνω: Πώς θα το ορίσεις ως σταθερά όταν αλλάζει συνεχώς τιμές μέσα στο βρόχο;
Φυσικά δεν έχω υλοποιήσει μεταγλωττιστή, οπότε δεν μπορώ να είμαι 100% σίγουρος.

Παράθεση από: aperdos στις 14 Απρ 2011, 02:07:04 ΠΜ
Συντακτικά ίδιες θα πει ότι και στις δύο η μεταβλητή ξεκινάει από την ίδια τιμή, μπορεί να φτάσει μέχρι την ίδια τιμή και αλλάζει κάθε φορά κατά την ίδια τιμή.
Αυτό νομίζω δεν έχει καμία σχέση με την σύνταξη.
Programs must be written for people to read, and only incidentally for machines to execute - Harold Abelson

alkisg

Κώδικας: C
#include <stdio.h>

int main(void)
{
    int i;

    for (i=0; i<10; i++)
    {
        const int hidden=i;
        const int i=hidden;
        // Πλέον εντός της for το i είναι υποχρεωτικά σταθερό

        // Σε αυτό χτυπάει syntax error, αν το βγάλεις παίζει μια χαρά
        i=i+1;
        printf("%d\n", i);
    }

    return 0;
}


Αποτέλεσμα της μεταγλώττισης:
Παράθεση από: gcc syntax.c
syntax.c: In function 'main':
syntax.c:14: error: assignment of read-only variable 'i'

Με το παραπάνω παράδειγμα θέλω να πω ότι δεν είναι δύσκολο το i να αλλάξει από "μεταβλητή" σε "σταθερά" εντός ενός μπλοκ. Αρκεί το συντακτικό της αντίστοιχης γλώσσας να έκανε ό,τι κάνουν οι δύο εντολές με το "hidden" παραπάνω. Είναι καθαρά θέμα ορισμού.

Αντίστοιχα, η επιλογή Να μην επιτρέπονται οι εντολές ΓΡΑΨΕ και ΔΙΑΒΑΣΕ στο εσωτερικό συναρτήσεων του Διερμηνευτή, κάνει το συντακτικό της ΓΛΩΣΣΑΣ να τις απαγορεύει κι ας έχουν οι συναρτήσεις παρόμοιο BNF συμβολισμό με τις διαδικασίες.

odysseas

Προσωπικά έχω την αίσθηση οτι ο διαχωρισμός μεταξύ συντακτικού και σημασιολογίας είναι πολύ σαφής. Το συντακτικό το ορίζεις με μια γραμματική, υπάρχουν πολύ καλά ορισμένοι κανόνες για το πως μπορείς να το κάνεις αυτό. Ένα παράδειγμα περιγραφής γραμματικής είναι η BNF, που αναφέρθηκε προηγουμένως. Η γραμματική περιγράφει ποια προγράμματα είναι συντακτικώς αποδεκτά και τίποτα παραπάνω. Μπορεί κανείς να γράψει μια γραμματική που να περιγράφει προγράμματα στα οποία δε γίνεται να αυξήσεις τον μετρητή; Δε μου φαίνεται και τόσο εύκολο...

Να το θέσω αλλιώς: υπάρχουν πολλά εργαλεία για κατασκευή μεταγλωττιστών (στις μέρες μου ήταν στα φόρτε τους το yacc και το bison). Σε αυτά περιγράφεις τους κανόνες τις γραμματικής σου και σε κάθε κανόνα κολλάς το τι πρέπει να γίνει οταν η είσοδος "ταιριάξει" με αυτόν τον κανόνα. Οι κανόνες της γραμματικής είναι το συντακτικό. Αυτά που κολλάς δίπλα είναι η σημασιολογία. Οπότε ρωτάω τώρα: Άλκη, το τέχνασμα που έκανες επάνω με το "μασκάρισμα" της i μπορείς να το περιγράψεις ως κανόνα της γραμματικής ή θα το κόλλαγες πάνω στον κανόνα που αναγνωρίζει μια ΓΙΑ; Εγώ νομίζω το δεύτερο.

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

evry

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

Επίσης δίνω και 2 παραδείγματα για να καταλάβεις τι εννοώ ως συντακτικό και σημασιολογικό γιατί μου φαίνεται ότι εσύ το βλέπεις το θέμα από άλλη σκοπιά.
1. Το type checking δεν θεωρείται συντακτικό αλλά σημασιολογικό. Υποθέτω ότι εσύ το θεωρείς συντακτικό έτσι? Δηλαδή το παρακάτω το θεωρείς συντακτικό λάθος

ΑΚΕΡΑΙΕΣ: Α, Β, Γ

Γ <- Α/Β

2. Όταν δηλώνεις μια  μεταβλητή και την χρησιμοποιείς χωρίς να την αρχικοποιήσεις. Αυτό το πιάνεις στο compile-time αλλά δεν είναι συντακτικό λάθος.Δεν παραβιάζει τους κανόνες της γραμματικής. Είναι σημασιολογικό.

Τα παραπάνω που αναφέρω κάποιοι τα αναφέρουν σαν static semantics διότι ναι μεν είναι semantics αλλά μπορείς να τα πιάσεις σε compile-time

Δες και εδώ για να καταλάβεις το σκεπτικό μου πως ορίζει syntax και semantics
http://en.wikipedia.org/wiki/Programming_language
http://en.wikipedia.org/wiki/Syntax_%28programming_languages%29#Syntax_versus_semantics

Για την ακρίβεια εδώ
http://en.wikipedia.org/wiki/For_loop#Loop_variable_scope_and_semantics
λέει

in some languages (not C or C++) the loop variable is immutable within the scope of the loop body, with any attempt to modify its value being regarded as a semantic error.

Τα ανέφερα γιατί έχω την εντύπωση ότι βλέπουμε το πρόβλημα από άλλη σκοπιά
(χωρίς να σημαίνει ότι επειδή το λέει η wikipedia είναι απαραίτητα και σωστό έτσι ;))

edit Φυσικά με καλύπτουν αυτά που λέει ο Οδυσσέας αλλά όταν τα είδα είχα ήδη γράψει το δικό μου μήνυμα ::)
What I cannot create I do not understand -- Richard Feynman
http://evripides.mysch.gr

alkisg

Πήγα να απαντήσω πιο πριν αλλά έπαιρνα proxy errors, και τώρα μετά τα τελευταία μηνύματα μου φαίνεται πια ότι είμαι εκτός θέματος... :D
αλλά τέλος πάντων αφού το έγραψα, το παραθέτω και ας το κλείσουμε εδώ.

Παράθεση από: odysseas στις 14 Απρ 2011, 10:58:15 ΠΜ
Προσωπικά έχω την αίσθηση οτι ο διαχωρισμός μεταξύ συντακτικού και σημασιολογίας είναι πολύ σαφής.

Για τον συντακτικό έλεγχο συμφωνώ, ο ορισμός του είναι εντελώς ξεκάθαρος: όποιο πρόγραμμα περνάει από συντακτικό έλεγχο είναι εκτελεστέο. Τελεία, σαφέστατο. Το τι θα γίνει κατά το χρόνο εκτέλεσης δεν μας ενδιαφέρει καθόλου στο συντακτικό έλεγχο.
Για τη σημασιολογία δεν συμφωνώ και τόσο. Άλλοτε μπαίνει στα χωράφια του συντακτικού ελέγχου, άλλοτε στο χρόνο εκτέλεσης, άλλοτε παίρνει τη μορφή αλγεβρικής μελέτης, άλλοτε όπως τώρα αφορά φιλολογικές συζητήσεις...  ;D
Το BNF είναι μια μορφή αναπαράστασης γραμματικής, δεν είναι όμως υποχρεωτικό. Ούτε το Delphi ούτε η FreePascal ούτε ο Διερμηνευτής χρησιμοποιούν compiler generators τύπου bison/yacc, αλλά υλοποιούν το συντακτικό έλεγχο με recursive descent parsers όπου το "κολλάω κάτι από δίπλα" όπως το είπες, είναι μέρος της γραμματικής. Μάλιστα απ' όσο ξέρω το bounty που είχε βγει για να γραφεί η γραμματική της FreePascal σε BNF δεν το ανέλαβε κανένας λόγω δυσκολίας.


Παράθεση από: evry στις 14 Απρ 2011, 11:26:24 ΠΜ
Στο παράδειγμα που έδωσα παραπάνω με τον δείκτη σε συνάρτηση πως μπορεί να γίνει αυτό?

Στη συνάρτηση αυτή περνάς το i, και όχι τη διεύθυνσή του. Άρα η συνάρτηση δεν μπορεί να μεταβάλλει το μετρητή.
Εάν εσύ το προχωρούσες και έλεγες "οκ θα περάσω τη διεύθυνση του i", τότε εγώ θα απαντούσα "αν το i δεν είναι l-value, τότε ΔΕΝ έχει διεύθυνση και δεν μπορείς να την πάρεις για να την περάσεις, είναι συντακτικό λάθος".


Παράθεση από: evry στις 14 Απρ 2011, 11:26:24 ΠΜ
2. Όταν δηλώνεις μια  μεταβλητή και την χρησιμοποιείς χωρίς να την αρχικοποιήσεις. Αυτό το πιάνεις στο compile-time αλλά δεν είναι συντακτικό λάθος. Δεν παραβιάζει τους κανόνες της γραμματικής. Είναι σημασιολογικό.

Συμφωνώ απόλυτα ότι δεν παραβιάζει τη γραμματική και ότι δεν είναι συντακτικό λάθος. Διαφωνώ για το compile time, δεν πιάνεται πάντα εκεί, γι' αυτό και συνήθως είναι warning και όχι error (και άρα δημιουργείται εκτελέσιμο). Συμφωνώ ότι θα μπορούσε υπό προϋποθέσεις να είναι σημασιολογικό (γιατί μπορεί να το έχω αρχικοποιήσει με κάποιον άλλον μυστήριο τρόπο και να μου βγαίνει warning χωρίς όμως να υπάρχει κανένα απολύτως λάθος), αλλά θεωρώ ότι κυρίως είναι λάθος χρόνου εκτέλεσης, αφού εκεί είναι που μπορείς να το πιάσεις με σιγουριά (σε managed γλώσσες). Επίσης, όταν είναι σημασιολογικό λάθος, είναι συγχρόνως και λογικό λάθος.


Παράθεση από: evry στις 14 Απρ 2011, 11:26:24 ΠΜ
Για την ακρίβεια εδώ
http://en.wikipedia.org/wiki/For_loop#Loop_variable_scope_and_semantics
λέει

in some languages (not C or C++) the loop variable is immutable within the scope of the loop body, with any attempt to modify its value being regarded as a semantic error.

Δεν διαφωνώ ότι θεωρείται και σημασιολογικό σφάλμα.
Αυτό που λέω είναι ότι από τη στιγμή που κάποιον έλεγχο τον βάζεις ως μέρος του συντακτικού ελέγχου, τότε είναι συντακτικό σφάλμα. Π.χ. η απαγόρευση της μεταβολής του μετρητή εντός της ΓΙΑ στη ΓΛΩΣΣΑ θα μπορούσε άνετα να είναι μέρος του συντακτικού ελέγχου.
Αν κάποιον έλεγχο τον βάλεις στο χρόνο εκτέλεσης, τότε είναι σφάλμα χρόνου εκτέλεσης. Π.χ. ο έλεγχος μεταβλητή <- μεταβλητή_με_ακέραια_τιμή / μεταβλητή_με_τιμή_χαρακτήρα" στην ψευδογλώσσα θα μπορούσε άνετα να είχε οριστεί ως dynamic type checking που γίνεται κατά το χρόνο εκτέλεσης, ενώ το ίδιο σφάλμα στη ΓΛΩΣΣΑ θα ήταν συντακτικό αφού έχει static type checking.
Και σημασιολογικό θα το έλεγα όταν ήθελα να αναφερθώ σε αυτό το σφάλμα ανεξάρτητα από το σε ποια φάση ελέγχεται, είτε κατά το συντακτικό έλεγχο είτε κατά το χρόνο εκτέλεσης.


ΟΚ, αυτά, δε νομίζω ότι έχει νόημα πια. :)

evry

Παράθεση από: alkisg στις 14 Απρ 2011, 06:53:38 ΜΜ
Στη συνάρτηση αυτή περνάς το i, και όχι τη διεύθυνσή του. Άρα η συνάρτηση δεν μπορεί να μεταβάλλει το μετρητή.
Εάν εσύ το προχωρούσες και έλεγες "οκ θα περάσω τη διεύθυνση του i", τότε εγώ θα απαντούσα "αν το i δεν είναι l-value, τότε ΔΕΝ έχει διεύθυνση και δεν μπορείς να την πάρεις για να την περάσεις, είναι συντακτικό λάθος".

καλά ρε που την παρατήρησες αυτή τη λεπτομέρεια, τελικά μάλλον έπρεπε να το τρέξω :D
What I cannot create I do not understand -- Richard Feynman
http://evripides.mysch.gr

evry

εεε, βασικά πράγματι είσαι εκτός θέματος, απάντησες σε λάθος thread, ;D
το σωστό thread είναι εδώ
https://alkisg.mysch.gr/steki/index.php?topic=3831.msg40319#msg40319
Παράθεση από: alkisg στις 14 Απρ 2011, 06:53:38 ΜΜ
και τώρα μετά τα τελευταία μηνύματα μου φαίνεται πια ότι είμαι εκτός θέματος... :D
οπότε σε εγκαλώ στην τάξη :police:
What I cannot create I do not understand -- Richard Feynman
http://evripides.mysch.gr


Αθανάσιος Πέρδος

#include <stdio.h>
#include "t2.h"


int main()
{
    int i;
   void (*increament)(int &);
   increament = &my_int_func;

   
   for (i=1; i<=5; i++)
   {
      (*increament)( i );
      printf( "%d\n", i );
   }
    return 0;
}

ο κώδικας του header είναι:

#ifndef T2_H
#define T2_H

void my_int_func(int &x)
{
    x=x+2;
};

#endif

Ο παραπάνω κώδικας για να βοηθήσω την τελευταία συζήτηση.
Θα ήθελα όμως να ρωτήσω κάτι σχετικά με το εξής πρόβλημα.

#include<iostream.h>

int main()
{
   int a, b, mo;
   
   a=2;
   b=5;

   mo = (a + b)/2;
   
   cout<<mo<<endl;
   return 0;
}

Αν εκτελεστεί βγάζει 3. Συντακτικό λάθος δεν υπάρχει. Με βάση το σχολικό βιβλίο ούτε λογικό αφού η υλοποίηση του αλγόριθμου είναι σωστή.  Είναι λοιπόν σημασιολογικό; Το θέμα προέκυψε όταν έδειχνα τα στάδια της μεταγλώτισης στους μαθητές και εκ παραδρομής είχα δηλώσει τη mo ως int. Πως θα έπρεπε να εξηγηθεί; Θεωρούμε τα σημασιολογικά ως λογικά και μιλάμε για παράλειψη του σχολικού;

Τώρα το ίδιο θέμα φυσικά ο διερμηνευτής το  αντιμετωπίζει ως συντακτικό λάθος.
 

Kalli

Καλημέρα σας!
Θα ήθελα να ρωτήσω κάτι για μετατροπή Οσο σε Μέχρις_ότου.
Είναι σωστή η μετατροπή της παρακάτω ΟΣΟ σε  Μέχρις_ότου;;;

ΔΙΑΒΑΣΕ α
ΌΣΟ α<>0 επανάλαβε
   ΕΜΦΑΝΙΣΕ α
   ΔΙΑΒΑΣΕ α
ΤΕΛΟΣ_ΕΠΑΝΑΛΗΨΗΣ
             ||
             \/
ΑΡΧΗ_ΕΠΑΝΑΛΗΨΗΣ
   ΔΙΑΒΑΣΕ α
   ΑΝ α<>0 ΤΟΤΕ
       ΕΜΦΑΝΙΣΕ α
       ΔΙΑΒΑΣΕ α
   ΤΕΛΟΣ_ΑΝ
ΜΕΧΡΙΣ_ΟΤΟΥ α=0

P.Tsiotakis

όχι δεν είναι σωστή
ουσιαστικά υπάρχουν δυο διαδοχικά διάβασε αν δίνονται μη μηδενικές τιμές και δεν εμφανίζονται όλα όπως πρέπει

Δε χρειάζεσαι δυο Διάβασε στη Μέχρις_ότου
ΑΡΧΗ_ΕΠΑΝΑΛΗΨΗΣ
   ΔΙΑΒΑΣΕ α
   ΑΝ α<>0 ΤΟΤΕ
       ΕΜΦΑΝΙΣΕ α
       ΔΙΑΒΑΣΕ α
   ΤΕΛΟΣ_ΑΝ
ΜΕΧΡΙΣ_ΟΤΟΥ α=0