Scala 自定义运算符(示例 abs)

Posted

技术标签:

【中文标题】Scala 自定义运算符(示例 abs)【英文标题】:Scala custom operator (example abs) 【发布时间】:2017-11-30 14:37:13 【问题描述】:

我知道 scala 允许对其默认运算符 (+, - ! etc.) 进行重载。是否可以定义自定义运算符并制作类似 |.| 的东西运算符,以便 | -3|计算结果为 3。或者定义像 ++++ 这样的运算符,使 a ++++ b 等于 a+3*b?

【问题讨论】:

【参考方案1】:

你应该看看scala operators documentation。

您可以轻松地制作 ++++ 运算符,而不是 |.|运算符。

scala 中的运算符只是具有非字母数字名称的函数。由于 scala 还支持将 a.f(b) 作为 a f b 调用,因此您可以实现第一个行为。例如:

case class A(v: Int) 
  def ++++(b: A): A = A(v + 3 * b.v)


val a = A(1)
val b = A(2)
a ++++ b
>> A(7)
a.++++(b) // just another way of doing the exact same call

如果您想将它添加到整数,您只需创建一个隐式类来添加它。

另一种选择是为运算符添加前缀,例如考虑使用 -a 来获得否定值。没有“第一个元素”可以将 - 应用到,而是 - 应用到 a(参见 this answer)。

例如:

case class A(v: Int) 
  def unary_!(): Int = -v

val a = A(3)
!a
>> -3

正在做|.|有两个问题:首先,运营商有两个部分,即它是分裂的。二是使用|

为了做一个两部分的操作符(比如!.!),你可能想要生成一些私有类型并从一个中返回它!然后用它作为另一个的输入来返回输出类型。

第二个问题是使用 |这是一个非法字符。查看this answer 获取合法字符列表

【讨论】:

| 是合法的,并且在您链接的答案中被列为合法。 你是对的,从答案看来它是合法的,但是,该特定字符似乎不起作用(至少在 REPL 中)我必须错过另一个限制。 嗯,对我来说,它作为一种方法正常工作:class A def |(int: Int) = int * 2; def ||(int: Int) = int * 3; def |||(int: Int) = int * 4 ; new A || 2 // returns 6。它不能作为 unary_| 工作,我相信只有 unary_-unary_! 支持作为前缀运算符。 问题是 OP 要求 |x|| 作为分隔符。它仍然可以完成,但不会笨拙。【参考方案2】:

一个扩展@assaf-mendelson答案的例子

case class Abs(a: Int) 
  def !(): Int = a.abs


implicit def toAbs(a: Int) = new 
  def unary_! : Abs = Abs(a)

然后

> val a = -3
a: Int = -3

> !a
res0: Abs = Abs(-3)

> !a!
res1: Int = 3

> val b = 12
b: Int = 12

> !b!
res2: Int = 12

> (!a!) + (!b!)
res3: Int = 15

我们不能将 abs 实现为 |a|,因为 unary_ 仅适用于 !~+-

【讨论】:

以上是关于Scala 自定义运算符(示例 abs)的主要内容,如果未能解决你的问题,请参考以下文章

scala 自定义实现枚举

ViennaCL 中的自定义线性运算符

编写scala版hive的自定义函数

通过自定义string类型来理解运算符重载

使用 Perl 6 自定义运算符

scala自定义隐式转换