何时在函数式编程中选择无点样式与以数据为中心的样式是否合适? [英] When is it appropriate to choose point-free style vs a data-centric style in functional programming?

查看:112
本文介绍了何时在函数式编程中选择无点样式与以数据为中心的样式是否合适?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果重要的是这是关于JavaScript中的函数式编程,在我的例子中我将使用Ramda。

虽然每个人都在工作已完全接受函数式编程,还有很多关于如何正确执行它的讨论。

While everybody at work has fully embraced functional programming, there’s also a lot of discussions around how to do it "right".

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

These two functions will do exactly the same thing: take a list and return a new list in which all strings have been trimmed.

// data-centric style
const trimList = list => R.map(R.trim, list);



// point-free style
const trimList = R.map(R.trim);

到目前为止一切顺利。然而,对于一个更复杂的示例,两种样式之间的差异是惊人的:获取一个列表并返回一个新列表,其中所有字符串都等于在对象中找到的属性。

So far so good. However with a more complex example, the difference between the two styles is striking: take a list and return a new list in which all strings are equal to a property found in an object.

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)]);

除了可读性和个人品味外,是否有任何可靠的证据表明一种风格比其他在某些情况下?

Besides readability and personal taste, are there any reliable evidences to suggest that one style is better suited than the other in some circumstances?

推荐答案

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

I know of no evidence that demonstrates advantages of one style over the other. But there is a clear trend in the history of programming towards higher abstractions... and an equally clear history of resistance to this trend. A move from Assembly to Fortran or LISP was a move up the abstraction stack. The use of SQL rather than bespoke B-tree retrievals was a another. The move to FP, both within a language like Javascript and in the changing landscape of programming languages, is to my mind a similar move.

但其中大部分都要做使用比这个句法决策更基本的元素:等式推理意味着我们可以在更稳固的基础上构建我们自己的抽象。因此,纯度和不变性至关重要;无点的只是很好。

But much of that has to do with elements more fundamental than this syntactic decision: equational reasoning means that we can build our own abstractions on top of more solid footing. So purity and immutability are essential; point-free is merely nice to have.

这就是说,它通常更简单。这很重要。更简单的代码更易于阅读,更易于修改。请注意,我区分简单简单 - 经典 Rich Hickey的讲话。对风格不熟悉的人往往会感到更加困惑;那些厌恶下一代语言及其所有类型的汇编程序员也是如此。

That said, it is often simpler. And that is important. Simpler code is easier to read, easier to modify. Note that I distinguish between simple and easy -- the distinction articulated in the classic talk by Rich Hickey. Those new to the style will often find it more confusing; so too the assembly programmers who abhorred the next generation of language and all their ilk.

通过不定义中间变量,甚至不指定可以推断的参数,我们可以显着提高了简洁性。

By not defining intermediate variables, by not even specifying arguments that can be inferred, we can significantly improve simplicity.

这很难说:

const foo = (arg) => {
  const qux = baz(arg)
  return bar(qux)
}

甚至是这样:

const foo = (arg) => bar(baz(arg))

比这简单:

const foo = compose(bar, baz)

这是因为虽然所有三个都涉及这些概念:

And that's because while all three involve these notions:


  • 函数声明

  • 函数参考

第二个还添加:


  • 参数定义

  • 函数体

  • 函数应用程序

  • 函数调用的嵌套

  • argument definition
  • function body
  • function application
  • nesting of function calls

且第一个版本有:


  • 参数定义

  • 函数体

  • 函数应用程序

  • 局部变量定义

  • 局部变量作业

  • 返回声明

  • argument definition
  • function body
  • function application
  • local variable definition
  • local variable assignment
  • the return statement

而第三个只添加


  • 功能组成

如果简单意味着缠绕的概念较少,则t他的无点版本更简单,即使它对某些人不太熟悉。

If simpler means having fewer notions entwined, the point-free version is simpler, even if it's less familiar to some people.

最后,大部分内容归结为可读性。与编写代码相比,您花费更多时间阅读自己的代码。其他人花了很多时间 更多时间阅读它。如果您编写的代码简单易读,那么您的体验对每个人来说都会更好。因此,在无点代码更易读的情况下,使用它。

In the end, much of this comes down to readability. You spend more time reading your own code more than you do writing it. Anyone else spends a lot more time reading it. If you write code that it is simple and readable, you've made the experience much better for everyone. So where point-free code is more readable, use it.

但是没有必要删除每个点,以便咳嗽,证明一点。很容易陷入试图让所有事情都无点无关的陷阱,因为你可以。我们已经知道这是可能的;我们不需要看到血淋淋的细节。

But don't find it necessary to remove every point in order to, ahem, prove a point. It's easy to fall into the trap of trying to make everything point-free just because you can. We already know that it's possible; we don't need to see the gory details.

这篇关于何时在函数式编程中选择无点样式与以数据为中心的样式是否合适?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