2014-09-22 23 views
6

Tôi có một chức năng dường như hợp pháp có thể chuyển đổi một mảng đến một từ điển:Swift không thể suy ra loại từ bối cảnh

func arrayToDictionary<Key : Hashable, Value> 
    (source: Array<Value>, key: Value -> Key) -> Dictionary<Key, Value> { 
    var dictionary = Dictionary<Key, Value>() 
    for element in source { 
    let key = key(element) 
    dictionary[key] = element 
    } 
    return dictionary 
} 

Bây giờ, khi tôi cố gắng gọi nó là:

let dict = arrayToDictionary([1, 2, 3], { val in return val }) 

tôi nhận được một lỗi - Không thể chuyển đổi loại biểu thức '($ T6, (($ T9) -> ($ T9) -> $ T8) -> (($ T9) -> $ T8) -> $ T8)' để nhập 'Hashable'

Kỳ lạ, nếu tôi sử dụng trả lại tiềm ẩn:

let dict = arrayToDictionary([1, 2, 3], { val in val }) 

hoặc viết tắt:

let dict = arrayToDictionary([1, 2, 3], { $0 }) 

nó hoạt động tốt. Tại sao?

+0

'để dict = arrayToDictionary ([1, 2, 3], {val trong val}) '(lấy ra' return') cũng có vẻ hoạt động tốt. –

+0

Và, ngay cả người lạ, xác định rõ ràng 'val' như một' Int' với 'return' tại chỗ:' let dict = arrayToDictionary ([1, 2, 3], {(val: Int) trong trả về val}) ' gây ra lỗi: ''NSNumber' không phải là một kiểu con của 'Int''. Lấy lại 'return' ra vẫn hoạt động. –

+0

điều này trông giống như một lỗi trình biên dịch cho tôi và tôi khuyên bạn nên báo cáo nó. Một số tối ưu hóa diễn ra đằng sau hậu trường được thực hiện quá sớm và kiểm tra kiểu không hài lòng về nó –

Trả lời

2

Câu hỏi này chỉ có thể được trả lời bởi một kỹ sư biên dịch tại Apple và mỗi người bình luận ở trên có thể/được coi là lỗi, nhưng chắc chắn là một lỗ hổng trong cú pháp viết tắt của họ. Đối với những câu hỏi như thế này, tôi đã nhận được kết quả tốt từ việc đăng bài lên devforums.

Quy tắc đơn giản là bất cứ khi nào bạn có nhiều dòng/cần sử dụng từ khóa return, bạn phải xác định rõ ràng loại trả về hoặc loại giá trị được ghi lại. Giới hạn này có thể là do trong trường hợp nhỏ gọn/thoái hóa, bạn được đảm bảo chỉ có một điểm thoát - val in val, khi bạn sử dụng từ khóa return, có thể có nhiều điểm trả lại. Trong trường hợp sau này, bạn có thể trả về Int trên một dòng return 1 và trả lại nil cho một số khác. Trong trường hợp đó, nó sẽ là hợp lý để có trình biên dịch phàn nàn để làm cho giả định rõ ràng. Tóm lại, điều này sẽ đòi hỏi suy luận kiểu phức tạp hơn trong trình biên dịch, và họ có thể chưa đạt được điều đó.

Vì vậy, TL; DR, tôi đồng ý với đề xuất báo cáo lỗi này, và trong thời gian chờ đợi, hãy chỉ định loại trả lại từ việc đóng. Điểm vẫn còn mặc dù trình biên dịch có đủ ngữ cảnh để suy ra đúng loại, như bạn đã nói.

Lưu ý, rằng ngoài ví dụ của bạn, những trường hợp này cũng làm việc:

// inferring var dict as a context for lines below 
var dict = arrayToDictionary([1, 2, 3], { val in val }) 

// dict is already defined, so this works: 
dict = arrayToDictionary([1, 2, 3], { val in return val }) 

// explicit final type, compiler infers backwards 
let d2:Dictionary<Int, Int> = arrayToDictionary([1, 2, 3], { val in val }) 

// explicit return type, compiler infers "forewards" 
let d3 = arrayToDictionary([1, 2, 3], { val -> Int in return val }) 
Các vấn đề liên quan