他说的是什么意思
函数式程序没有边
影响?
大多数人认为编程就是创建变量、为其赋值、将内容添加到列表等。变量“变化”,因此得名。
函数式编程是一种消除变量的程序设计风格——一切都是常量或只读。
当 Joel 说函数式程序没有副作用时,涉及到很多挥手的内容,因为编写函数式程序非常容易,do修改变量——但很大程度上,当人们谈论函数式编程时,他们指的是不持有任何可修改状态的程序。
“但是朱丽叶!如果不能,如何编写一个有用的程序?修改任何东西"
好问题!
您可以通过创建具有修改状态的对象的新实例来“修改”事物。例如:
class Customer
{
public string Id { get; private set; }
public string Name { get; private set; }
public Customer(string id, string name)
{
this.Id = id;
this.Name = name;
}
public Customer SetName(string name)
{
// returns a new customer with the given name
return new Customer(this.Id, name);
}
}
因此,所有初始化都在构造函数中进行,并且我们无法再次修改该对象 - 我们将修改传递到构造函数中来创建新实例。
您会惊讶地发现这种编程风格能走多远。
“但是朱丽叶!?这么多的复制怎么可能有效呢?”
诀窍是意识到您不必复制整个对象图,只需复制已更改的部分。如果对象图的某些部分没有更改,可以在新对象中重用它(复制pointer,不要在图表的该部分新建任何对象的新实例)。
您会惊讶地发现这种编程风格能走多远。事实上,其极其轻松编写许多常见数据结构的不可变版本——例如不可变的 Avl 树、红黑树、多种堆等。请参阅here https://stackoverflow.com/questions/2437733/why-is-insertion-into-my-tree-faster-on-sorted-input-than-random-input用于实现不可变陷阱。
在大多数情况下,数据结构的不可变版本与可变版本具有相同的插入/查找/删除计算复杂性。唯一的区别是插入返回数据结构的新版本,而不修改原始数据结构。
这如何实现并行化
琐碎的?
想想看:如果您有一个不可变的树或任何其他数据结构,那么您可以使用两个线程插入、删除和查找树中的项目,而无需锁定。由于树是不可变的,一个线程不可能在另一个线程的鼻子下将对象置于无效状态 - 因此我们消除了与竞争条件相关的一整类多线程错误。由于我们没有竞争条件,因此不需要锁,因此我们还消除了与死锁相关的一整类错误。
因为不可变对象本质上是线程安全的,所以据说它们使并发变得“微不足道”。但这只是故事的一半。那里are有时我们需要一个线程中的更改对另一个线程可见 - 那么我们如何使用不可变对象来做到这一点?
诀窍是重新思考我们的并发模型。我们不是让两个线程彼此共享状态,而是将线程视为一种可以发送和接收消息的邮箱。
因此,如果线程 A 有一个指向线程 B 的指针,它可以将消息(更新后的数据结构)传递给线程 B,线程 B 将其副本与数据结构及其收到的消息中的副本合并。线程也可以通过itself作为消息,线程 A 将自身发送给线程 B,然后线程 B 通过它收到的指针将消息发送回线程 A。
相信我,上面的策略使并发编程比可变状态上的锁容易 1000 倍。因此,Joel 评论的重要部分是:“如果不了解函数式编程,你就无法发明 MapReduce,这种算法使 Google 具有如此大规模的可扩展性。”
传统的锁定不能很好地扩展,因为为了锁定一个对象,您需要对其指针的引用——锁定的对象需要与执行锁定的对象位于同一内存中。您无法跨进程获取对象的锁。
但想一想上面的消息传递模型:线程相互传递两个消息。将消息传递给同一进程中的线程与将消息传递给侦听某个 IP 地址的线程之间真的有区别吗?并不真地。正是因为线程可以跨进程边界发送和接收消息,消息传递才可以扩展,因为它不绑定到一台机器,所以您可以让您的应用程序根据需要在尽可能多的机器上运行。
(无论其价值如何,你can使用可变消息实现消息传递,只是没有人愿意这样做,因为线程在不锁定消息的情况下无法对消息执行任何操作 - 我们已经知道这充满了问题。因此,当您使用消息传递并发时,不可变是默认的方式。)
尽管其水平非常高并且掩盖了许多实际实现细节,但上述原则正是 Google 的 MapReduce 可以无限扩展的方式。
也可以看看:http://www.defmacro.org/ramblings/fp.html http://www.defmacro.org/ramblings/fp.html