Frage

Ich habe das Lernen kürzlich über funktionale Programmierung (speziell Haskell, aber ich habe durch Tutorials auf Lisp und Erlang auch weg). Während ich die Konzepte sehr aufschlussreich fand, habe ich noch nicht die praktische Seite des „keine Nebenwirkungen“ -Konzept sehen. Was sind die praktischen Vorteile davon? Ich versuche, in der funktionalen Einstellung zu denken, aber es gibt einige Situationen, die nur allzu komplex erscheinen, ohne die Fähigkeit Zustand auf einfache Weise zu speichern (Ich glaube nicht, Haskells Monaden ‚easy‘).

Ist es weiterhin wert Haskell (oder ein andere rein funktionale Sprache) in der Tiefe lernen? Ist funktionale oder staatenlos Programmierung tatsächlich produktiver als prozedurale? Ist es wahrscheinlich, dass ich Haskell oder eine andere funktionale Sprache später verwenden, wird weitergehen, oder soll ich lernen, es nur für das Verständnis?

ich weniger kümmern uns um Leistung als die Produktivität. Also frage ich vor allem, wenn ich in einer funktionalen Sprache als eine prozedurale / objektorientiert / was auch immer produktiver sein wird.

War es hilfreich?

Lösung

Lesen Sie Functional Programming in aller Kürze .

Es gibt viele Vorteile zu staatenlos Programmierung, nicht zuletzt von denen ist dramatisch multithreaded und gleichzeitige Code. Um es klar zu sagen, wandelbar Zustand ist Feind des multithreaded Code. Wenn Werte standardmäßig unveränderlich sind, Programmierer müssen nicht über einen Thread Mutieren der Wert des gemeinsamen Zustand zwischen zwei Threads kümmern, so beseitigt es eine ganze Klasse von Multithreading-Bugs im Zusammenhang Bedingungen zu fahren. Da es keine Rennbedingungen sind, gibt es keinen Grund Schlösser entweder zu verwenden, so eliminiert Unveränderlichkeit eine andere ganze Klasse von Fehlern sowie zu Deadlocks verwandt.

Das ist der große Grund, warum die funktionale Programmierung Fragen, und wahrscheinlich das beste auf der funktionalen Programmierung Zug für das Springen. Es gibt auch viele anderen Vorteile, darunter vereinfachtes Debugging (dh Funktionen sind rein und mutieren Zustand nicht in anderen Teilen einer Anwendung), mehr prägnanten und ausdruck Code, weniger Standardcode im Vergleich zu Sprachen, die auf Designmuster stark abhängig sind, und kann der Compiler den Code aggressiver optimieren.

Andere Tipps

Je mehr Teile des Programms sind staatenlos, desto mehr Möglichkeiten gibt es Stücke zusammen zu stellen, ohne etwas brechen . Die Macht des staatenlos Paradigma liegt in Staatenlosigkeit (oder Reinheit) nicht per se , sondern die Fähigkeit, es gibt Ihnen leistungsstarke, wiederverwendbar Funktionen und kombinieren sie zu schreiben.

Sie können ein gutes Tutorial mit vielen Beispielen in John Hughes Papier Warum Functional Programming Matters (PDF).

Sie werden Gobs produktiver, vor allem, wenn Sie eine funktionale Sprache auswählen, die auch algebraische Datentypen und Musterabgleich (Caml, SML, Haskell) hat.

Viele der anderen Antworten haben auf die Leistung (Parallelität) Seite der funktionalen Programmierung konzentriert, die meiner Meinung nach sehr wichtig ist. Aber Sie haben speziell über die Produktivität fragen, wie in, können Sie die gleiche Sache schneller in einem funktionalen Paradigma programmieren als in einem imperativen Paradigmas.

Ich finde eigentlich (aus eigener Erfahrung), dass die Programmierung in F #, um die Art und Weise paßt ich besser denken, und es ist so einfach. Ich denke, das ist der größte Unterschied. Ich habe in beiden F # und C # programmiert, und es gibt viel weniger in F # „um die Sprache zu kämpfen“, die ich liebe. Sie müssen über die Details in F # nicht denken. Hier ein paar Beispiele dafür, was ich gefunden habe ich wirklich genießen.

