Γιατι υπάρχουν οι συναρτήσεις;;;;;;

Ξεκίνησε από agelos, 27 Μαρ 2007, 08:43:42 ΠΜ

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

agelos

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

agelos

Το βρήκα γιατί.Διότι στη συνάρτηση,αν περάσουμε μεταβλητές του κυρίως προγράμματος και πρέπει να αλλαχθεί η τιμή τους μέσα στο υποπρόγραμμα προκειμένου να υπολογιστεί το αποτέλεσμα που ψάχνουμε,δεν θα επηρεαστούν όταν θα έχουμε επιστρέψει στο κυρίως πρόγραμμα.Αντίθετα στη διαδικασία θα επιστραφούν αλλαγμένες θέλουμε δεν θέλουμε.Και αυτός φαντάζομαι είναι άλλος ένας λόγος για τον οποίο στις σοβαρές γλώσσες προγραμματισμού χρησιμοποιούμε τους pointers.Διότι πχ στη c++ θα περάσεις σε μία συνάρτηση τους pointers των μεταβλητών που θέλεις να αλλαχθούν.Επομένως δεν υπάρχει κίνδυνος να αλλάξεις και τις τιμές μεταβλητών που δεν θα ήθελες να αλλαχθούν.Αν κάποιος έχει κάποια άλλη άποψη σε αυτό το θέμα θα ήθελα πολύ να το συζητήσουμε.

alkisg

Οι συναρτήσεις υπάρχουν για τον ίδιο λόγο που υπάρχουν οι δομές ΓΙΑ και ΑΡΧΗ_ΕΠΑΝΑΛΗΨΗΣ.
Αφού η ΟΣΟ είναι η πιο ισχυρή από όλες τις δομές , τι τις θέλουμε; Απάντηση: για ευκολία.

Φαντάσου να ήθελες να γράψεις την παρακάτω έκφραση και οι Τ_Ρ, Α_Τ, ΛΟΓ, Α_Μ να ήταν διαδικασίες:
Κώδικας: ΓΛΩΣΣΑ
χ <- Τ_Ρ(ι) + Α_Τ(2*κ) + ΛΟΓ(3*λ) + Α_Μ(4*μ)


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

Γι' αυτό που λες, ότι οι τιμές της συνάρτησης δεν επηρεάζονται κατά την επιστροφή, ισχύει μεν αλλά δεν είναι αυτός ο λόγος. Μπορώ να καλέσω μια διαδικασία έτσι:
Κώδικας: ΓΛΩΣΣΑ
ΚΑΛΕΣΕ Αντιμετάθεσε(χ+1, (ψ))


και φυσικά δεν πρόκειται να αντιμεταθέσει τα χ και ψ, αφού δεν του πέρασα τα χ και ψ αλλά εκφράσεις που δεν αντιστοιχούν σε κάποια διεύθυνση μνήμης.

Τέλος, αν ήθελα σε μια διαδικασία να μη μεταβάλλεται κάποια μεταβλητή, θα μπορούσα (και θα ήταν πιο κατανοητό) να χρησιμοποιήσω μια προσωρινή μεταβλητή:
Κώδικας: ΓΛΩΣΣΑ
ΔΙΑΔΙΚΑΣΙΑ ΜηνΠειράζειςΤοΑ(α, β)
ΜΕΤΑΒΛΗΤΕΣ
  ΑΚΕΡΑΙΕΣ: α, β, προσωρινή
ΑΡΧΗ
  προσωρινή <- α
!και από εδώ και κάτω μη χρησιμοποιείς το α αλλά την προσωρινή

evry


Αυτό ισχύει κυρίως στη C, στη C++ αρκεί να χρησιμοποιήσεις τον τελεστή & .

Παράθεση από: agelos στις 27 Μαρ 2007, 09:26:24 ΠΜ
Διότι πχ στη c++ θα περάσεις σε μία συνάρτηση τους pointers των μεταβλητών που θέλεις να αλλαχθούν.Επομένως δεν υπάρχει κίνδυνος να αλλάξεις και τις τιμές μεταβλητών που δεν θα ήθελες να αλλαχθούν.Αν κάποιος έχει κάποια άλλη άποψη σε αυτό το θέμα θα ήθελα πολύ να το συζητήσουμε.
What I cannot create I do not understand -- Richard Feynman
http://evripides.mysch.gr

