是否可以在 CoffeeScript(或纯 JavaScript)中定义我自己的中缀函数/运算符?例如我想打电话
a foo b
或者
a `foo` b
代替
a.foo b
或者,当 foo 是全局函数时,
foo a, b
有没有办法做到这一点?
是否可以在 CoffeeScript(或纯 JavaScript)中定义我自己的中缀函数/运算符?例如我想打电话
a foo b
或者
a `foo` b
代替
a.foo b
或者,当 foo 是全局函数时,
foo a, b
有没有办法做到这一点?
ES6 启用了一种非常 Haskell/Lambda 演算的做事方式。
给定一个乘法函数:
const multiply = a => b => (a * b)
您可以使用部分应用程序定义一个加倍函数(省略一个参数):
const double = multiply (2)
你可以用它自己组合双重函数,创建一个四重函数:
const compose = (f, g) => x => f(g(x))
const quadruple = compose (double, double)
但实际上,如果您更喜欢中缀符号怎么办?正如 Steve Ladavich 所说,您确实需要扩展原型。
但我认为使用数组表示法而不是点表示法可以做得更优雅。
让我们使用函数组合的官方符号“∘”:
Function.prototype['∘'] = function(f){
return x => this(f(x))
}
const multiply = a => b => (a * b)
const double = multiply (2)
const doublethreetimes = (double) ['∘'] (double) ['∘'] (double)
console.log(doublethreetimes(3));
你可以使用 sweet.js。看:
Sweet.js 使用宏扩展了 Javascript。
它就像一个预处理器。
Javascript 不包含用于部分应用的函数或部分的中缀表示法。但它附带了更高阶的函数,这让我们几乎可以做所有事情:
// applicator for infix notation
const $ = (x, f, y) => f(x) (y);
// for left section
const $_ = (x, f) => f(x);
// for right section
const _$ = (f, y) => x => f(x) (y);
// non-commutative operator function
const sub = x => y => x - y;
// application
console.log(
$(2, sub, 3), // -1
$_(2, sub) (3), // -1
_$(sub, 3) (2) // -1
);
如您所见,在这种情况下,我更喜欢视觉名称$
和$_
文本_$
名称。这是你能得到的最好的——至少对于纯 Javascript/ES2015。
这绝对不是中缀符号,但它有点接近:/
let plus = function(a,b){return a+b};
let a = 3;
let b = 5;
let c = a._(plus).b // 8
我认为没有人真正想要使用这个“符号”,因为它非常难看,但我认为可能可以进行一些调整以使其看起来不同或更好(可能在这里使用这个答案来“调用函数" 不带括号)。
中缀函数
// Add to prototype so that it's always there for you
Object.prototype._ = function(binaryOperator){
// The first operand is captured in the this keyword
let operand1 = this;
// Use a proxy to capture the second operand with "get"
// Note that the first operand and the applied function
// are stored in the get function's closure, since operand2
// is just a string, for eval(operand2) to be in scope,
// the value for operand2 must be defined globally
return new Proxy({},{
get: function(obj, operand2){
return binaryOperator(operand1, eval(operand2))
}
})
}
另请注意,第二个操作数作为字符串传递并评估eval
以获取其值。正因为如此,我认为只要操作数(又名“b”)的值未在全局范围内定义,代码就会中断。