FP:在没有实际状态变化的情况下反映状态

FP: Reflecting state in absence of actual state change?

本文关键字:状态 变化 情况下 FP      更新时间:2023-09-26

我对一些高级函数式编程思想不熟悉,特别是:如何处理不可变数据。数据结构通常是复合的,由更小的数据结构组成。例如,如果我们有一个家庭集合,它由一个家庭的所有成员组成。我们可以构造这个家族:

var flintstones = new Family().
    add(new Member({name: 'Fred'})).    //returns new instance of family 
    add(new Member({name: 'Wilma'}).    // "
    add(new Member({name: 'Pebbles'})); // "
var fred = flintstones.get({name: 'Fred'}).set({lname: 'Flintstone'});
flintstones = fred.family(); //new instance of family with latest fred.

注意改变fred实际上并没有改变flintstones。我可以抓取一个新的参考flintstones,但为了什么目的?因为所有对象都只是快照,所以我看不到保留引用的意义。状态变化已经被抽象掉了,所以我们不打算使用观察者模式。因此,像gui这样的依赖于状态变化的东西是如何处理的呢?为了保持同步,除了观察之外,还有什么功能上的替代方法?我不认为物体本身有任何渲染它们自己的业务。函数式程序如何处理保持单页web应用GUI同步的状态?

Rich Hickey的演讲激发了我对函数式编程的探索。我理解他的概念,但我很难跳到一个实际的实现(在JavaScript中)。

在您的示例中,Family应该是不可变的。因此,每次调用add都必须返回一个全新的对象,该对象基于现有对象的内容(它们本身是不可变的,因此复制它们不是问题)加上新对象。同样,你在Fred上调用的set必须返回一个基于Fred但具有不同姓氏的全新家庭成员。(因此,Flintstones内部的原始Fred根本没有改变。)

这种函数式风格的优点是,一旦你得到了一个对象的引用,你就知道它不会改变。如果它在构造时是有效的,那么就不必一直检查它是否仍然有效。因此,您可以将对象从代码中传递出去,而不必先克隆它,以保护内部副本不被更改。

如果你想学习更多关于函数式编程的知识,你最好尝试一下纯粹的函数式语言,比如Haskell或f#;尝试在JavaScript中进行函数式编程很可能会令人困惑。