[译]柯里化有用吗?

2019-03-01 11:27:09 浏览数 (2)

作者:Hugh FD Jackson 原标题: 《Does Curry Help?》 原文地址:https://hughfdjackson.com/javascript/does-curry-help/ 译者:the5fire 注:这一篇应该跟上一篇一起读 [译]为什么柯里化是有用的

柯里化有用吗?

在两年半前我写了这篇文章《为什么柯里化是有用的》 ——一些关于在JavaScript中使用柯里化函数的赞美之言。这篇文章轻松成为阅读量最大的一篇,每个月给我带来许多读者。

但是随着时间流逝,时间发生了变化,我也是。依靠这个技巧让代码变得更有表达力仍旧是一个好的想法吗?

我并不是那么确信。

“这不是Haskell”

当我一开始提出要把柯里化作为一个新增功能放到我们工作中的工具箱中时,我的同事William(不是真名)坚决坚持:

这不是Haskell!

我同样固执地争论道我们需要吸取好的技巧无论是在什么地方发现的,不论源码有多么晦涩。(后来)我花了一段时间才意识到他是多么正确。

简单或许很重要,但是易用仍然重要

用他的话来说就是——“简单致使易用”,Rich Hickey(the5fire注:Clojure作者)鼓励把简单和易用的理念区分来看。

“简单”,他指出,意味着这些关注点不是纠缠在一起的(the5fire注:concerns表示关注点,在软件设计上有一个原则是SoC(分离关注点-Separation of concerns),个人理解就是对关注点(功能点)做解耦)。“易用”,表示有些事情跟你当前的理解是一致的。

但是完美简单的代码 —— 就是那些不需要跟任何关注点纠缠的代码 —— 如果用起来特别困难,那对团队来说没什么好处。你需要权衡利弊;足够简单能防止bug产生并且能满足生存和发展需求,足够易用能够让你的团队不需要快速学习新技术就能够理解它。

Haskell和JavaScript的第一点不同是,在Haskell中,柯里化是内置的概念。这是入门的门槛——因此所有的Haskell开发者都知道这个概念。

在JavaScript中,这个概念是外来物。我所交流过的大多数开发者都发现它难以领会并且(代码)难以阅读。当然你可以辩称它能够使代码简单,但这不足以让大多数团队受益。

故障和它们的起源

Haskell有类型系统能够在编译阶段捕获大多数的bug。当我被卡住时,我经常编译我明知会出错的程序 - 然后让编译错误指导我进行下一步。

JavsScript使用截然相反的做法,执行不受编译时限制。从积极方面来说这相当灵活。从消极方面来说错误出现的地方和它们的起因相隔甚远。

提供一个携带更少参数的柯里化函数是容易犯的错误,并且它可能经常在代码相对较晚的阶段才会引起错误。

代码语言:javascript复制
var curry = require('curry');
var add = curry(function(a, b, c){ return a   b   c });

// 哎呀 —— threeP不像我们预期的那样是值为3的Promise对象
// 而是一个一元函数的Promise对象 (the5fire注: 这个一元函数就是柯里化返回的被局部赋值的函数,其中a被赋值为2,b被赋值为1,c是新返回函数的参数)
// 使用了threeP函数的代码可能最终发现了这个错误,然后抛出错误。
var threeP = Promise.resolve(1)
  .then(add(2))

嵌入在大多数应用的更复杂的代码中,容易引起你或者你的同事浪费几个小时来查找这个神秘函数的出处。

箭头函数

几个月之前,Josh Habdas评论了那篇文章:

代码语言:javascript复制
考虑到[ES2015]中的箭头函数,示例中获取数据的代码可以进行明显的简化。

他的话没毛病。

《为什么柯里化是有用的》这篇文章的结尾是清晰的,毫无疑问的。它体现了通过Promise和一些工具函数来展开用户文章列表里的标题。

代码语言:javascript复制
fetchFromServer()
    .then(JSON.parse)
    .then(get('posts'))
    .then(map(get('title')))

在上一篇文章,我探索了通过箭头函数能够移除多少引用,并且使用新的语法特性替换一开始通过使用柯里化函数获取的好处:

代码语言:javascript复制
fetchFromServer()
    .then(JSON.parse)
    .then(data => data.posts)
    .then(posts => posts.map(p => p.title))

我错了吗?

我比其他太空步比赛的选手退的更快吗?是的,就是这样。 (the5fire注:这里是隐喻吗,没懂。原文:Am I back-peddling faster than a contestant in a moonwalk race? Yup, pretty much.)

然而我依然相信我在这篇文章《为什么柯里化是有用的》中所关注的好处是存在的,这篇文章没有花费足够多的注意力在在实际使用这些技巧是带来的问题。现在ES2015已经到了,在大部分JavaScript的环境中使用箭头函数是更加自然的减少视觉污染的方式。

如今,我在JavaScript中很少使用柯里化了。

然而我依然试着挑战极限,在过去的两年半中,我看到了近距离与人会面所带来的价值。 (the5fire注: 最后一句是说跟人见面还是说代码,也是隐喻吗。原文:And while I still try to push the envelope, over the last 2 and a half years, I’ve seen the value of meeting people much closer to where they are.)

相关资料: simple-made-easy slide

0 人点赞