2010-10-18 29 views
11

Ai đó có thể giải thích cho tôi về tình huống sau đây với cơ chế chuyển đổi tiềm ẩn của Scala. Có một mã:Câu hỏi về chuyển đổi tiềm ẩn Scala Quy tắc không mơ hồ

object Main { 
    implicit val x:Int => String = v => "val" 
    implicit def y(v:Int) = "def" 

    def p(s:String) = print(s) 

    def main(args: Array[String]): Unit = { 
     p(1) 
    } 
} 

Mã này in "val". Nhưng khi tôi nhận xét dòng thứ hai:

//implicit val x:Int => String = v => "val" 

in mã "def".

Vì vậy, cả hai chuyển đổi tiềm ẩn (x và y) đều có thể xảy ra trong tình huống này. Có Quy tắc không mơ hồ - một chuyển đổi tiềm ẩn chỉ được chèn vào nếu không có chuyển đổi có thể khác để chèn. Theo quy tắc này, mã này không được biên dịch chút nào. Nhưng mã được biên dịch và thực hiện thành công. Những gì tôi không hiểu?

Cảm ơn.

Trả lời

9

Lý do cho điều này được nêu trong phần Đặc điểm Ngôn ngữ Scala 6.26.2.

Trước khi phương pháp này có thể được coi là hàm cần phải được chuyển đổi thành một hàm bằng cách thực hiện mở rộng eta. Do đó, một chuyển đổi tiềm ẩn hơn sẽ phải được áp dụng và do đó, val được chọn.

CẬP NHẬT: ví dụ bị xóa hoàn toàn.

Đánh giá phương thức không có tham số luôn được thực hiện ngầm định.

+0

Xin chào Moritz. Cảm ơn bạn đã trả lời. Vì vậy, khi trình biên dịch Scala thấy biểu thức có kiểu không khớp với kiểu mong đợi, nó sẽ tìm kiếm các chuyển đổi ngầm định kiểu T => F, nếu không tìm thấy các chuyển đổi như vậy, trình biên dịch sẽ cố gắng thực hiện Eta Expansion hoặc Empty Application trên các biểu thức phương thức có sẵn (từ "Nếu không" trong Đặc tả Ngôn ngữ Scala cho biết hành động này sẽ được thực hiện sau). Cho dù tôi hiểu tất cả? –

+0

Nhưng trong ví dụ của bạn nếu tôi nhận xét // ngụ ý val t = "World", mã sẽ không được biên dịch. Dường như ứng dụng rỗng không được xem xét bởi trình biên dịch Scala ở đây. –

+0

Ứng dụng trống là AFAICT thực sự không được sử dụng khi trình biên dịch tìm kiếm các chuyển đổi tiềm ẩn nhưng chỉ để điền vào các tham số ngầm định khác. Nếu bạn viết 'implicit def i2s(): Int => String = _.toString', điều này sẽ không được coi là một ứng cử viên cho một chuyển đổi từ' String' thành 'Int'. Ngoài ra nó là chính xác - các chuyển đổi trong danh sách trong 6.26.2 được cố gắng từ trên xuống dưới nếu giá trị không thể được đánh giá trực tiếp. – Moritz

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