Zum Beispiel, obwohl F # statisch typisiert (alle Typen werden bei der Kompilierung aufgelöst), Zahlen der Typinferenz heraus, welche Arten Sie haben, so muss man es nicht sagen. Und wenn es sie nicht herausfinden kann, macht es automatisch Ihre Funktion / Klasse / was auch immer generisch. So haben Sie noch nie etwas generisch zu schreiben, was, es ist alles automatisch. Ich finde, das bedeutet, ich verbringe mehr Zeit, sich Gedanken über das Problem und weniger, wie es zu implementieren. In der Tat, wenn ich zurück zu C # kommen, ich finde ich diese Typinferenz wirklich vermissen, die Sie nie erkennen, wie störend es ist, bis Sie es nicht mehr brauchen zu tun.

Auch in F #, statt Schleifen zu schreiben, rufen Sie Funktionen. Es ist eine subtile Veränderung, aber signifikant, weil Sie mehr nicht über das Schleifenkonstrukt zu denken. Zum Beispiel, hier ist ein Stück Code, der durch gehen würde, und passen Sie etwas (ich kann mich nicht erinnern, was, es ist aus einem Projekt Euler Puzzle):

let matchingFactors =
    factors
    |> Seq.filter (fun x -> largestPalindrome % x = 0)
    |> Seq.map (fun x -> (x, largestPalindrome / x))

Ich weiß, dass ein Filter tut dann eine Karte (das ist eine Umwandlung jedes Elements) in C # ganz einfach wäre, aber man muss auf einem niedrigeren Niveau denken. Insbesondere würden Sie die Schleife selbst zu schreiben, und Ihre eigene explizite if-Anweisung haben, und diese Art von Dingen. Da das Lernen F #, habe ich realisiert habe ich es leichter gefunden in der funktionalen Weise zu codieren, wo, wenn Sie filtern möchten, können Sie „Filter“ zu schreiben, und wenn Sie zuordnen möchten, schreiben Sie „Karte“, statt der Umsetzung jeder der Details.

Ich liebe auch die |> Operator, die ich denke, F # von ocaml trennt und möglicherweise andere funktionale Sprachen. Es ist das Rohr Operator, es läßt Dich „pipe“ die Ausgabe eines Ausdrucks in den Eingang eines anderen Ausdrucks. Es macht den Code folgen, wie ich mehr denken. Wie im Codeausschnitt oben, das sagt, „die Faktoren Folge nehmen, filtern, dann zuordnen.“ Es ist ein sehr hohes Maß an Denken, das Sie in einer imperativen Programmiersprache nicht bekommen, weil Sie so beschäftigt sind, schreiben die Schleife und if-Anweisungen. Es ist das einzige, was ich am meisten vermisse, wenn ich in einer anderen Sprache zu gehen.

Also nur im Allgemeinen, auch wenn ich in C # und F # programmieren kann, finde ich es einfacher, F # verwenden, da Sie auf einem höheren Niveau denken. Ich würde argumentieren, dass, weil die kleineren Details aus dem funktionalen Programmierung (in F # zumindest) entfernt werden, dass ich produktiver.

Bearbeiten : Ich sah in einer der Kommentare, die Sie für ein Beispiel von „Zustand“, fragte in einer funktionalen Programmiersprache. F # kann imperativ geschrieben werden, so ist hier ein direktes Beispiel, wie Sie wandelbaren Zustand in F # haben:

let mutable x = 5
for i in 1..10 do
    x <- x + i

Betrachten Sie alle schwierig Bugs Sie eine lange Zeit Debuggen ausgegeben haben.

Nun, wie viele dieser Fehler aufgrund „unbeabsichtigte Wechselwirkungen“ zwischen zwei getrennten Komponenten eines Programms waren? (Fast alle Threading-Bugs haben diese Form: Rennen mit gemeinsam genutzten Daten zu schreiben, Deadlocks, ... Darüber hinaus ist es üblich, Bibliotheken zu finden, die eine unerwartete Wirkung auf die globale Zustand haben, oder lesen / schreiben die Registrierung / Umwelt, etc.) < em> I würde postulieren, dass mindestens 1 in 3 fallen 'harten Fehler' in diese Kategorie.

