如果这与JavaScript中的函数式编程有关,在我的示例中,我将使用Ramda。
虽然工作中的每个人都已经完全接受了函数式编程,但也有很多关于如何“正确”实现它的讨论。
这两个函数将执行完全相同的任务:获取一个列表并返回一个新列表,其中所有字符串都已被裁剪。
// data-centric style
const trimList = list => R.map(R.trim, list);// point-free style
const trimList = R.map(R.trim);到目前一切尚好。但是,使用一个更复杂的示例,这两种样式之间的差别是惊人的:获取一个列表并返回一个新列表,其中所有字符串都等于在对象中找到的属性。
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"]// data-centric style
const myFilter = (opts, key, list) => {
var predicate = R.equals(opts[key]);
return R.filter(predicate, list);
};// 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)]);除了可读性和个人品味之外,是否有可靠的证据表明,在某些情况下,一种风格比另一种风格更适合?
发布于 2018-12-12 18:40:52
我不知道有任何证据表明一种风格比另一种风格更有优势。但是,在编程史上,有一个明显的趋势是向更高的抽象.以及同样明确的抵制这一趋势的历史。从Assembly迁移到Fortran或LISP是在抽象堆栈上的移动。另一种是使用SQL而不是定制B树检索。在我看来,无论是在像Javascript这样的语言中还是在不断变化的编程语言环境中,转向FP都是一个类似的举动。
但这在很大程度上与比这个句法决策更基本的元素有关:等式推理意味着我们可以在更坚实的基础上构建自己的抽象。所以纯洁性和永恒性是必不可少的;没有点只是美好的。
话虽如此,但它往往更简单。这很重要。更简单的代码更容易阅读,更易于修改。请注意,我区分了简单和easy --这是经典里奇·希基的讲话中阐述的区别。那些刚接触到这种风格的人往往会发现它更令人困惑;厌恶下一代语言和他们所有同类的组装程序员也会感到困惑。
通过不定义中间变量,甚至不指定可以推断的参数,我们就可以大大提高简单性。
很难说这是:
const foo = (arg) => {
const qux = baz(arg)
return bar(qux)
}甚至这个:
const foo = (arg) => bar(baz(arg))比这更简单:
const foo = compose(bar, baz)这是因为,虽然这三者都涉及到这些概念:
第二条补充说:
第一个版本有:
return语句而第三个只增加了
如果更简单意味着更少的概念交织在一起,那么无意义的版本就会更简单,即使对某些人来说它不那么熟悉。
最后,这很大程度上取决于可读性。比起编写代码,你花更多的时间阅读自己的代码。其他人花更多的时间读它。如果您编写的代码简单、可读性强,那么您已经为每个人提供了更好的体验。因此,在无点代码更具可读性的地方,请使用它。
但是,不要认为有必要删除每一个点来证明一个点。这很容易落入陷阱,试图使一切都没有意义,仅仅因为你可以。我们已经知道这是可能的,我们不需要看到血淋淋的细节。
发布于 2018-12-07 13:59:32
学术学期是eta转换。当您有一个带有冗余lambda抽象的函数时,如
const trim = s => s.trim();
const map = f => xs => xs.map(x => f(x));
const trimList = xs => map(trim) (xs); // lambda redundancy您可以通过eta简化简单地去掉最后一个lamdba抽象:
const trimList = map(trim);当您广泛使用eta缩减时,您将以无点样式结束。然而,这两个版本在功能范式中都是非常好的。这只是风格的问题。
实际上,在Javascript中使用eta抽象(与eta缩减相反)至少有两个原因:
map = f => xs => xs.map(x => f(x))所做的那样recur = f => x => f(recur(f)) (x)中那样立即计算表达式/语句(惰性计算效果)发布于 2018-12-23 22:07:23
有一些好的答案,在我看来,混合这两种风格是可行的。
最后一个没有点的样式示例有点让人困惑,您可以减少它的混淆:
const myFilter = converge(
filter,
[compose(equals , flip(prop)) , nthArg(2)]
)https://stackoverflow.com/questions/53670665
复制相似问题