agelos

#4
Φίλε Άλκη.Κατ αρχάς εκτιμάω πολύ την δουλειά που έχετε κάνει με τον compiler της ΓΛΩΣΣΑΣ.Είναι πραγματικά πολύ καλή δουλειά.Θα διαφωνήσω μαζί σου στη χρήση της ΓΙΑ και της ΑΡΧΗΣ_ΕΠΑΝΑΛΗΨΗΣ επειδή έχουν διαφορές με την την ΟΣΟ.Διότι αν θέλω ένας βρόχος επανάληψης να εκτελεστεί σίγουρα μια φορά και δεν ξέρω τι δεδομένα εισάγει ο χρήστης αρχικά τότε πρέπει να χρησιμοποιήσω την ΑΡΧΗ_ΕΠΑΝΑΛΗΨΗΣ και όχι την ΟΣΟ.Επίσης η ΓΙΑ δεν χρειάζεται εντολή αρχικοποίησης ούτε μεταβολής της μεταβλητής που ελέγχεται πράγμα που κάνει το πρόγραμμά μου ποιό σύντομο και κατανοητό.ΠΧ αν είχα 10 βρόχους επανάληψης θα έπερεπε να γράψω 20 εντολές παραπάνω στο πρόγραμμά μου προκειμένου να το κάνω με ΟΣΟ.ʼρα το πρόγραμμά μου θα γινόταν ποιό δύσκολο στη κατανόηση και θα υπήρχε μεγαλύτερος κίνδυνος λάθους από πλευράς προγραμματιστή.Η κατανόηση του προγράμματος από τρίτους είναι πολύ σοβαρός λόγος όταν φτιάχνεις ένα μέρος κώδικα και όχι όλο το πρόγραμμα.Το ίδιο σοβαρός είναι και ο λόγος της αποφυγής λαθών την ώρα του προγραμματισμού.Αναλογίσου πόσες ώρες μπορεί να χρειάστηκες κάποτε για να βρείς ότι σε ένα πρόγραμμα 1000 γραμμών πχ. που είχες φτιάξει και δεν έτρεχε το λάθος μπορεί να ήταν ένα κόμμα.Θα διαφωνήσω ακόμη στο θέμα της προσωρινής μεταβλητής στο θέμα της διαδικασίας.Διότι όπως γνωρίζεις κάθε έξτρα μεταβλητή έχει κόστος σε μνήμη.Και αν πχ ήθελα να περάσω στη διαδικασία 20 πραγματικές μεταβλητές οι οποίες θα έπρεπε να αλλαχθούν μέσα στη διαδικασία άλλα όχι στο πρόγραμμα θα ήθελα 20 έξτρα προσωρινές μεταβλητές.Αναλογίσου λοιπόν το κόστος σε μνήμη.ʼρα αυτός είναι ένας επίσης πολύ σοβαρός λόγος για να χρησιμοποιήσω pointers ή συνάρτηση στη προκειμένη περίπτωση.
Τέλος συμφωνώ σε αυτό που λές ότι αν ήθελα να γράψω χ <- Τ_Ρ(ι) + Α_Τ(2*κ) + ΛΟΓ(3*λ) + Α_Μ(4*μ) και αυτά ήταν διαδικασίες θα υπήρχε πρόβλημα.Είναι και αυτός ένας καλός λόγος για να χρησιμοποιήσω συνάρτηση και από πλευράς κατανόησης και από πλευράς μνήμης.
Σε ευχαριστώ για τη βοήθεια.

alkisg

Άγγελε σ' ευχαριστώ για τα καλά σου λόγια.

Δυο σχόλια σ' αυτά που έγραψες:
Παράθεση από: agelos στις 28 Μαρ 2007, 10:00:44 ΠΜ
Θα διαφωνήσω μαζί σου στη χρήση της ΓΙΑ και της ΑΡΧΗΣ_ΕΠΑΝΑΛΗΨΗΣ επειδή έχουν διαφορές με την την ΟΣΟ.Διότι αν θέλω ένας βρόχος επανάληψης να εκτελεστεί σίγουρα μια φορά και δεν ξέρω τι δεδομένα εισάγει ο χρήστης αρχικά τότε πρέπει να χρησιμοποιήσω την ΑΡΧΗ_ΕΠΑΝΑΛΗΨΗΣ και όχι την ΟΣΟ.Επίσης η ΓΙΑ δεν χρειάζεται εντολή αρχικοποίησης ούτε μεταβολής της μεταβλητής που ελέγχεται πράγμα που κάνει το πρόγραμμά μου ποιό σύντομο και κατανοητό.