Nun, wenn Sie zu staatenlos / unveränderlich / reine Programmierung wechseln, all diese Fehler weg. Sie sind stattdessen mit einigen neuen Herausforderungen (zB wenn Sie tun will verschiedene Module mit der Umwelt zu interagieren), aber in einer Sprache wie Haskell, erhalten diese Interaktionen explizit in das Typsystem verdinglicht, die Sie bedeutet nur Blick auf die Art der Funktion und der Vernunft über die Art der Wechselwirkungen kann es mit dem Rest des Programms haben kann.

Das ist der große Gewinn von ‚Unveränderlichkeit‘ IMO. In einer idealen Welt würden wir alle Designs grandios APIs und auch wenn die Dinge wandelbar, würden Effekte lokal sein und gut dokumentierte und unerwartete Interaktionen würden auf ein Minimum beschränkt werden. In der realen Welt gibt es viele APIs, die mit den globalen Zustand in vielfältiger Weise interagieren, und diese sind die Quelle der schädlichsten Fehler. Angehende zu Staatenlosigkeit strebt los sein unbeabsichtigter / implizite / hinter den Kulissen Interaktionen zwischen den Komponenten.

Ein Vorteil staatenlos Funktionen ist, dass sie Vorkalkulation oder Caching der Funktion des Rückgabewertes ermöglichen. Sogar einige C-Compiler können Sie explizit Funktionen als staatenlos zu markieren, um ihre optimisability zu verbessern. Wie viele andere hier schon berichtet haben, sind staatenlos Funktionen viel einfacher parallelisieren.

Aber Effizienz ist nicht die einzige Sorge. Eine reine Funktion ist einfacher zu testen und debuggen, da alles, was es wird ausdrücklich darauf hingewiesen beeinflusst. Und wenn in einer funktionalen Sprache programmiert, so erhält man die Gewohnheit, so wenige Funktionen machen „dirty“ (mit E / A, etc.) wie möglich. Abtrennen der Stateful Sachen auf diese Weise ist ein guter Weg, um Programme zu entwickeln, auch in nicht-so-funktionalen Sprachen.

Funktionale Sprachen können eine Weile dauern, bis „get“, und es ist schwierig, mit jemandem zu erklären, der nicht durch diesen Prozess gegangen ist. Aber die meisten Menschen, die lange genug bestehen bleiben schließlich erkennen, dass die Aufregung ist es wert, auch wenn sie am Ende nicht viel funktionale Sprachen verwendet wird.

Ohne Zustand, es ist sehr einfach, um automatisch den Code parallelisieren (als CPUs mit immer mehr Kernen hergestellt sind dies ist sehr wichtig).

Ich schrieb einen Beitrag zu eben diesem Thema eine Weile zurück: auf die Bedeutung der Reinheit .

Stateless Web-Anwendungen wichtig sind, wenn Sie höheren Verkehr mit starten.

Es könnte von Benutzerdaten viel sein, dass Sie nicht wollen, aus Sicherheitsgründen zum Beispiel auf der Clientseite zu speichern. In diesem Fall müssen Sie es Server-Seite zu speichern. Sie könnten die Web-Anwendungen Standardsitzung verwenden, aber wenn Sie mehr als eine Instanz der Anwendung haben Sie sicherstellen müssen, dass jeder Benutzer immer auf die gleiche Instanz gerichtet ist.

Loadbalancer haben oft die Fähigkeit, ‚Sticky Sessions‘ zu haben, wo der Load Balancer einige, wie weiß, welcher Server die Benutzer zu verlangen, zu senden. Dies ist zwar nicht ideal, zum Beispiel bedeutet, dass es jedes Mal, wenn Sie Ihre Web-Anwendung neu starten, werden alle angeschlossenen Benutzer ihre Sitzung verlieren.

Ein besserer Ansatz ist es, die Sitzung hinter den Web-Servern in einer Art von Datenspeicher zu speichern, in diesen Tagen gibt es viele interessante nosql Produkte für dieses (redis, Mongo, Elasticsearch, Memcached). Auf diese Weise die Web-Server sind staatenlos, aber sie haben immer noch State-Server-Seite und die Verfügbarkeit dieser Zustand kann durch die Wahl der richtigen Datenspeicher Setup verwaltet werden. Diese Daten speichert in der Regel große Redundanz haben, so dass es fast immer möglich sein sollte, Änderungen an Ihrer Web-Anwendung zu machen und auch den Datenspeicher, ohne die Benutzer zu beeinträchtigen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top