A programação funcional: Estado vs. redesignação

votos
13

Preciso de ajuda para obter a minha cabeça em torno da diferença entre o meu atual noção OOP de Estado, e da forma como seria feito em uma linguagem funcional como Haskell ou Clojure.

Para usar um exemplo banal, digamos que estamos lidando com objetos de conta bancária simplificada / estruturas / whatever. Em uma linguagem OOP, eu teria alguma classe mantendo uma referência a um BankAccount, que teria variáveis ​​de instância para coisas como taxa de juros e métodos como setInterestRate () que mudam o estado do objeto e geralmente retornar nada. No dizer Clojure, eu teria um struct-conta bancária (a hashmap glorificado) e funções especiais que levam um parâmetro de conta bancária e outras informações, e retornar uma nova estrutura. Então, ao invés de mudar o estado do objeto original, agora tenho um novo que estão sendo devolvidos, com as modificações desejadas.

Então ... o que eu faço com ele? Sobrescrever qualquer que seja variável foi referenciando a conta bancária de idade? Se assim for, isso tem vantagens sobre a abordagem OOP de mudança de estado? No final, em ambos os casos, parece um tem uma variável que faz referência o objeto com as mudanças necessárias. Retardado como eu sou, eu só tenho um vago conceito do que está acontecendo.

Espero que fazia sentido, obrigado por qualquer ajuda!

Publicado 09/12/2008 em 20:24
fonte usuário
Em outras línguas...                            


4 respostas

votos
11

Em um estilo funcional pura, você nunca vai substituir qualquer variável.

Uma analogia seria a de espaço-tempo na física. Se você considerar o mundo como 3d, posições, em seguida, os objetos não têm fixos - eles se movem ao longo do tempo. Para trazer a matemática para suportar sobre o mundo físico, portanto, adicionar uma dimensão de tempo e considerar os valores de várias propriedades em determinadas épocas. Ao fazê-lo, fizemos os objetos de nosso estudo em constantes. Da mesma forma, na programação, há uma simplicidade conceitual para ser tido por trabalhar com valores imutáveis. Objetos com uma identidade no mundo real pode ser modelado como uma sequência de valores imutáveis ​​(os estados do objeto, por vezes aumentando) em vez de um único valor que muda.

É claro que os detalhes de como associar a seqüência de valores para uma "identidade de objeto" pode ser um pouco peludo. Haskell tem Mônadas que permitem estado do modelo. Programação Reactive funcional é uma tentativa mais literal na modelagem de objetos no mundo, com atualizações funcionais puros, que eu acho que é uma direção muito promissor para a programação.

I notarão que Clojure, ao contrário de Haskell, não é puro, e você pode atualizar variáveis ​​como você sugeriu. Se você estiver atualizando apenas alguns variáveis ​​em um nível alto, você ainda vai provavelmente desfrutar de muitos dos benefícios simplicidade conceitual de programação funcional.

Respondeu 09/12/2008 em 21:10
fonte usuário

votos
8

Presumivelmente no mundo OO você tem um loop e está modificando estas contas bancárias e outra vez em resposta às solicitações. Vamos supor que você tem toda uma carteira de contas e estes têm tipo Portfolio. Então, em Haskell você iria escrever uma função pura

updatePortfolio :: Request -> Portfolio -> Portfolio

E o seu loop principal pode ler as solicitações de entrada padrão e manter a sua carteira até à data. (O exemplo não é muito útil a menos que você pode escrever a carteira bem, mas é mais simples.)

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)

e agora eu espero que você veja o que aconteceu ao seu estado mutável: em um programa funcional típico, estado que muda é passado como um parâmetro para uma função. Quando o changess estado, você fazer uma nova chamada de função. A chamada está em posição de cauda (você pode olhar para cima 'chamada de cauda adequada') e por isso não utilizar quaisquer recursos adicionais, e de fato quando o compilador gera código assembly gera um loop, e vai manter o ponteiro para o em constante mudança Portfolio num registo.

Este é um exemplo muito brinquedo, mas espero que lhe dá um pouco do sabor de uma linguagem funcional.

Respondeu 10/12/2008 em 04:57
fonte usuário

votos
4

Então ... o que eu faço com ele? Sobrescrever qualquer que seja variável foi referenciando a conta bancária de idade?

sim

Se assim for, isso tem vantagens sobre a abordagem OOP de mudança de estado?

Vamos dizer que o cálculo de qualquer ação que você faz no que struct leva muito tempo e algo acontece no meio do caminho e você precisa voltar para a estrutura original ou o cálculo levantou um erro. Com a interpretação que você apresentou para mim de OO (usando uma referência, porque você pode ter uma linguagem OO imutável) que os dados poderiam ser desconhecido do --é corrupto a menos que suficiente informação foi dada a partir da chamada de função falhou, e permite sugerir que falhou seriamente. Em uma abordagem funcional você sabe com certeza que a sua estrutura de dados original está correta --because você inicialmente feito uma cópia.

Estender este cenário em aplicações multi-threaded. Nós podemos garantir que ninguém mais está usando a estrutura de dados que são uma vez que todos nós temos nossa própria versão dela.

Além disso, podemos economizar espaço usando dados da outra estrutura que estamos copiando. Um exemplo clássico é quando a adição de um elemento para a cabeça de uma lista. Se tivermos um ponteiro para o segundo elemento, e um ponteiro para o primeiro elemento se pode fazer referência a ambas as listas com apenas o tamanho do primeiro (ver abaixo). Sem imutabilidade não podemos garantir isso.

        b__
           |  
a -> [6|] -+-> [5|] -> [4|] -> [3|] -> [2|] -> [1|x]
Respondeu 09/12/2008 em 20:58
fonte usuário

votos
1

Olhe para Haskell, que é uma pura funcional linguagem não tem re-atribuição que seja, assim como há outros efeitos colaterais: a fim de fazer IO, no IO mônada construí-la na verdade substitui o RealWorld com uma nova instância do mundo que tem, por exemplo, o novo texto exibido no console.

Respondeu 09/12/2008 em 22:29
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more