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


Για να χρησιμοποιήσετε μια τετριμμένη παράδειγμα, ας υποθέσουμε ότι έχουμε να κάνουμε με αντικείμενα λογαριασμό απλοποιημένη τράπεζα / Δομές / οτιδήποτε άλλο. Σε μια γλώσσα OOP, θα είχα κάποια τάξη κρατώντας μια αναφορά σε μια BankAccount, η οποία θα πρέπει παράδειγμα μεταβλητές για πράγματα όπως το επιτόκιο, και μεθόδους όπως setInterestRate () που αλλάζουν την κατάσταση του αντικειμένου και γενικά τίποτα να επιστρέψει. Σε λένε Clojure, θα είχα ένα struct σε τραπεζικό λογαριασμό (μια δοξασμένη HashMap), και τις ειδικές λειτουργίες που λαμβάνουν μια παράμετρο σε τραπεζικό λογαριασμό και άλλες πληροφορίες, και να επιστρέψει ένα νέο struct. Έτσι, αντί να αλλάζει την κατάσταση του αρχικού αντικειμένου, έχω τώρα ένα νέο που επιστρέφονται με τις επιθυμητές τροποποιήσεις. 


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


Ελπίζω ότι είχε νόημα, ευχαριστώ για οποιαδήποτε βοήθεια!

 
Λειτουργική προγραμματισμού: κατάσταση έναντι αλλαγή
====================================================



Σε ένα καθαρό λειτουργικό στιλ, δεν πρόκειται ποτέ να αντικαταστήσετε κάθε μεταβλητή.


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


Φυσικά οι λεπτομέρειες για το πώς να συνδέσει την ακολουθία των τιμών σε μια «ταυτότητα αντικειμένου» μπορεί να είναι λίγο τριχωτό. Haskell έχει [Μονάδες](http://en.wikipedia.org/wiki/Monad_(functional_programming)) που θα αφήσει το μοντέλο κράτους. [Λειτουργική Αντιδραστική Προγραμματισμός](http://en.wikipedia.org/wiki/Functional_reactive_programming) είναι μια πιο κυριολεκτική προσπάθεια μοντελοποίηση αντικειμένων στον κόσμο με καθαρό λειτουργικό ενημερώσεις, που πιστεύω ότι είναι μια πολλά υποσχόμενη κατεύθυνση για τον προγραμματισμό.


Θα σημειωθεί ότι Clojure, σε αντίθεση με Haskell, δεν είναι καθαρό, και μπορείτε να ενημερώσετε τις μεταβλητές, όπως προτείνατε. Αν κάνετε ενημέρωση μόνο μερικές μεταβλητές σε υψηλό επίπεδο, θα εξακολουθούν πιθανώς να απολαύσουν πολλές από τις εννοιολογικές οφέλη απλότητα του λειτουργικού προγραμματισμού.

 

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



```
updatePortfolio :: Request -> Portfolio -> Portfolio

```

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



```
readRequest :: IO Request  -- an action that, when performed, reads a Request with side effects

main :: Portfolio -> IO ()  -- a completely useless program that updates a Portfolio in response to a stream of Requests

main portfolio = do req <- readRequest
                    main (updatePortfolio req)

```

και τώρα ελπίζω να δούμε τι συνέβη σε μεταβλητά σας κατάσταση: σε ένα τυπικό λειτουργικό πρόγραμμα, κατάσταση που αλλάζει περνά ως παράμετρος σε μια λειτουργία. Όταν το κράτος changess, κάνετε μια νέα κλήση της συνάρτησης. Η κλήση είναι σε θέση ουρά (μπορείτε να αναζητήσετε «σωστή κλήση ουρά») και γι 'αυτό δεν χρησιμοποιεί πρόσθετους πόρους, και μάλιστα όταν ο compiler δημιουργεί κώδικα συναρμολόγησης δημιουργεί έναν βρόχο, και θα κρατήσει το δείκτη προς τα συνεχώς μεταβαλλόμενο χαρτοφυλακίου σε μητρώο.


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

 

*Λοιπόν ... τι να κάνω με αυτό; Αντικατάσταση οτιδήποτε μεταβλητή αναφοράς το παλιό τραπεζικό λογαριασμό;*


Ναί


*Αν ναι, μήπως αυτό έχει πλεονεκτήματα σε σχέση με την προσέγγιση κατάσταση αλλάζει OOP;*


Ας πούμε ότι ο υπολογισμός οποιασδήποτε δράσης που κάνετε σε αυτό το struct παίρνει πολύ χρόνο και κάτι που συμβαίνει στη μέση και θα πρέπει να επανέλθει στην αρχική του struct ή ο υπολογισμός έθεσε ένα σφάλμα. Με την ερμηνεία που έχετε παρουσιάζονται σε μένα των OO (χρησιμοποιώντας μια αναφορά, επειδή μπορείτε να έχετε μια αμετάβλητη γλώσσα OO) ότι τα δεδομένα θα μπορούσε να είναι άγνωστο διεφθαρμένη --it, εκτός εάν αρκετές πληροφορίες δόθηκαν από την αποτυχημένη κλήση της συνάρτησης, και σας δίνει τη δυνατότητα να προτείνει απέτυχε κακώς. Σε μια λειτουργική προσέγγιση που γνωρίζουμε με βεβαιότητα ότι η αρχική δομή των δεδομένων σας είναι σωστή --because που αρχικά έκανε ένα αντίγραφο.


Επεκτείνετε αυτό το σενάριο σε multi-threaded εφαρμογές. Μπορούμε να διασφαλίσουμε ότι κανείς άλλος χρησιμοποιεί τη δομή των δεδομένων που είναι από τη στιγμή που όλοι έχουμε τη δική μας εκδοχή της.


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



```
        b__
           |  
a -> [6|] -+-> [5|] -> [4|] -> [3|] -> [2|] -> [1|x]

```
 

Κοιτάξτε Haskell, η οποία είναι μια καθαρή λειτουργική γλώσσα δεν έχει καμία απολύτως εκ νέου ανάθεση, καθώς δεν υπάρχουν άλλες παρενέργειες: για να γίνει IO, στην *[IO μονάδα](http://www.haskell.org/haskellwiki/IO_inside#Welcome_to_the_RealWorld.2C_baby_:.29)* κατασκευάσει ουσιαστικά αντικαθιστά τον **RealWorld** με ένα νέο παράδειγμα της κόσμο που έχει, για παράδειγμα, το νέο κείμενο που εμφανίζεται στην κονσόλα.

 