将运算符分配给Scala中的变量

Gui*_*sco 1 scala operators

鉴于Scala中的这一代码:

val mapMerge : (Map[VertexId, Factor], Map[VertexId, Factor]) => Map[VertexId, Factor] = (d1, d2) => d1 ++ d2
Run Code Online (Sandbox Code Playgroud)

这可以缩短为:

val mapMerge : (Map[VertexId, Factor], Map[VertexId, Factor]) => Map[VertexId, Factor] = _ ++ _
Run Code Online (Sandbox Code Playgroud)

实际上代码的作用是重命名Map [VertexId,Factor]的operator ++,因此:有没有办法将该运算符赋值给变量?就像在这个想象中的例子一样:

val mapMerge : (Map[VertexId, Factor], Map[VertexId, Factor]) => Map[VertexId, Factor] = Map.++
Run Code Online (Sandbox Code Playgroud)

并且可能使用类型推断它就足够了

val mapMerge = Map[VertexId,Factor].++
Run Code Online (Sandbox Code Playgroud)

谢谢

Sar*_*sch 6

不幸的是,不,因为Scala中的"运算符"是实例方法 - 不是来自类型类的函数,比如Haskell.
在你写的时候_ ++ _,你正在创建一个带有未命名参数的新的2参数函数(lambda).这相当于(a, b) => a ++ b,相当于(a, b) => a.++(b),但不是(a, b) => SomeClass.++(a, b).

您可以使用隐式参数来模拟类型类(请参阅"scala中的类型类"演示文稿)

你可以传递"运算符"之类的函数 - 它们不是真正的运算符.你可以拥有看起来相同的运营商.看这个例子:

object Main {

    trait Concat[A] { def ++ (x: A, y: A): A }
    implicit object IntConcat extends Concat[Int] {
        override def ++ (x: Int, y: Int): Int = (x.toString + y.toString).toInt
    }

    implicit class ConcatOperators[A: Concat](x: A) {
        def ++ (y: A) = implicitly[Concat[A]].++(x, y)
    }

    def main(args: Array[String]): Unit = {
        val a = 1234
        val b = 765

        val c = a ++ b // Instance method from ConcatOperators — can be used with infix notation like other built-in "operators"

        println(c)

        val d = highOrderTest(a, b)(IntConcat.++) // 2-argument method from the typeclass instance

        println(d)
        // both calls to println print "1234765"
    }

    def highOrderTest[A](x: A, y: A)(fun: (A, A) => A) = fun(x, y)

}
Run Code Online (Sandbox Code Playgroud)

这里我们定义Concat类型类并为Int创建一个实现,我们在类型类中使用类似运算符的名称.

因为你可以为任何类型实现一个类型类,你可以使用任何类型的这种技巧 - 但这需要编写相当多的支持代码,有时它不值得结果.