函数式编程:如何正确组合成员提取运算符?



JavaScript 中的一个特性似乎使我能够避开"正确"的方式。

与其写d.food.bar还能够写d["foo"]d["bar"]

在大多数使用场景中,任何一种形式都可以,但在下面的代码中

function f(myscale, foo_or_bar) {
blah.attr(myscale(d => d[foo_or_bar]));
}
f(foo_scale, "foo");
f(bar_scale, "bar");

我能够发送一个字符串来指示应该访问一个或另一个成员。

当然,这里我只有一个语句(blah.attr),它不保证定义/使用函数,但在实践中它更实质性,并且确实保证了一个共同的定义。

事实上,上面的代码看起来很糟糕,以至于发送布尔标志is_it_foo并编写一个if语句以在d.food.bar之间进行选择不会更糟。

组合两条线的正确(函数式编程)方法是什么

blah.attr(foo_scale(d => d.foo));
blah.attr(bar_scale(d => d.bar));

合二为一?

(我已经看到了在交换两个参数的同时发送函数的技巧;但正如你从这个问题中可以看出的那样,我还没有在野外掌握这项技术,甚至可能在理论上也没有掌握

更新

我基本上是在寻找一个LispScheme专家,然后他选择了JavaScript。对于这个人来说,这个问题将是一个琐碎而即时的练习。如果像我一样,你的引力仍然在C++/Java世界中,请和我一起等待有人来阐明。(对于"关闭"的选民,如果 Scheme/Lisp 的人也表示这个问题没有意义,并且传递字符串来提取成员是完全可以的,我会很乐意删除这个问题。

与其将属性名称作为字符串传递,不如将属性 getter 函数作为参数传递给f

function f(myscale, get) {
blah.attr(myscale(get));
}
f(foo_scale, d => d.foo);
f(bar_scale, d => d.bar);

对于每个键foo如果你有一个唯一的映射器函数foo_scale,那么你目前的做法是正确的方法:

blah.attr(foo_scale(d => d.foo);
blah.attr(bar_scale(d => d.bar);

这更像是一种代码设计模式,而不是Javascript功能。因为这不仅会增强代码的可读性,还可以让你随意改变任何键的功能。

但是假设你所有的键都映射到一个映射器函数scale,你可以这样做:

const keys = ["foo", "bar"]
keys.forEach((key) => {
blah.attr1(scale(d => d[foo_or_bar]);
blah.attr2(scale2(d => d[foo_or_bar]);
blah.attr3(scale3(d => d[foo_or_bar]);
})

理想情况下,这是一个很好的模式,如果您能够将常见模式概括为单个方法,则可以使用它scale

最新更新