Этот странный тип [T *] - PullRequest
       33

Этот странный тип [T *]

3 голосов
/ 25 ноября 2010

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

def mixer1(begin: String, beginings: String*)(end: String, endings: String*) =
  for (b <- (begin +: beginings); e <- (end +: endings)) yield (b + e)

На самом деле то, что делает функция, не имеет значения, я хочу переписать ее следующим образом:

  def mixer2(begin: String, beginings: String*):Function2[String, Seq[String], Seq[String]] = {
    return new Function2[String, Seq[String], Seq[String]] {
      def apply(end:String, endings:Seq[String]) = for(b <- (begin +: beginings); e <- (end +: endings)) yield b+e
    }
  }

Очевидно, что второй не будет работать должным образом, потому что второй параметр apply имеет тип Seq [String], но не String * (как они оба компилируются в Seq [String]):

scala> mixer1("a","b")("c","d")
res0: Seq[java.lang.String] = ArrayBuffer(ac, ad, bc, bd)

scala> mixer2("a","b")("c","d")
<console>:10: error: type mismatch;
 found   : java.lang.String("d")
 required: Seq[String]
       mixer2("a","b")("c","d")

Как я могу (если смогу) переопределить функцию mixer2?

Ответы [ 4 ]

3 голосов
/ 25 ноября 2010

Попробуйте так:

def mixer2(begin: String, beginings: String*) = {
    new ((String, String*) => Seq[String]) {
      def apply(end: String, endings: String*) = for(b <- (begin +: beginings); e <- (end +: endings)) yield b+e
    }
}

Мы используем вывод типа на mixer2, чтобы получить правильный тип. Это означает, что return должен быть удален, но это нормально, так как это было ненужно (и, как правило, не рекомендуется в Scala). Большая хитрость заключается в использовании A => B синтаксического сахара для Function, чтобы иметь возможность использовать String*. Затем просто измените apply, как и ожидалось.

2 голосов
/ 25 ноября 2010

Вы можете пойти легким путем:

def mixer2 = mixer1 _
0 голосов
/ 28 ноября 2010

Вы можете сбежать, даже не называя промежуточный тип возврата.

def mixer2(begin: String, beginings: String*) = new {
  def apply(end: String, endings: String*) =
    for (b <- (begin +: beginings); e <- (end +: endings)) yield b+e
}

Люди попытаются сказать вам, что это подразумевает рефлексию.Удивительно, но это не так.

0 голосов
/ 25 ноября 2010

Как в вашем примере, вы можете просто сделать это

implicit def toSeq[T](x: T): Seq[T] = List(x)

Но когда дело доходит до большего количества аргументов, например

mixer2("a","b")("c","d","e")

Кажется, нет подходящего решения, хотя было неявное преобразование из Array [T] в Seq [T]. Поскольку T * - это синтаксическая конфета, («c», «d», «e») будут рассматриваться как 3 аргумента. Компилятор не может распознать, какие из них образуют массив.

Так что мне интересно, каков ваш настоящий сценарий, этот пример выглядит странно. Если вам нужна только часть функции, решение @ Debilski - отличный способ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...