Warum benötigen einige funktionale Sprachen Software-Transaktionsspeicher?

24

Funktionssprachen sollten per Definition keine Statusvariablen verwalten. Warum bieten dann Haskell, Clojure und andere Implementierungen von Software Transactional Memory (STM) an? Gibt es einen Konflikt zwischen zwei Ansätzen?

Michael Spector
quelle
Ich möchte nur dieses interessante Papier verlinken , das ziemlich viel erklärt.
Falcon
1
Es ist klar, dass alle funktionalen Sprachen den Status beibehalten, die Reinheit jedoch vorschreibt, dass sich der Wert einer Variablen nach dem Festlegen nicht ändert.
Robert Harvey

Antworten:

13

An einer funktionalen Sprache, die einen veränderlichen Zustand beibehält, ist nichts auszusetzen. Sogar "reine" funktionale Sprachen wie Haskell müssen den Zustand aufrechterhalten, um mit der realen Welt interagieren zu können. "Unreine" Funktionssprachen wie Clojure ermöglichen Nebenwirkungen, die Mutationen einschließen können.

Der wichtigste Punkt ist, dass funktionale Sprachen den veränderlichen Zustand verhindern, es sei denn, Sie brauchen ihn wirklich . Der allgemeine Stil besteht darin, mit reinen Funktionen und unveränderlichen Daten zu programmieren und nur mit "unreinen" veränderlichen Zuständen in den spezifischen Teilen Ihres Codes zu interagieren, die dies erfordern. Auf diese Weise können Sie den Rest Ihrer Codebasis "rein" halten.

Ich denke, es gibt mehrere Gründe, warum STM in funktionalen Sprachen häufiger vorkommt:

  • Forschung : STM ist ein heißes Forschungsthema, und Programmiersprachenforscher bevorzugen häufig die Arbeit mit funktionalen Sprachen (ein eigenständiges Forschungsthema, außerdem ist es einfacher, "Beweise" für das Programmverhalten zu erstellen).
  • Nicht zusammensetzen durch Sperren: STM kann als Alternative zu sperrenbasierten Ansätzen für die Parallelität angesehen werden, bei denen Probleme auftreten, wenn Sie durch Zusammensetzen verschiedener Komponenten auf komplexe Systeme skalieren. Dies ist wohl der wichtigste "pragmatische" Grund für STM
  • STM passt gut zur Unveränderlichkeit : Wenn Sie eine große unveränderliche Struktur haben, möchten Sie sicherstellen, dass sie unveränderlich bleibt, damit kein anderer Thread hereinkommt und ein Unterelement mutiert. Ebenso können Sie, wenn Sie die Unveränderlichkeit dieser Datenstruktur garantieren können, zuverlässig als einen stabilen "Wert" in Ihrem STM-System behandeln.

Ich persönlich mag Clojures Ansatz, die Veränderbarkeit zuzulassen, aber nur im Kontext streng kontrollierter "verwalteter Referenzen", die an STM-Transaktionen teilnehmen können. Alles andere in der Sprache ist "rein funktional".

  ;; define two accounts as managed references
  (def account-a (ref 100))
  (def account-b (ref 100))

  ;; define a transactional "transfer" function
  (defn transfer [ref-1 ref-2 amount]
    (dosync
      (if (>= @ref-1 amount)
        (do 
          (alter ref-1 - amount)
          (alter ref-2 + amount))
        (throw (Error. "Insufficient balance!")))))

  ;; make a stranfer
  (transfer account-a account-b 75)

  ;; inspect the accounts
  @account-a
  => 25

  @account-b
  => 175

Beachten Sie, dass der obige Code vollständig transaktionell und atomar ist - ein externer Beobachter, der die beiden Salden innerhalb einer anderen Transaktion liest, sieht immer einen konsistenten atomaren Zustand, dh die beiden Salden summieren sich immer auf 200. Bei einer sperrenbasierten Parallelität ist dies ein überraschend schwieriges Problem in einem großen komplexen System mit vielen Transaktionsentitäten zu lösen.

Für zusätzliche Aufklärung leistet Rich Hickey in diesem Video eine hervorragende Erklärung für Clojures STM

mikera
quelle
3

Funktionssprachen sollten per Definition keine Statusvariablen verwalten

Deine Definition ist falsch. Sprache, die den Status nicht aufrechterhalten kann, kann einfach nicht verwendet werden.

Der Unterschied zwischen funktionalen und imperativen Sprachen besteht nicht darin, dass eine von ihnen einen Staat hat und die andere nicht. Es ist in gewisser Weise, dass sie den Staat aufrechterhalten.

Imperative Sprachen haben Staat im ganzen Programm verbreitet.

Funktionssprachen isolieren und pflegen den Zustand explizit über Typensignaturen. Und das ist der Grund, warum sie ausgefeilte Zustandsverwaltungsmechanismen wie STM bereitstellen.

Vagif Verdi
quelle
2

Manchmal erfordert ein Programm einen veränderlichen Status (z. B. Datenbankinhalte für eine Web-App), und es wäre großartig, wenn Sie es verwenden könnten, ohne die Vorteile der funktionalen Programmierung zu verlieren . In nicht funktionalen Sprachen durchdringt der veränderbare Zustand alles. Wenn Sie es mit einer speziellen API explizit machen , können Sie es auf einen kleinen identifizierbaren Bereich beschränken, während alles andere rein funktional bleibt. Zu den Vorteilen von FP zählen ein einfacheres Debugging, wiederholbare Komponententests, eine reibungslose Parallelität und die Benutzerfreundlichkeit von Multicore / GPU.

Will Ware
quelle
Sie meinen wahrscheinlich veränderlichen Zustand. Alle Programme behalten ihren Zustand, auch die funktionalen.
Robert Harvey
Du hast recht. Klar, ich verbringe nicht genug Zeit mit funktionaler Programmierung, um das zu verpassen.
Will Ware