Defining function that takes arguments in prefix notation scala

时间:2017-04-06 17:01:46

标签: scala

I want to do define a function in scala that takes arguments in prefix notation:

sum i1 i2 i3 ... in 

and returns and Int with the sum of all the provided args. Note that I don't want to use parentheses when I call the function.

My goal is to do something like sum i1 plus i2 but I want to start with something simpler first.

NOTE: You might say there is not purpose for doing this if you can use the + operator, but my goal is not to add numbers. I am just using this as a generic learning tool.

1 个答案:

答案 0 :(得分:1)

在回答这个问题之前,我想指出scala首先是面向对象的语言,所以你想要定义的大多数函数实际上都是特定对象的方法。对于任何课程T(不一定是Int),我会更一般地给出答案。我还假设您想要在值列表中执行的操作可以迭代完成,因此sum 1 2 3实际上与sum (sum 1 2) 3相同,因此我假设您有一些reducer函数f: (T, T) => T

定义中缀运算符,以便您可以执行类似

的操作
i1 and i2 and i3 ...

你只需要定义一个方法

and(that: T): T = f(this, that)

在您的班级T上。如果您无法为类型添加方法(例如,如果您使用的是lib中的类,或Int),则可以使用implicit wrapper类型:

implicit class ReducibleT(i: T) {
  def and(j: T): f(i, j)
}

使用中缀转发器定义前缀运算符,例如

sum i1 and i2 and i3 ...
看来你做不到!这是因为像ident1 ident2 ident3这样的表达式总是(据我所知)被解析为ident1.ident2(ident3),(除非ident2以冒号结束,在这种情况下它被反转)。但是,您无法为类型T定义所有可能标识符的方法(例如,对于Int,您无法在对象上定义方法1,因此sum 1 2具有没有任何意义),所以这是不可能的。

然而,你几乎可以做得很好:

sum (i1) and i2 and i3 ...

在这种情况下,parens表示函数调用,因此它实际调用对象and上的方法sum(i1)(实际上是sum.apply(i1),因为所有函数都是对象apply特殊方法def sum(i: T) = i implicit class ReducibleT(i: T) { def and(j: T): f(i, j) } )。这是一个例子:

sum i1 i2 i3 ...

现在,如果您理解了第二种情况,那么您无法做到就不足为奇了

sum (i1) (i2) (i3)

任一。我们必须限制自己

def sum(i: T) = i

implicit class ReducibleT(i: T) {
  def apply(j: T) = f(i, j)
}

使用以下内容:

implicit def tAsReducer(i: T): T => T = f(i, _)

或者,为了混合一点,您可以使用隐式转换为函数:

"ja.v_,a"