2013-04-18 28 views
6

Tôi đang cố gắng hiểu chú thích loại tên nào có nghĩa là trong ngữ cảnh của các hàm bậc cao hơn. Dưới đây là một ví dụ:Làm thế nào để các đối số theo tên hoạt động trong các hàm bậc cao hơn?

object Test { 
    def apply[A, B](f: (=> A) => B, x: => A): B = f(x) 
    def const[A](ignored: A): Int = 1 
    val res: Int = apply(const, ???) 
} 

const là nghiêm ngặt trong đối số của nó (tức là nó thiếu một chú thích =>), vậy tại sao phải không buộc đối số của nó (đó là ??? trong trường hợp này) và đặt ra một ngoại lệ?

Có giấy mô tả ngữ nghĩa ở đây không?

Tôi đang tìm câu trả lời có thẩm quyền tại đây.

Trả lời

5

Đối số f trong chức năng apply của bạn là Funcion1 có tham số gọi theo tên loại A và trả lại B. Do đó, f(x) sẽ không đánh giá thông số theo từng tên x, nhưng chuyển trực tiếp tham chiếu của nó tới f.

Đó là hữu ích để hiểu res như sau:

def res[C]: Int = apply[C, Int](const, ???) 

nơi trong ví dụ của bạn C sẽ là một loại không đặc hiệu. Bây giờ tham số kiểu được suy ra cho const trong dòng này là gì? Đó là => C. Đáng tiếc là bạn không thể gõ mà tham số:

def res[C]: Int = apply[C, Int](const[=> C], ???) // illegal syntax 

Nhưng bạn có thể xác minh những gì đang xảy ra:

def res[C]: Int = apply[C, Int](const[Nothing], ???) 

đem lại cho bạn

<console>:10: error: type mismatch; 
found : Nothing => Int 
required: => C => Int 
     def res[C]: Int = apply[C, Int](const[Nothing], ???) 
              ^

loại này xuất hiện bên const như một Function0[Int] (vì vậy Scala ngầm xử lý các đối số theo từng tên hoặc "thunk" như một hàm không có đối số). Một lần nữa, bạn có thể xác minh điều này:

def const[A](ignored: A): Int = if (ignored.isInstanceOf[Function0[_]]) 1 else 0 

Bây giờ Test.res sẽ cung cấp cho bạn 1 (nghĩa là ignored thực sự là một Function0).


Vì vậy, để trả lời câu hỏi một cách khác nhau, const có một cuộc tranh cãi hăng hái của loại A, nhưng điều đó không quan trọng ở đây vì A trở thành một chức năng trong ví dụ của bạn, và bạn không bao giờ áp dụng chức năng này, do đó ??? không bao giờ được thực hiện.


some debate như why there is both một "thunk" hoặc ngoặc-ít chức năng và một chức năng trắng Dấu ngoặc đơn (Function0) tại Scala.

+0

Tôi nghĩ rằng điều này có thể là trên http://scalapuzzlers.com/ – ghik

+0

Cảm ơn bạn đã giải thích chi tiết. Là ngữ nghĩa của sự cần thiết (mà tôi nhầm lẫn theo tên) trong Scala được định nghĩa ở đâu đó? Thông thường tính chất nghiêm ngặt được định nghĩa trong điều khoản của hàm đang được áp dụng (trong trường hợp này là 'const') nhưng lời giải thích của bạn là rất nhiều về việc thực hiện và cách đối số' const' được xây dựng. – tibbe

+0

Một câu hỏi khác, có thể tham số loại 'A' hợp nhất với cả đối số giá trị (ví dụ: 'Int') và đối số theo nhu cầu (tức là' => Int')? – tibbe

0

Tôi mở câu trả lời khác, bởi vì nó vẫn có vẻ không rõ ràng cho bạn những gì đang xảy ra:

tính thường nghiêm khắc được xác định theo chức năng được áp dụng (trong trường hợp này const) nhưng lời giải thích của bạn là rất nhiều về việc thực hiện và cách đối số cho const được xây dựng.

tôi sẽ xác định lại đối tượng của bạn với tên loại riêng biệt:

object Test { 
    def apply[A, B](f: (=> A) => B, x: => A): B = f(x) 
    def const[C](ignored: C): Int = 1 
    def res[A1]: Int = apply[A1, Int](const, ???) 
} 

Bây giờ, chúng ta hãy trao đổi bằng tên thông số với Function0, để làm nổi bật nơi "lười biếng" được ẩn:

object Test { 
    def apply[A, B](f: (() => A) => B, x:() => A): B = f(x) 
    def const[C](ignored: C): Int = 1 
    def res[A1]: Int = apply[A1, Int](const[() => A1],() => ???) 
} 

Bạn thấy đấy, định nghĩa của const không quan trọng. Điều quan trọng là đối số x đối với apply là theo tên (hoặc một hàm trong phiên bản trước). Vì vậy, f(x) gọi f với đối số chức năngx, vì vậy, bất kỳ nội dung nào của x đều không được đánh giá tại thời điểm này.

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