cus*_*der 3 javascript functional-programming pointfree ramda.js
如果重要的话,这是关于JavaScript中的函数式编程,在我的例子中,我将使用Ramda.
虽然工作中的每个人都完全接受了函数式编程,但还有很多关于如何"正确"地进行讨论的讨论.
这两个函数将完全相同:获取一个列表并返回一个新列表,其中所有字符串都已被修剪.
// data-centric style
const trimList = list => R.map(R.trim, list);
Run Code Online (Sandbox Code Playgroud)
// point-free style
const trimList = R.map(R.trim);
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.然而,对于更复杂的示例,两种样式之间的差异是惊人的:获取列表并返回一个新列表,其中所有字符串都等于在对象中找到的属性.
var opts = {a: 'foo', b: 'bar', c: 'baz'};
var list = ['foo', 'foo', 'bar', 'foo', 'baz', 'bar'];
myFilter(opts, 'a', list); //=> ["foo", "foo", "foo"]
myFilter(opts, 'b', list); //=> ["bar", "bar"]
Run Code Online (Sandbox Code Playgroud)
// data-centric style
const myFilter = (opts, key, list) => {
var predicate = R.equals(opts[key]);
return R.filter(predicate, list);
};
Run Code Online (Sandbox Code Playgroud)
// point-free style
const myFilter = R.converge(
R.filter, [
R.converge(
R.compose(R.equals, R.prop), [
R.nthArg(1),
R.nthArg(0)]),
R.nthArg(2)]);
Run Code Online (Sandbox Code Playgroud)
除了可读性和个人品味外,是否还有可靠的证据表明在某些情况下一种风格比另一种更适合?
我知道没有证据表明一种风格优于另一种风格。但是在编程的历史上有一个明显的趋势是朝着更高的抽象发展……并且同样明显地反对这种趋势。从汇编到 Fortran 或 LISP 的转变是在抽象堆栈上的提升。使用 SQL 而不是定制的 B 树检索是另一种。向 FP 的转变,无论是在 Javascript 这样的语言中还是在不断变化的编程语言环境中,在我看来都是类似的举动。
但其中大部分与比这个句法决定更基本的元素有关:等式推理意味着我们可以在更坚实的基础上构建我们自己的抽象。所以纯度和不变性是必不可少的;点免费只是很好。
也就是说,它通常更简单。这很重要。更简单的代码更容易阅读,更容易修改。请注意,我区分了simple和easy-Rich Hickey的经典演讲中阐明的区别。那些刚接触这种风格的人往往会发现它更令人困惑;憎恶下一代语言及其同类的汇编程序员也是如此。
通过不定义中间变量,甚至不指定可以推断的参数,我们可以显着提高简单性。
很难说:
const foo = (arg) => {
const qux = baz(arg)
return bar(qux)
}
Run Code Online (Sandbox Code Playgroud)
甚至这个:
const foo = (arg) => bar(baz(arg))
Run Code Online (Sandbox Code Playgroud)
比这更简单:
const foo = compose(bar, baz)
Run Code Online (Sandbox Code Playgroud)
那是因为虽然所有三个都涉及这些概念:
第二个还补充说:
第一个版本有:
return声明而第三个只添加
如果更简单意味着纠缠的概念更少,那么无点版本更简单,即使它对某些人来说不太熟悉。
最后,其中大部分归结为可读性。与编写代码相比,您花在阅读自己代码上的时间更多。任何人都花了很多更多的时间阅读。如果您编写的代码简单易读,那么每个人的体验都会变得更好。因此,在无点代码更具可读性的地方,使用它。
但是不要觉得有必要删除每一点,以证明一个观点。很容易陷入仅仅因为你可以而试图让一切都变得毫无意义的陷阱。我们已经知道这是可能的;我们不需要看到血腥的细节。
小智 5
学术术语是eta转换.当你有一个带冗余lambda抽象的函数时
const trim = s => s.trim();
const map = f => xs => xs.map(x => f(x));
const trimList = xs => map(trim) (xs); // lambda redundancy
Run Code Online (Sandbox Code Playgroud)
你可以通过eta减少简单地删除最后的lamdba抽象:
const trimList = map(trim);
Run Code Online (Sandbox Code Playgroud)
当你广泛使用eta减少时,你最终会得到无点风格.但是,这两个版本在功能范例中都非常精细.这只是一种风格问题.
实际上,在Javascript中使用eta抽象(与eta减少相反)至少有两个原因:
map = f => xs => xs.map(x => f(x))recur = f => x => f(recur(f)) (x)| 归档时间: |
|
| 查看次数: |
293 次 |
| 最近记录: |