可以定义一个中缀函数吗



是否可以在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));

实际上添加这个作为答案:,这是不可能的。

这在香草JS中是不可能的。

这在CoffeeScript中是不可能的。

您可以使用sweet.js。请参阅:

  1. http://sweetjs.org/doc/main/sweet.html#infix-宏
  2. http://sweetjs.org/doc/main/sweet.html#custom-操作员

Sweet.js用宏扩展了Javascript。

它的作用就像一个预处理器。

这绝对不是中缀表示法,但它有点接近:/

let plus = function(a,b){return a+b};
let a = 3;
let b = 5;
let c = a._(plus).b // 8

我不认为有人会真的想使用这个"符号",因为它很难看,但我认为可能有一些调整可以让它看起来不同或更好(可能在这里使用这个答案来"调用函数"而不使用括号)。

Infix函数

// 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")的值没有全局定义,代码就会中断。

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。

您可以通过函数currying来接近:

const $ = (a) => (f) => f(a);
const plus = (a) => (b) => (a+b);
const twoPlusThree = $ (2) (plus) (3);

但我仍然没有想出一个巧妙的方法来构建这个结构。

相关内容

  • 没有找到相关文章

最新更新