有人可以澄清一下 Joel On Software 引用的意思吗:(功能性程序没有副作用)

2024-04-01

我正在读书乔尔安软件 http://www.joelonsoftware.com/今天又遇到了这个报价 http://www.joelonsoftware.com/articles/ThePerilsofJavaSchools.html:

不了解功能 编程,你不能发明 MapReduce,该算法使得 谷歌的可扩展性如此之大。这 术语“Map”和“Reduce”来自 Lisp 和函数式编程。映射减少 回想起来,对任何人来说都是显而易见的 谁还记得他们的 纯函数式程序具有的 6.001 等效编程类 没有副作用,因此微不足道 可并行化。

当他说函数式程序没有副作用时,他是什么意思?这如何使并行化变得微不足道?


他说的是什么意思 函数式程序没有边 影响?

大多数人认为编程就是创建变量、为其赋值、将内容添加到列表等。变量“变化”,因此得名。

函数式编程是一种消除变量的程序设计风格——一切都是常量或只读。

当 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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

有人可以澄清一下 Joel On Software 引用的意思吗:(功能性程序没有副作用) 的相关文章

  • 如何在 Perl 中以函数式风格进行编码?

    你如何 have a sub返回一个sub or 将文本作为代码执行 in Perl 另外 如何拥有匿名函数存储状态 子返回子作为coderef example 1 return a sub that is defined inline s
  • F# 检查列表是否为空

    作为 F 新手 我正在尝试实现一个简单的函数 该函数将索引和列表作为参数 然后返回给定索引的列表值 let rec getElementAtIndex index int list a list match index list with
  • 如何判断何时创建新组件?

    我一直在寻找背后的逻辑当有人在 AngularJS Angular 上的 Web 应用程序中创建新组件时但我认为这更通用 可能适用于所有基于组件的前端框架 我知道有像这样的一些原则应该是抽象的和可重用的但例如我在角度文档中看到 每个单独的路
  • 使用fold_left/right反转OCaml中的列表

    更新 解决方案 感谢 jacobm 的帮助 我想出了一个解决方案 Folding Recursion let reverse list 3 theList List fold left fun element recursive call
  • 使用 RxJava 限制吞吐量

    我现在遇到的情况很难解释 所以我会写一个更简单的版本来解释这个问题 我有一个Observable from 它发出一系列由ArrayList文件数量 所有这些文件都应上传到服务器 为此 我有一个函数可以完成这项工作并返回一个Observab
  • 通过消除嵌套的 for 循环来改进此代码

    R 包corrplot除其他内容外 还包含这个漂亮的功能 cor mtest lt function mat conf level 0 95 mat lt as matrix mat n lt ncol mat p mat lt lowCI
  • 使用 Reader Monad 进行依赖注入

    我最近看到了谈话极其简单的依赖注入 http www youtube com watch v ZasXwtTRkio and 无需体操的依赖注入 http vimeo com 44502327关于 Monads 的 DI 并留下了深刻的印象
  • 我为什么要学习 Lisp? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • F# 中的动态编程

    实现解决问题的动态规划算法的最优雅的方法是什么子问题重叠的问题 http en wikipedia org wiki Overlapping subproblem 在命令式编程中 人们通常会创建一个按问题大小索引的数组 至少在一维 然后算法
  • 对列表中的相邻元素进行分组

    假设我想编写一个函数来执行此操作 输入 1 1 3 3 4 2 2 5 6 6 输出 1 1 3 3 4 2 2 5 6 6 它将相同的相邻元素分组 这个方法的名称应该是什么 此操作有标准名称吗 In 1 1 3 3 4 2 2 5 6 6
  • 从函数返回随机值是副作用吗?

    我当时正在编写一些 F 代码 并且正在编写一个从一组字符串中返回随机字符串的函数 假设我有这样的事情 open System let a a b c d let rstring arr string let r new Random arr
  • Java泛型 - 实现像map这样的高阶函数

    我决定用 Java 编写一些常见的高阶函数 map filter reduce 等 这些函数通过泛型实现类型安全 但我在一个特定函数中遇到通配符匹配问题 为了完整起见 函子接口是这样的 The interface containing th
  • 如何使用 FS2 中的分类器函数对对象进行分组?

    我有一个无序的流measurements 我想将其分组为固定大小的批次 以便以后可以有效地保留它们 val measurements for id lt Seq foo bar baz value lt 1 to 5 yield id va
  • 如何使用 rxpy/rxjs 延迟事件发射?

    我有两个事件流 一个来自电感环路 另一个来自网络摄像机 汽车将驶过环路 然后撞上相机 如果事件彼此相差在 N 毫秒内 汽车总是会首先进入循环 我想将它们组合起来 但我也希望每个流中不匹配的事件 硬件可能会失败 全部合并到单个流中 像这样的事
  • C++0x (C++11) 作为函数式语言?

    我想知道 C 0x C 11 带有 lambda 和完美转发 是否是一种函数式语言 的超集 函数式语言有什么特性是 C 所没有的吗 函数式编程范式将计算建模为集合之间的关系 因此本质上是声明性的 然而 在实践中 我们通常认为函数是命令式的
  • 使用 Either 处理 Scala 代码中的故障

    Optionmonad 是 Scala 中处理有或无事物的一种很好的表达方式 但是 如果在 什么也没发生 时需要记录一条消息怎么办 根据 Scala API 文档 Either 类型通常用作 scala Option where Left
  • 如何将函数转换为点自由形式?

    假设我有一个 JavaScript 函数 function f x return a b x c x 我如何将其转换为无点函数 通过组合函数 还有关于这方面的更多信息的资源吗 一般来说 当您将函数转变为无点风格时 没有简单的规则可遵循 要么
  • 副作用是纯函数中找不到的一切吗?

    可以肯定地说 以下二分法成立 每个给定的函数是 要么纯粹 或有副作用 如果是这样 函数的 副作用就是纯函数中找不到的任何东西 这很大程度上取决于您选择的定义 可以公平地说 函数是pure or impure 纯函数始终返回相同的结果并且不会
  • 存在函数依赖关系时类型推断如何工作

    考虑下面的代码 LANGUAGE MultiParamTypeClasses FlexibleInstances FunctionalDependencies UndecidableInstances FlexibleContexts cl
  • 为什么解析器组合器“seq”用“bind”和“return”定义?

    我正在读这个article http eprints nottingham ac uk 237 1 monparsing pdf关于解析器组合器并且不理解以下内容 他们说使用seq 见下文 导致解析器将嵌套元组作为结果 操作起来很混乱 se

