Как мне написать рекурсивные анонимные функции? - PullRequest
6 голосов
/ 25 июня 2011

В своих постоянных усилиях по изучению scala я работаю над «Scala by example» Одерского и над главой о функциях первого класса, раздел об анонимной функции избегает ситуации рекурсивной анонимной функции. У меня есть решение, которое, кажется, работает. Мне любопытно, есть ли лучший ответ там.

Из PDF: Код для демонстрации функций высшего порядка

def sum(f: Int => Int, a: Int, b: Int): Int =
  if (a > b) 0 else f(a) + sum(f, a + 1, b)

def id(x: Int): Int = x
def square(x: Int): Int = x * x
def powerOfTwo(x: Int): Int = if (x == 0) 1 else 2 * powerOfTwo(x-1)

def sumInts(a: Int, b: Int): Int = sum(id, a, b)
def sumSquares(a: Int, b: Int): Int = sum(square, a, b)
def sumPowersOfTwo(a: Int, b: Int): Int = sum(powerOfTwo, a, b)

scala> sumPowersOfTwo(2,3)
res0: Int = 12

из pdf: Код для демонстрации анонимных функций

def sum(f: Int => Int, a: Int, b: Int): Int =
  if (a > b) 0 else f(a) + sum(f, a + 1, b)

def sumInts(a: Int, b: Int): Int = sum((x: Int) => x, a, b)
def sumSquares(a: Int, b: Int): Int = sum((x: Int) => x * x, a, b)
// no sumPowersOfTwo

Мой код:

def sumPowersOfTwo(a: Int, b: Int): Int = sum((x: Int) => {
   def f(y:Int):Int = if (y==0) 1 else 2 * f(y-1); f(x) }, a, b)

scala> sumPowersOfTwo(2,3)
res0: Int = 12

Ответы [ 2 ]

13 голосов
/ 25 июня 2011

Для чего это стоит ... (название и «реальный вопрос» не совсем согласны)

Рекурсивные анонимные функциональные объекты могут быть созданы с помощью расширения "длинной руки" FunctionN, а затем с помощью this(...) внутри apply.

(new Function1[Int,Unit] {
  def apply(x: Int) {
    println("" + x)
    if (x > 1) this(x - 1)
  }
})(10)

Тем не менее, количество врожденности, которое это обычно вносит, делает подход, как правило, не идеальным. Лучше всего просто использовать «имя» и иметь более описательный модульный код - не то, чтобы следующий аргумент был очень хорошим аргументом для такого; -)

val printingCounter: (Int) => Unit = (x: Int) => {
    println("" + x)
    if (x > 1) printingCounter(x - 1)
}
printingCounter(10)

Удачного кодирования.

2 голосов
/ 28 июня 2011

Вы можете обобщить эту косвенную рекурсию на:

case class Rec[I, O](fn : (I => O, I) => O) extends (I => O) {
  def apply(v : I) = fn(this, v)
}

Теперь сумма может быть записана с использованием косвенной рекурсии как:

val sum = Rec[Int, Int]((f, v) => if (v == 0) 0 else v + f(v - 1))

Такое же решение можно использовать, например, для создания заметок.

...