Por que algumas linguagens funcionais precisam de memória transacional de software?


24

Linguagens funcionais, por definição, não devem manter variáveis ​​de estado. Por que, então, Haskell, Clojure e outros fornecem implementações de memória transacional de software (STM)? Existe um conflito entre duas abordagens?


Gostaria apenas de vincular este artigo interessante, que explica bastante.
— Falcon

11
Para ser claro, todas as linguagens funcionais mantêm o estado, mas a pureza determina que o valor de uma variável não muda depois que é definido.
— Robert Harvey

Respostas:


13

Não há nada de errado em uma linguagem funcional manter um estado mutável. Mesmo linguagens funcionais "puras", como Haskell, precisam manter o estado para interagir com o mundo real. Linguagens funcionais "impuras" como o Clojure permitem efeitos colaterais que podem incluir um estado de mutação.

O ponto principal é que as linguagens funcionais desencorajam o estado mutável, a menos que você realmente precise . O estilo geral é programar usando funções puras e dados imutáveis ​​e interagir apenas com o estado mutável "impuro" nas partes específicas do seu código que o exigem. Dessa forma, você pode manter o restante da sua base de código "pura".

Eu acho que há várias razões pelas quais o STM é mais comum em linguagens funcionais:

  • Pesquisa : STM é um tópico de pesquisa popular, e os pesquisadores da linguagem de programação frequentemente preferem trabalhar com idiomas funcionais (um tópico de pesquisa em si mesmos, além de ser mais fácil criar "provas" sobre o comportamento do programa)
  • Bloquear não compor : o STM pode ser visto como uma alternativa às abordagens de concorrência baseadas em bloqueio, que começam a ter problemas quando você aumenta a escala para sistemas complexos compondo componentes diferentes. Esta é sem dúvida a principal razão "pragmática" para STM
  • O STM se encaixa bem com a imutabilidade : se você tem uma estrutura imutável grande, deseja garantir que ela permaneça imutável, para que você não queira que outro encadeamento entre e modifique algum subelemento. Da mesma forma, se você puder garantir a imutabilidade da referida estrutura de dados, poderá tratá-lo com segurança como um "valor" estável em seu sistema STM.

Pessoalmente, gosto da abordagem de Clojure de permitir a mutabilidade, mas apenas no contexto de "referências gerenciadas" estritamente controladas que podem participar de transações do STM. Todo o resto da linguagem é "puramente funcional".

  ;; 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

Observe que o código acima é totalmente transacional e atômico - um observador externo que lê os dois saldos em outra transação sempre verá um estado atômico consistente, ou seja, os dois saldos sempre somam 200. Com a concorrência baseada em bloqueio, esse é um problema surpreendentemente difícil resolver em um grande sistema complexo com muitas entidades transacionais.

Para uma iluminação extra, Rich Hickey faz um excelente trabalho ao explicar o STM de Clojure neste vídeo


3

Linguagens funcionais, por definição, não devem manter variáveis ​​de estado

Sua definição está errada. Linguagem que não pode manter o estado simplesmente não pode ser usada.

A diferença entre linguagens funcionais e imperativas não é que uma delas tenha estado e a outra não. É de certa forma que eles mantêm o estado.

Linguagens imperativas têm estado espalhado por todo o programa.

Linguagens funcionais isolam e mantêm o estado explicitamente por meio de assinaturas de tipo. E é por isso que eles fornecem mecanismos sofisticados de gerenciamento de estado, como o STM.


2

Às vezes, um programa requer um estado mutável (por exemplo, conteúdo de banco de dados para um aplicativo Web) e seria ótimo poder usá-lo sem perder os benefícios da programação funcional. Em linguagens não funcionais, o estado mutável permeia tudo. Se você o tornar explícito com algum tipo de API especial , poderá confiná-lo a uma pequena região identificável, enquanto todo o resto permanecerá puramente funcional. Os benefícios do FP incluem depuração mais fácil, teste de unidade repetível, simultaneidade indolor e compatibilidade com vários núcleos / GPU.


Você provavelmente quer dizer estado mutável. Todos os programas mantêm estado, mesmo os funcionais.
— Robert Harvey

Você está certo. Claramente, não estou gastando tempo suficiente fazendo programação funcional, para ter perdido isso.
— Will Ware
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.