Αυτό εννοούσα "για ευκολία". Είναι δυνατόν να φτιαχτεί ένα φόρουμ σαν το Στέκι σε γλώσσα C (ή assembly!), και μάλιστα θα είναι και πιο γρήγορο. Ο λόγος που δεν προτιμάται η C αλλά η PHP είναι επειδή η PHP είναι πιο κατάλληλη για το χειρισμό text κειμένου, ότι είναι interpreted και άρα κάνει πιο εύκολες τις διορθώσεις και πολλά άλλα.
Για ακριβώς τους λόγους που ανέφερες προτιμούμε τη ΓΙΑ ή την ΑΡΧΗ_ΕΠΑΝΑΛΗΨΗΣ στις περιπτώσεις που είπες. Όχι όμως ότι δε θα μπορούσε να γίνει η ίδια δουλειά με την ΟΣΟ. Απλά το είπα εν συντομία χωρίς να επεκταθώ: για ευκολία. Το ίδιο εννοώ και για τις συναρτήσεις. Ο,τιδήποτε γίνεται με συνάρτηση μπορεί να γίνει και με διαδικασία. Διαλέγουμε συνάρτηση επειδή μας βολεύει καλύτερα (και συντακτικά, και για debugging και για όλα όσα είπες).

Παράθεση από: agelos στις 28 Μαρ 2007, 10:00:44 ΠΜ
Θα διαφωνήσω ακόμη στο θέμα της προσωρινής μεταβλητής στο θέμα της διαδικασίας.Διότι όπως γνωρίζεις κάθε έξτρα μεταβλητή έχει κόστος σε μνήμη.Και αν πχ ήθελα να περάσω στη διαδικασία 20 πραγματικές μεταβλητές οι οποίες θα έπρεπε να αλλαχθούν μέσα στη διαδικασία άλλα όχι στο πρόγραμμα θα ήθελα 20 έξτρα προσωρινές μεταβλητές.Αναλογίσου λοιπόν το κόστος σε μνήμη.
Το πρόβλημα: θέλω να περάσω μια μεταβλητή σε κάποιο υποπρόγραμμα και να μην αλλαχτεί η τιμή της όταν την πειράζω.
1η λύση: χρησιμοποιώ την προσωρινή μεταβλητή που έλεγα. ʼρα όπως είπες χρειάζομαι παραπάνω μνήμη, sizeof(μεταβλητή).
2η λύση: χρησιμοποιώ συνάρτηση. Εσωτερικά η συνάρτηση θα φτιάξει μια προσωρινή μεταβλητή στη στοίβα (=τυπική παράμετρος), και θα την αρχικοποιήσει με τα περιεχόμενα της πραγματικής παραμέτρου. ʼρα χρειάζομαι πάλι sizeof(μεταβλητή).
3η λύση: χρησιμοποιώ προσωρινή μεταβλητή στο κυρίως πρόγραμμα ακριβώς πριν την ΚΑΛΕΣΕ, και βάζω σαν παράμετρο την προσωρινή μεταβλητή. Πάλι sizeof(μεταβλητή).

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

evry


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

void   Διαδικασία( const int& a )    και με pointers Μπορείς να γράψεις     void   Διαδικασία( const int const * a )


αν τα θυμάμαι καλά.

Παράθεση από: alkisg στις 28 Μαρ 2007, 11:42:15 ΠΜ
Το πρόβλημα: θέλω να περάσω μια μεταβλητή σε κάποιο υποπρόγραμμα και να μην αλλαχτεί η τιμή της όταν την πειράζω.
1η λύση: χρησιμοποιώ την προσωρινή μεταβλητή που έλεγα. Άρα όπως είπες χρειάζομαι παραπάνω μνήμη, sizeof(μεταβλητή).
2η λύση: χρησιμοποιώ συνάρτηση. Εσωτερικά η συνάρτηση θα φτιάξει μια προσωρινή μεταβλητή στη στοίβα (=τυπική παράμετρος), και θα την αρχικοποιήσει με τα περιεχόμενα της πραγματικής παραμέτρου. ʼρα χρειάζομαι πάλι sizeof(μεταβλητή).
3η λύση: χρησιμοποιώ προσωρινή μεταβλητή στο κυρίως πρόγραμμα ακριβώς πριν την ΚΑΛΕΣΕ, και βάζω σαν παράμετρο την προσωρινή μεταβλητή. Πάλι sizeof(μεταβλητή).
What I cannot create I do not understand -- Richard Feynman
http://evripides.mysch.gr

