2012-11-06 24 views
5

tôi nhận được một lỗi trên dòng:Lỗi trên lớp scala: Phương pháp đệ quy printExpr cần kết quả loại

case Sum(l, r) => printExpr(l); print("+"); printExpr(r) 

lỗi là:

phương pháp đệ quy printExpr cần loại quả

Mã này có vẻ ổn với tôi, tôi đang làm gì sai?

abstract class Expr { 

    case class Num(n: Int) extends Expr 
    case class Sum(l: Expr , r: Expr) extends Expr 
    case class Prod(l: Expr, r: Expr) extends Expr 

    def evalExpr(e: Expr): Int = e match { 
    case Num(n) => n 
    case Sum(l, r) => evalExpr(l) + evalExpr(r) 
    case Prod(l, r) => evalExpr(l) * evalExpr(r) 
    } 

    def printExpr(e: Expr) = e match { 
    case Num(n) => print(" " + n + " ") 
    case Sum(l, r) => printExpr(l); print("+"); printExpr(r) 
    case Prod(l, r) => printExpr(l); print("x"); printExpr(r) 
    } 
} 

Trả lời

8

Phương thức đệ quy trong Scala cần loại trả về rõ ràng, như thông báo lỗi nêu rõ.

Lý do là Scala xâm nhập kiểu trả về của phương thức từ các loại được sử dụng trong phần thân phương thức. Khi kiểu trả về của phương thức ảnh hưởng đến các kiểu được sử dụng trong thân phương thức (vì nó tự gọi là đệ quy), Scala không thể tìm ra loại nào cần gán cho phương thức, vì vậy nó yêu cầu bạn làm như vậy trong nguồn mã (như bạn có với evalExpr, trong đó bạn nói rõ ràng rằng nó trả về một số Int).

Trong trường hợp này, bạn muốn printExpr để có loại trả lại Unit, là loại giá trị không quan tâm không có thông tin. Thường gọi một phương thức với kiểu trả về Unit chỉ được thực hiện cho các tác dụng phụ của nó (chẳng hạn như print).

Vì vậy, bạn có thể thay đổi dòng tiêu đề của printExpr tới:

def printExpr(e: Expr) : Unit = e match { 

Ngoài ra, Scala có một số cú pháp đường cho tuyên bố "thủ tục". Bạn có thể nghĩ về một "thủ tục" như không trả lại bất cứ điều gì, và chỉ thực hiện một số mã, nhưng thực sự mọi phương pháp trong Scala trả về một cái gì đó; "thủ tục" chỉ là phương thức trả về loại Unit. Cú pháp để làm như vậy là bỏ qua = sau tiêu đề của phương thức, nhưng sau đó bạn phải bao quanh thân phương thức bằng dấu ngoặc nhọn (ngay cả khi đó là một biểu thức duy nhất, như match). Vì vậy, bạn có thể làm:

def printExpr(e: Expr) { 
    e match { 
    ... 
    } 
} 

để tránh tuyên bố rõ ràng Unit.

1

tặng một kiểu trả về để printExpr(e : Expr) như String hoặc Expr ví dụ

printExpr(e : Expr): Expr 
printExpr(e : Expr): String 
4

Scala biên dịch các loại suy luận không thể cho các phương pháp đệ quy, vì vậy bạn phải khai báo nó một cách rõ ràng:

def printExpr(e: Expr): Unit = e match { 
Các vấn đề liên quan