如何将不同的 return 类型分配给 Scala 中的函数?

How can assign different return types to a function in Scala?

我正在尝试编写一个函数,它应该根据输入 return 不同的对。我已经为我的特定用途覆盖了 Scala 中的“+ - / *”。每一个(+、-、*、/)都有基于输入的三种实现。我将 RDD 和 Float 作为输入,因此它可以是 RDD 和 RDD、Float 和 RDD、Float 和 Float 等之间的 +。

现在我有一个解析器,它从输入中读取表达式,例如:RDD+1,解析它并创建后缀以使计算更容易,例如:RDD1+,然后我想使用我实现的 + 进行计算。在 this algorithm 的帮助下,我试图以某种方式更改它,使其根据我的输入表达式执行计算。例如它包含:

 var lastOp: (Float, Float) => Float = add

我怎样才能改变这个:(Float, Float) => Float 到可以接受的东西 (RDD, Float)|(RDD, RDD) |(Float, Float) => RDD = add // 我的 add 实现 ???

版本:

我在下面两个答案的帮助下添加了这一部分: 好的,我写了这个:

     def lastop:(Either[RDD[(Int,Array[Float])], Float], Either[RDD[(Int,Array[Float])], Float]) => RDD[(Int,Array[Float])] = sv.+

其中 sv 是我的另一个 class 的一个实例,我已经在其中覆盖了 + 但是以两种不同的方式所以现在我收到一个错误,我猜这是因为编译器对哪个实现感到困惑使用这个是

       error:  type mismatch;
       [error]  found   : (that: org.apache.spark.rdd.RDD[(Int, Array[Float])])org.apache.spark.rdd.RDD[(Int, Array[Float])] <and> (that: Float)org.apache.spark.rdd.RDD[(Int, Array[Float])]
       [error]  required: (Either[org.apache.spark.rdd.RDD[(Int, Array[Float])],Float], Either[org.apache.spark.rdd.RDD[(Int, Array[Float])],Float]) => org.apache.spark.rdd.RDD[(Int, Array[Float])]

注意:它所说的发现是“+”的两种不同实现方式

好吧,我不确定这是最好的方法,但这是一种方法,应该会导致您描述的用法(或至少接近它):

import scala.language.implicitConversions

// implicit conversions
implicit def float2Either(in: Float): Either[Float, RDD[(Int,Array[Float])]] = Left(in)
implicit def rdd2Either(in: RDD[(Int,Array[Float])]): Either[Float, RDD[(Int,Array[Float])]] = Right(in)

def add(left: Either[Float, RDD[(Int,Array[Float])]], right: Either[Float, RDD[(Int,Array[Float])]]): Float = {
  (left, right) match {
    case (Left(someFloat), Left(anotherFloat)) => ???
    case (Left(someFloat), Right(someRdd)) => ???
    case (Right(someRdd), Left(someFloat)) => ???
    case (Right(someRdd), Right(anotherRdd)) => ???
  }
}
val lastOp: (Either[Float, RDD[(Int,Array[Float])]], Either[Float, RDD[(Int,Array[Float])]]) => Float = add

另一种可能更好的方法是 pimp my library 模式。

但是,您无法自己决定 (float + float) 会产生什么。在最理智的情况下这应该不是问题。

您可以为 Float 和 RDD 编写隐式包装器 类,就像 'RichFloat' 'RichInt' 等。为每个接受另一个作为输入的运算符实施运算符。

implicit class RichRdd(val underlying: RDD) extends AnyVal {
  def +(in: Float): Float = ???
  def +(in: Test): Float = ???
}
implicit class RicherFloat(val underlying: Float) extends AnyVal {
  def +(in: RDD): Float = ???
}

我认为 pattern matching 是正确的方法,您可能需要对运算符重载进行更多研究。

关于RDD,它应该是Spark中的一个collection of elements,我不知道你想通过向数字添加一个列表来实现什么,RDD中只有一个元素? ..ETC。

在不知道你想要什么的情况下,这里有一个例子展示了你如何使用模式匹配来处理不同类型的组合:

import math.hypot

object test {

    def myadd(x: Any, y: Any) = (x, y) match {
        case (x: String, y:String) => x.toInt + y.toInt
        case (x: String, y:Int) => x.toInt + y.toInt
        case (x: Int, y:String) => x + y.toInt
        case (x: Int, y:Int) => x + y
        case _ =>
    }                                         //> myadd: (x: Any, y: Any)AnyVal

    var result = myadd(1,2)                   //> result  : AnyVal = 3
    println(result)                           //> 3
    println(result.getClass())                //> class java.lang.Integer

    result = myadd(1,"2")
    println(result)                           //> 3
    println(result.getClass())                //> class java.lang.Integer

    result = myadd(1.0,2)
    println(result)                           //> ()
    println(result.getClass())                //> class scala.runtime.BoxedUnit

}