2016-04-05 2 views
-3

Мне нужна помощь с синтаксисом.Рекурсивный вызов функции, возвращающей функцию

Вопрос: Как я могу вызвать метод рекурсивно в этой ситуации?

Пожалуйста, найти ошибку в коде ниже:

def increase[T: Numeric](x: T) = (y: T) => { 
    require(implicitly[Numeric[T]].gt(x , 0.asInstanceOf[T])) 
    if (implicitly[Numeric[T]].gt(y , 0.asInstanceOf[T])) 
     implicitly[Numeric[T]].plus(x, y) 
    else     
     increase[T](x)(implicitly[Numeric[T]].abs(y)) 
} 

val inc = increase[Int] _ 

println(inc(5)(-1)) 

Вот код ошибки: C: \ Sources> CD

Scala

C: \ Sources \ Scala> Scala main.scala с : \ Sources \ Scala \ main.scala: 29: ошибка: рекурсивный метод нуждается в увеличении привести ти ре increaseT (. неявно [Числовые [Т]] абс (у)) ^ одна ошибка найдено

c: \ Sources \ scala>

+0

Возможный дубликат [Ошибка в классе scala: рекурсивный метод printExpr нуждается в типе результата] (http://stackoverflow.com/questions/13260275/error-on-scala-class-recursive-method-printexpr-needs-result-type) – Ben

+0

Также, пожалуйста, разместите ошибки как текст, а не изображения. – Ben

+0

Я возвращаю функцию из функции, поэтому не уверен, что это хорошая идея, чтобы изменить подпись функции. – Pavel

ответ

4

Существует довольно много проблем с определением вашей функции.

  1. Из-за того, как контекст ограничивает работу, def increase[T: Numeric](x: T) = (y: T) => ??? действует как нечто вроде def increase[T](x: T)(implicit ev: Numeric[T])(y: T). Список неявных аргументов находится между нормальными, поэтому невозможно просто указать один из следующих значений: x и y. Итак, increase(x)(abs(y)) не будет работать, вам нужно будет использовать что-то вроде increase(x).apply(abs(y)).

  2. Нельзя использовать 0.asInstanceOf[T]. Например, если T - BigInt, это становится 0.asInstanceOf[BigInt] и приводит к исключению во время выполнения: java.lang.ClassCastException: java.lang.Integer cannot be cast to scala.math.BigInt. Вместо этого вы можете использовать implicitly[Numeric[T]].zero.

  3. Имея эти implicitly[Numeric[T]] везде, не очень красиво. Лучше иметь фиксированное имя для этого неявного аргумента и импортировать неявные операции, поэтому можно будет использовать x > num.zero и x + y. См. Пример ниже.

  4. Как уже упоминалось в комментариях, вы должны явно указать тип возврата рекурсивной функции. В вашем случае это должно быть T => T.

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

def increase[T](x: T)(implicit num: Numeric[T]): T => T = (y: T) => { 
    import num._ 

    require(x > num.zero) 
    if (y > num.zero) x + y 
    else increase(x).apply(y.abs) 
} 

val inc = increase[Int] _ 

println(inc(5)(-1)) 

Кроме того, вы можете иметь аналогичное определение без использования анонимной функции:

def increase[T](x: T)(y: T)(implicit num: Numeric[T]): T = { 
    import num._ 

    require(x > num.zero) 
    if (y > num.zero) x + y 
    else increase(x)(y.abs) 
} 

И на всякий случай, здесь вам даже не нужно делать это рекурсивно:

def increase[T](x: T)(y: T)(implicit num: Numeric[T]): T = { 
    import num._ 

    require(x > num.zero) 
    x + y.abs 
} 
+0

Хорошо, вижу. Это выглядит как хороший и подробный ответ для меня. Похоже, нужно улучшить знания scala в нескольких областях. Благодаря! – Pavel

+0

Просто для подтверждения: T => T = (y: T) здесь вы определяете тип возврата для функции. Я немного запутался с частью после стрелы. Что это за конструкция? спасибо – Pavel

+1

@PavelOliynyk 'T => T' - это тип возврата, тогда у вас есть' = ', а затем начинается определение функции:' (y: T) '. Это похоже на ваш код с добавлением определения типа T => T. А 'A => B' - это тип функции, который принимает аргумент типа' A' и возвращает результат типа 'B'. 'A => B' на самом деле является синтаксическим сахаром для' Function1 [A, B] '. – Kolmar

Смежные вопросы