随机推荐

  • 在 Android 中检测传入电子邮件通知

    android 中有传入电子邮件时我们可以检测到通知吗 有什么解决方案 教程或示例代码我可以尝试吗 Thanks 尝试实现NotificationListenerService 这是官方文档https developer android c
  • 我应该在将模型导入 Unity 之前在 Blender 中烘焙模型吗?

    正如标题所示 何时为 Blender 模型烘焙纹理以在手机游戏中使用它很重要 烘焙对性能有何好处 如果我没有烘烤它并且直接在游戏中的模型上使用纹理 会有什么问题吗 有Unity中的烘焙和blender中的烘焙 您的问题似乎是关于在将模型导入
  • MS Chart控件缩放MinSize问题

    我正在使用 MS Chart Control NET 3 5 WinForms C 实现散点图 我的 x 轴数据是 DateTime 并注意到我无法放大小于 1 天的分辨率 尽管按如下方式设置 ScaleView chart1 ChartA
  • 熊猫连接失败

    我正在尝试连接以下两个 csv 文件中的数据帧 df a https www dropbox com s slcu7o7yyottujl df current csv dl 0 df b https www dropbox com s la
  • 如何从文件字节开始在内存中创建 zip 文件?

    我尝试使用 C 在内存中创建一个 zip 文件 但结果是一个 zip 文件 其中包含损坏的文件 所有要压缩的文件都在数据库中 我存储字节 文件为 PDF 格式 我的代码如下 extract bytes and file name for e
  • Notification.addAction 在 Android O 中不起作用

    下面提到的代码适用于 Android O 版本以下的所有设备 对于安卓O addAction 方法不起作用 即按钮单击在 android O 中不起作用 任何帮助 将不胜感激 NotificationManager notification
  • MVC 自定义 ViewModel 和自动绑定

    我有一个自定义 ViewModel 定义为 public class SampleFormViewModel public SampleFormViewModel SelectList companies Widget widget Com
  • 为 iOS7 编译 PJSIP

    我正在尝试在 Mac 10 9 Xcode 5 0 上编译适用于 iOS 的 PJSIP2 1 0 但是我运行时遇到一些错误 configure iphone 以下是错误 configure iphone DEVPATH is not sp
  • Java正则表达式和转义元字符

    我正在尝试编写正则表达式来匹配嵌入在两个大括号之间的标记 例如 如果缓冲区Hello World 我想从字符串中获取 World 令牌 当我使用正则表达式时 eclipse 显示错误消息为 无效的转义序列 有效的是 b t n f r 谁能
  • 是否可以远程托管 Android 应用程序中使用的资源,使其只能由我的应用程序使用?

    基本上我想要实现的是托管一个 CSV 文件 我的应用程序将检索该文件并将其用作数据源来填充一些表 CSV 将使用最新数据进行更新 我预计应用程序会经常获取最新版本 以确保其中的数据是最新的 我的问题是是否可以确保此远程 CSV 资源仅由我的
  • PHP:我应该如何转义将进入 Javascript 字符串的字符串?

    我应该如何转义将要进入 Javascript 字符串的字符串 URL 编码 X str replace X use json encode 所以你可以做 page params array user logged in gt suer gt
  • 如何在另一个 Perl 脚本中使用变量?

    我知道如何在 Perl 中使用一个包到另一个包的变量 我正在尝试使用声明的全局变量test1 pl在另一个 Perl 脚本中test2 pl 我在用require加载 perl 文件 usr bin perl test1 pl use st
  • 使用 jquery .html() 插入 html

    我想将一大块 html 插入到预先存在的 td 我正在使用这个方法 td content html LOTS OF HTML CODE HERE 但这不起作用 我是菜鸟 有很多引用和 HTML 块内似乎破坏了它 这样做的正确方法是什么 我建
  • 为什么局部变量或临时变量的返回地址只是警告而不是错误?

    刚刚收到编译器针对此函数的警告 template
  • hapi.js - 404 路由 VS 静态文件路由

    我正在尝试将 Express 应用程序迁移到 hapi js 但我的路线遇到了问题 我只想要 2 GET 我的索引 以及所有不是 的内容重定向到 使用 Express 我有这个 static files app use express st
  • 没有这样的模块 JSQMessagesViewController

    我正在尝试导入 JSQMessagesViewController import JSQMessagesViewController 它给了我错误 没有这样的模块 我在网上看到很多人遇到这个问题 但我找不到解决方案 这是我的 Podfile
  • 如何从颜色推断形状的状态

    我已经形成了乐高立方体4x4形状 我试图推断图像内区域的状态 空 满以及颜色是黄色还是蓝色 为了简化我的工作 我添加了红色标记定义border由于相机有时会晃动 因此形状会受到影响 这是我试图检测的形状的清晰图像 由手机摄像头拍摄 编辑 请
  • Phonegap - 在启用自动方向的同时防止旋转?

    我正在重新发布我在 Google 群组中找到的其他人的问题 我也遇到了类似的问题 我有一个应用程序 要求所有内容都处于纵向 除了播放视频时 在 iOS 上 当视频播放传递到 Quicktime 播放器时 我希望视频能够以横向模式播放 目前
  • 获取正确的月份格式日期java

    有什么帮助吗 如何从 2014 01 10T09 41 16 000 0000 这样的字符串中获取正确的日期 我的代码是 String strDate 2014 01 10T09 41 16 000 0000 String day Stri
  • 有人可以澄清一下 Joel On Software 引用的意思吗:(功能性程序没有副作用)

    我正在读书乔尔安软件 http www joelonsoftware com 今天又遇到了这个报价 http www joelonsoftware com articles ThePerilsofJavaSchools html 不了解功能