alkisg

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

Επίσης, όταν δηλώνεις const έναν ακέραιο, πάλι αυτός μπαίνει στο stack. Δε γλυτώνεις μνήμη. Όταν δηλώνεις const έναν πίνακα που τον πέρασες με pointer γλυτώνεις τη μνήμη του πίνακα. Αυτό όμως δεν έχει σχέση με το const, γλυτώνεις τη μνήμη επειδή χρησιμοποιείς pointer (θα τη γλύτωνες και χωρίς const). Εξάλλου με το const στον πίνακα πάλι δεν αντιστοιχεί στο παραπάνω πρόβλημα, όπου θέλουμε να αλλάζουμε τη μεταβλητή στο υποπρόγραμμα...

Βέβαια στη ΓΛΩΣΣΑ δε γίνεται να γλυτωθεί μνήμη είτε αλλάζει η μεταβλητή είτε όχι, αφού δεν υπάρχουν pointers και ο μηχανισμός στις διαδικασίες είναι copy by value result πως τον λένε, όπου δημιουργούνται τοπικά αντίγραφα των μεταβλητών και δεν είναι by reference.

agelos

Βασικά ο λόγος για τον οποίο έθεσα το θέμα είναι ο εξής.Έρχεται ένας μαθητής μου και ρωτάει.Μα αφού οι διαδικασίες κάνουν όλα όσα κάνει το κυρίως πρόγραμμα και άρα και ότι κάνουν οι συναρτήσεις γιατί να υπάρχουν οι συναρτήσεις;Το προγραμματιστική ευκολία δεν μπορούν να το καταλάβουν τα παιδιά διότι δεν πρόκειται στα πλαίσια του μαθήματος να κάνουν κανένα μεγάλο πρόγραμμα για να δούν στην πράξη τι σημαίνει προγραμματιστική ευκολία.Οπότε τις θεωρούν περιττές και ανούσιες και απλά αναγκάζονται να τις μαθαίνουν παπαγαλία.Επίσης αγχώνονται γιατί σου λέει εγώ τι να κάνω στις πανελλήνιες αν δεν μου λέει;Διαδικασία ή συνάρτηση;Σε όλα τα παρόμοια ερωτήματά τους πάντα βρίσκω κάποια χρησιμότητα την οποία τους αναφέρω.Στις συναρτήσεις όχι.Και εν τέλει εγώ πάντα σε C++ προγραμμάτιζα και γλώσσες που δεν χρησιμοποιούν pointers ναι μεν τις θεωρώ ποιό εύκολες αλλά πολύ ποιό δυσκίνητες.Αλλά δεν είναι αυτό το θέμα.Το θέμα είναι ο μαθητής.Δηλαδή.Το να του λές ότι σε φωρτώνω με έξτρα ύλη για ευκολία είναι εντελώς παράλλογο γι αυτόν.Και γιατί να μην κάνω πολλά ΚΑΛΕΣΕ δηλαδή;Τουλάχιστον χρειάζεται να ξέρω μόνο την ΚΑΛΕΣΕ.Και αφού δεν πρόκειται στα πλαίσια αυτού του μαθήματος να αποκτήσω προγραμματιστική εμπειρία.Πως να κρίνω αν πρέπει να χρησιμοποιήσω συνάρτηση ή διαδικασία; 

petrosp13

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

alkisg

Στέλνω μια άσκηση από το τετράδιο μαθητή (ΔΣ5, 8ο κεφάλαιο) λυμένη με δύο τρόπους, για να τη σχολιάσουμε:
1) Με ΓΙΑ και συναρτήσεις
2) Με ΟΣΟ και διαδικασίες

Γράφω ΓΣαριθμοί γραμμών όταν αναφέρομαι στη λύση με ΓΙΑ/Συναρτήσεις και ΟΔαριθμοί γραμμών όταν αναφέρομαι στη λύση με ΟΣΟ/Διαδικασίες.

