2016-12-20 56 views
7

tôi đã viết các chương trình đơn giản sau đây:Hiểu loại inferrence trong Scala

import java.util.{Set => JavaSet} 
import java.util.Collections._ 

object Main extends App { 
    def test(set: JavaSet[String]) =() 

    test(emptySet()) //fine 
    test(emptySet) //error 
} 

DEMO

Và đã thực sự gây bất ngờ cho dòng cuối cùng test(emptySet) không được biên dịch. Tại sao? Sự khác nhau giữa test(emptySet()) là gì? Tôi nghĩ ở Scala, chúng ta có thể bỏ qua dấu ngoặc đơn một cách tự do trong những trường hợp như vậy.

Trả lời

4

Xem Method Conversions trong đặc tả Scala:

Bốn chuyển đổi tiềm ẩn sau đây có thể được áp dụng cho phương pháp đó không được áp dụng đối với một số danh sách đối số.

Đánh giá

Một parameterless phương pháp m của type => T luôn được chuyển đổi sang loại T bằng cách đánh giá các biểu hiện mà m đang bị ràng buộc.

Application Implicit

Nếu phương pháp này chỉ mất các thông số ngầm, lập luận ngầm được truyền theo các quy tắc ở đây.

Eta Expansion

Ngược lại, nếu phương pháp này không phải là một nhà xây dựng, và các loại dự kiến ​​pt là một loại chức năng (Ts ') ⇒T', eta-mở rộng được thực hiện trên các biểu hiện e.

Rỗng Application

Ngược lại, nếu e có kiểu() phương pháp T, nó được ngầm áp dụng cho danh sách đối số rỗng, năng suất e().

Thứ bạn muốn là "Ứng dụng trống", nhưng nó chỉ được áp dụng nếu không có chuyển đổi nào trước đó và trong trường hợp này "Eta Expansion" sẽ xảy ra thay thế.

EDIT: Điều này sai và nhận xét của @ Jasper-M là đúng. Không có sự mở rộng eta nào đang xảy ra, "Ứng dụng rỗng" chỉ là không thể áp dụng với các phương thức chung hiện nay.

+0

Nhưng tại sao loại được suy ra trong 'test (emptySet)' - 'JavaSet [Nothing]'? –

+1

Từ thông báo lỗi, nó không phải là. Nếu bạn có nghĩa là IDEA hiển thị loại này, nó sai. Bạn không thể tin tưởng các lỗi được hiển thị của IDEA và các loại suy ra khi nhập, luôn cố gắng thực sự tạo mã trước tiên. –

+0

Chỉ cần đọc báo cáo của bạn. Do đó, trường hợp thứ hai cũng nên hoạt động tốt, đúng không? –