2011-06-25 47 views
6

Trong nỗ lực liên tục của tôi để tìm hiểu scala, tôi đang làm việc thông qua 'Scala by example' của Odersky và trên chương về các hàm lớp đầu tiên, phần về chức năng ẩn danh tránh tình trạng ẩn danh đệ quy. Tôi có một giải pháp mà dường như làm việc. Tôi tò mò nếu có một câu trả lời tốt hơn ở đó.Làm cách nào để viết các hàm ẩn danh đệ quy?

Từ pdf: Mã để giới thiệu chức năng bậc cao

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 

từ pdf: Mã để giới thiệu chức năng ẩn danh

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 

Mã của tôi:

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 
+0

Bạn có chắc chắn về điều đó không? 'echo" 2^2 + 3^2 "| bc -l' -> '13'. – sarnold

+0

Đây là một bản sao http://stackoverflow.com/questions/5337464/anonymous-recursive-function-in-scala – Suroot

+1

@sarnold Tổng số Quyền hạn của Hai - tức là '2^a + 2^a + 1 + ... 2^b-1 + 2^b' '2^2 + 2^3 = 4 + 8 = 12' –

Trả lời

13

Đối những gì nó có giá trị ... (tiêu đề và "câu hỏi thực sự" không hoàn toàn đồng ý)

Recursive anonymous function-đối tượng có thể được tạo ra thông qua "tay dài" mở rộng của FunctionN và sau đó sử dụng this(...) bên apply.

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

Tuy nhiên, lượng icky-ness này thường giới thiệu làm cho cách tiếp cận thường ít hơn lý tưởng. Tốt nhất chỉ cần sử dụng một "tên" và có một số mô tả, mô-đun mã - không phải là sau đây là một đối số rất tốt cho ;-)

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

Chúc mừng mã hóa.

2

Bạn có thể khái quát đệ quy gián tiếp này để:

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

Bây giờ tổng thể được viết bằng đệ quy gián tiếp như:

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

Các giải pháp tương tự có thể được sử dụng để thực hiện memoization ví dụ.

Các vấn đề liên quan