首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在函数式编程中,选择无点样式与以数据为中心的样式是合适的吗?

在函数式编程中,选择无点样式与以数据为中心的样式是合适的吗?
EN

Stack Overflow用户
提问于 2018-12-07 13:33:26
回答 3查看 927关注 0票数 6

如果这与JavaScript中的函数式编程有关,在我的示例中,我将使用Ramda。

虽然工作中的每个人都已经完全接受了函数式编程,但也有很多关于如何“正确”实现它的讨论。

这两个函数将执行完全相同的任务:获取一个列表并返回一个新列表,其中所有字符串都已被裁剪。

代码语言:javascript
复制
// data-centric style
const trimList = list => R.map(R.trim, list);
代码语言:javascript
复制
// point-free style
const trimList = R.map(R.trim);

到目前一切尚好。但是,使用一个更复杂的示例,这两种样式之间的差别是惊人的:获取一个列表并返回一个新列表,其中所有字符串都等于在对象中找到的属性。

代码语言:javascript
复制
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"]
代码语言:javascript
复制
// data-centric style
const myFilter = (opts, key, list) => {
  var predicate = R.equals(opts[key]);
  return R.filter(predicate, list);
};
代码语言:javascript
复制
// 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)]);

除了可读性和个人品味之外,是否有可靠的证据表明,在某些情况下,一种风格比另一种风格更适合?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-12-12 18:40:52

我不知道有任何证据表明一种风格比另一种风格更有优势。但是,在编程史上,有一个明显的趋势是向更高的抽象.以及同样明确的抵制这一趋势的历史。从Assembly迁移到Fortran或LISP是在抽象堆栈上的移动。另一种是使用SQL而不是定制B树检索。在我看来,无论是在像Javascript这样的语言中还是在不断变化的编程语言环境中,转向FP都是一个类似的举动。

但这在很大程度上与比这个句法决策更基本的元素有关:等式推理意味着我们可以在更坚实的基础上构建自己的抽象。所以纯洁性和永恒性是必不可少的;没有点只是美好的。

话虽如此,但它往往更简单。这很重要。更简单的代码更容易阅读,更易于修改。请注意,我区分了简单easy --这是经典里奇·希基的讲话中阐述的区别。那些刚接触到这种风格的人往往会发现它更令人困惑;厌恶下一代语言和他们所有同类的组装程序员也会感到困惑。

通过不定义中间变量,甚至不指定可以推断的参数,我们就可以大大提高简单性。

很难说这是:

代码语言:javascript
复制
const foo = (arg) => {
  const qux = baz(arg)
  return bar(qux)
}

甚至这个:

代码语言:javascript
复制
const foo = (arg) => bar(baz(arg))

比这更简单:

代码语言:javascript
复制
const foo = compose(bar, baz)

这是因为,虽然这三者都涉及到这些概念:

  • 功能声明
  • 功能参考

第二条补充说:

  • 参数定义
  • 功能体
  • 功能应用
  • 函数调用嵌套

第一个版本有:

  • 参数定义
  • 功能体
  • 功能应用
  • 局部变量定义
  • 局部变量分配
  • return语句

而第三个只增加了

  • 功能组合

如果更简单意味着更少的概念交织在一起,那么无意义的版本就会更简单,即使对某些人来说它不那么熟悉。

最后,这很大程度上取决于可读性。比起编写代码,你花更多的时间阅读自己的代码。其他人花更多的时间读它。如果您编写的代码简单、可读性强,那么您已经为每个人提供了更好的体验。因此,在无点代码更具可读性的地方,请使用它。

但是,不要认为有必要删除每一个点来证明一个点。这很容易落入陷阱,试图使一切都没有意义,仅仅因为你可以。我们已经知道这是可能的,我们不需要看到血淋淋的细节。

票数 7
EN

Stack Overflow用户

发布于 2018-12-07 13:59:32

学术学期是eta转换。当您有一个带有冗余lambda抽象的函数时,如

代码语言:javascript
复制
const trim = s => s.trim();
const map = f => xs => xs.map(x => f(x));

const trimList = xs => map(trim) (xs); // lambda redundancy

您可以通过eta简化简单地去掉最后一个lamdba抽象:

代码语言:javascript
复制
const trimList = map(trim);

当您广泛使用eta缩减时,您将以无点样式结束。然而,这两个版本在功能范式中都是非常好的。这只是风格的问题。

实际上,在Javascript中使用eta抽象(与eta缩减相反)至少有两个原因:

  • 修复Javascript的多参数函数,就像我对map = f => xs => xs.map(x => f(x))所做的那样
  • 防止像在recur = f => x => f(recur(f)) (x)中那样立即计算表达式/语句(惰性计算效果)
票数 6
EN

Stack Overflow用户

发布于 2018-12-23 22:07:23

有一些好的答案,在我看来,混合这两种风格是可行的。

最后一个没有点的样式示例有点让人困惑,您可以减少它的混淆:

代码语言:javascript
复制
const myFilter = converge(
  filter,
  [compose(equals , flip(prop)) , nthArg(2)]
 )
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53670665

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档