2011-07-11 11 views
24

tôi nhận thấy rằng khi tôi đang làm việc với các chức năng mà mong đợi các chức năng khác như các thông số, đôi khi tôi có thể làm điều này:Khi nào tôi phải đối xử với các phương pháp của tôi như là các hàm được áp dụng một phần trong Scala?

someFunction(firstParam,anotherFunction) 

Nhưng thời điểm khác, trình biên dịch được đem lại cho tôi một lỗi, nói với tôi rằng tôi nên viết một chức năng như thế này, để cho nó để đối xử với nó như một chức năng áp dụng một phần:

someFunction(firstParam,anotherFunction _) 

Ví dụ, nếu tôi có điều này:

object Whatever { 
    def meth1(params:Array[Int]) = ... 
    def meth2(params:Array[Int]) = ... 
} 

import Whatever._ 
val callbacks = Array(meth1 _,meth2 _) 

Tại sao tôi không thể có mã như sau:

val callbacks = Array(meth1,meth2) 

Trình biên dịch cho tôi biết thêm _ trong hoàn cảnh nào?

Trả lời

26

Quy tắc thực sự đơn giản: bạn phải viết _ bất cứ khi nào trình biên dịch không rõ ràng mong đợi đối tượng Function.

Ví dụ trong REPL:

scala> def f(i: Int) = i  
f: (i: Int)Int 

scala> val g = f 
<console>:6: error: missing arguments for method f in object $iw; 
follow this method with `_' if you want to treat it as a partially applied function 
     val g = f 
      ^

scala> val g: Int => Int = f 
g: (Int) => Int = <function1> 
4

Ngoài chức năng gì Jean-Philippe Pellet nói, bạn có thể sử dụng ứng dụng một phần, khi viết các lớp đại biểu:

class ThirdPartyAPI{ 
    def f(a: Int, b: String, c: Int) = ... 
    // lots of other methods 
} 

// You want to hide all the unnecessary methods 
class APIWrapper(r: ThirdPartyAPI) { 
    // instead of writing this 
    def f(a: Int, b: String, c: Int) = r.f(a, b, c) 
    // you can write this 
    def f(a: Int, b: String, c: Int) = r.f _ 
    // or even this 
    def f = r.f _ 
} 

EDIT thêm def f = r.f _ một phần.

+4

Lưu ý rằng nó không phải là một * phần chức năng *, đó là một * chức năng được áp dụng một phần *. –

+0

Thx, sửa chữa nó .. – agilesteel

+1

Không nên (r: RichAPI) là (r: ThnirdPartyAPI)? –

6

Trong Scala, phương thức không phải là một hàm. Trình biên dịch có thể chuyển đổi một phương thức ngầm trong một hàm, nhưng nó cần biết loại nào. Vì vậy, hoặc là bạn sử dụng _ để chuyển đổi nó một cách rõ ràng hoặc bạn có thể đưa ra một số chỉ dẫn về loại chức năng sử dụng:

object Whatever { 
    def meth1(params:Array[Int]): Int = ... 
    def meth2(params:Array[Int]): Int = ... 
} 

import Whatever._ 
val callbacks = Array[ Array[Int] => Int ](meth1, meth2) 

hay:

val callbacks: Array[ Array[Int] => Int ] = Array(meth1, meth2)  
+0

Xem thêm [Huyền thoại: các phương pháp và chức năng giống nhau] (http://stackoverflow.com/questions/3926047/debunking-scala-myths/4812176#4812176). –