Как в Scala назначить функции разных типов возврата?

Я пытаюсь написать функцию, которая должна возвращать разные пары в зависимости от ввода. Я переопределил «+ - / *» в Scala для своего конкретного использования. Каждый ( +, -,* ,/) имеет три реализации на основе ввода. У меня есть RDD и Float в качестве входных данных, поэтому это может быть + между RDD и RDD, или Float и RDD, или Float и Float и так далее.

Теперь у меня есть синтаксический анализатор, который считывает выражение из ввода, например: RDD+1 , анализирует его и создает постфикс, чтобы упростить вычисления, например: RDD1+ , а затем я хочу выполнить расчет, используя реализованный + . с помощью этого алгоритма я пытаюсь изменить его таким образом, чтобы он выполнял вычисления на основе моего входного выражения. Например, он содержит:

 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 является экземпляром из моего другого класса, который я переопределил + в этом, но двумя разными способами, поэтому теперь я получаю сообщение об ошибке, которое, я думаю, связано с тем, что компилятор запутался в том, какую реализацию использовать, это

       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])]

Примечание: он говорит, что нашел две разные реализации для "+"


person Rubbic    schedule 02.07.2015    source источник
comment
Вы можете использовать перегрузку функций? То есть реализуйте каждый из этих методов с разными типами аргументов.   -  person marios    schedule 02.07.2015
comment
afaik, чтобы это сработало, вам нужно будет реализовать свою функцию «добавить» таким же образом. Таким образом, у вас будет только одна реализация с использованием Both вместо нескольких перегруженных реализаций. Тем не менее, я обновлю свой ответ третьим вариантом, который, надеюсь, лучше удовлетворит ваши потребности.   -  person Sascha Kolberg    schedule 03.07.2015
comment
Извините, для третьего варианта я думал в духе Numeric[T], который, как я теперь думаю, не сработает. Тем не менее, я обновил свой ответ до того, что, по моему мнению, может сработать. Я не думаю, что то, что вы описываете, возможно именно так, как вы это описываете.   -  person Sascha Kolberg    schedule 03.07.2015


Ответы (2)


Что ж, я не уверен, что это лучший способ сделать это, но это ОДИН способ сделать это, и он должен привести к описанному вами использованию (или, по крайней мере, близкому к нему):

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 и 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 = ???
}
person Sascha Kolberg    schedule 02.07.2015
comment
Спасибо за помощь мне. У меня есть несколько вопросов, что такое lFloat и rFloat, и под тестом вы имели в виду RDD в моей программе? тогда что будет lTest и rTest? - person Rubbic; 03.07.2015
comment
Это сопоставление с образцом, использование экстракторов (Left, Right) связывает содержащиеся значения с новыми локальными значениями. Вероятно, вам следует поискать сопоставление с образцом и экстракторы. - person Sascha Kolberg; 03.07.2015
comment
У меня есть вопрос после нашего обсуждения здесь, не могли бы вы помочь мне и с этим? - person Rubbic; 16.07.2015

Я думаю, что сопоставление с образцом правильный путь, вам, возможно, придется провести больше исследований в области перегрузки операторов.

Что касается RDD, это должен быть набор элементы в Spark, где я не знаю, чего вы пытаетесь достичь, добавляя список к числу, только один элемент в RDD? ..так далее.

Не зная точно, чего вы хотите, вот пример, показывающий, как вы можете обрабатывать различные комбинации типов, используя сопоставление с образцом:

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

}
person B.Mr.W.    schedule 02.07.2015
comment
@Б. Г-н В. Я поместил Any в класс myadd, но он выдает ошибку, потому что я отправляю RDD, а он запрашивает Any !!! не знаю, почему Any не может принять тип RDD - person Rubbic; 03.07.2015