Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
270 views
in Technique[技术] by (71.8m points)

javascript - When is it appropriate to choose point-free style vs a data-centric style in functional programming?

In case it matters this is about functional programming in JavaScript and in my examples I’ll be using 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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The academic term is eta conversion. When you have a function with redundant lambda abstraction like

const trim = s => s.trim();
const map = f => xs => xs.map(x => f(x));

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

you can simply strip the last lamdba abstraction by eta reduction:

const trimList = map(trim);

When you use eta reduction extensively, you end up with point free style. However, both versions are perfectly fine in the functional paradigm. It's just a matter of style.

Actually, there are at least two reasons to use eta abstraction (the opposite of eta reduction) in Javascript:

  • to fix Javascript's multi argument functions like I did with map = f => xs => xs.map(x => f(x))
  • to prevent immediate evaluation of expressions/statements (lazy evaluation effect) as in recur = f => x => f(recur(f)) (x)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...