Η σύγκριση ΓΙΑ και ΟΣΟ είναι γνωστή (αρχικοποίηση / βήμα μετρητή), δεν τη σχολιάζω.

Σύγκριση διαδικασιών / συναρτήσεων:

  • ΓΣ5, ΟΔ4,5,7,8: Με διαδικασίες χρειάστηκε μια παραπάνω μεταβλητή καθώς και μια (παραπάνω) εντολή ΚΑΛΕΣΕ.
  • ΓΣ13,17, ΟΔ16,21,22: Με διαδικασίες χρειάστηκε μια παραπάνω μεταβλητή καθώς και μια (παραπάνω) εντολή ΚΑΛΕΣΕ.
  • ΓΣ19,20, ΟΔ25: Με συναρτήσεις χρειάστηκε μια παραπάνω εντολή για να ανατεθεί το αποτέλεσμα στη συνάρτηση.
  • ΓΣ30,31, ΟΔ37: Με συναρτήσεις χρειάστηκε μια παραπάνω εντολή για να ανατεθεί το αποτέλεσμα στη συνάρτηση.

Βλέπουμε δηλαδή ότι το όφελος δεν είναι μέσα στη συνάρτηση, αλλά κατά την κλήση της, όπου είναι πιο κατανοητή και δε χρειάζεται παραπανίσιες μεταβλητές και εντολές ΚΑΛΕΣΕ. Και αυτό ακριβώς είναι και ο σκοπός των (υπο)προγραμμάτων, να τα γράφουμε έτσι ώστε να μπορούμε στη συνέχεια να τα χρησιμοποιήσουμε πολλές φορές όσο το δυνατόν ευκολότερα.
Η σύγκριση θα ήταν πιο "έντονη" αν είχαμε μεγαλύτερη παράσταση να υπολογίσουμε και χρειαζόταν πολλές ΚΑΛΕΣΕ στις γραμμές ΔΟ7,8, ενώ με συναρτήσεις θα χρειαζόταν πάλι μόνο η γραμμή ΓΣ5.

Δηλαδή, όπως στη ΓΙΑ γλυτώνουμε το "βάσανο" του μετρητή (και 2 γραμμές κώδικα), εδώ γλυτώνουμε το "βάσανο" της ΚΑΛΕΣΕ (και 1 γραμμή κώδικα + 1 προσωρινή μεταβλητή).

Όσο για το πότε χρησιμοποιούμε συναρτήσεις (κατ' αντιστοιχία με το "γνωστός αριθμός επαναλήψεων" που λέμε στη ΓΙΑ):
Είμαι της γνώμης ότι συναρτήσεις χρησιμοποιούμε όταν χρειαζόμαστε κάποιο υποπρόγραμμα που επιστρέφει μία μόνο τιμή, και αυτή η τιμή δεν είναι πίνακας.

Θα ήθελα κάποτε να γινόταν μια δοκιμή (μάλλον όχι στην ΑΕΠΠ, σαν εξεταζόμενο μάθημα...), να έβγαιναν από την ύλη η ΓΙΑ, η ΑΡΧΗ_ΕΠΑΝΑΛΗΨΗΣ, οι συναρτήσεις και οι αλγόριθμοι για να βλέπαμε αν θα ήταν πιο εύκολα για τους μαθητές (έτσι δε θα χανόταν κάτι σε δυνατότητες)...  ???

Vangelis

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

kLee

Να ρωτήσω κάτι σχετικά με τη βαθμολόγηση κ τα υποπρογράμματα?

Αν ζητείται σε άσκηση "εμμέσως πλην σαφώς" να χρησινοποιηθεί συνάρτηση κ μαθητής χρησιμοποιήσει διαδικασία, πώς βαθμολογείται? Χάνει όλο εκείνο το κομμάτι ή δεν υπάρχει πρόβλημα?

Ρωτάω, γιατί ο ίδιος μαθητής που θα με ρωτήσει σε τί χρειαζόμαστε τις συναρτήσεις είναι πολλές φορές και αυτός που λέει ότι εγώ θα πάρω παντού διαδικασίες και τελειώνει η υπόθεση!!
Ανδροκλής Πολυμένης

Πληροφορικός