2015-03-21 18 views
5

Tôi đang đọc "Ngôn ngữ lập trình D" của Andrei Alexandrescu và một câu làm tôi bối rối. Hãy xem xét mã như vậy (p.138):Điều gì là sai với loại suy luận của mẫu và chuyển đổi loại tiềm ẩn?

T[] find(T)(T[] haystack, T needle) { 
    while (haystack.length > 0 && haystack[0] != needle) { 
     haystack = haystack[1 .. $]; 
    } 
    return haystack; 
} 

và gọi số (p.140):

double[] a = [ 1.0, 2.5, 2.0, 3.4 ]; 
a = find(a, 2); // Error! ' find(double[], int)' undefined 

Giải thích (đoạn mã dưới đây):

Nếu chúng ta nheo mắt cứng đủ , chúng tôi thấy rằng mục đích của người gọi trong trường hợp này là có T = double và được hưởng lợi từ chuyển đổi tiềm ẩn tốt đẹp từ int thành double. Tuy nhiên, có sự cố gắng ngôn ngữ hợp tác cùng lúc với các chuyển đổi tiềm ẩn và loại khấu trừ là một đề xuất dicey trong trường hợp chung, vì vậy D không cố gắng làm tất cả những điều đó.

Tôi đang bối rối vì ngôn ngữ như C# cố gắng suy ra loại - nếu nó không thể làm điều này, người dùng bị lỗi, nhưng nếu nó có thể, tốt, nó hoạt động. C# sống với nó trong nhiều năm và tôi không nghe thấy bất kỳ câu chuyện làm thế nào tính năng này hủy hoại ngày của ai đó.

Và vì vậy câu hỏi của tôi là điều này - những mối nguy hiểm nào có liên quan đến việc suy ra các loại như trong ví dụ trên?

Tôi chỉ có thể thấy những lợi thế, thật dễ dàng để viết hàm chung và dễ gọi nó. Nếu không, bạn sẽ phải giới thiệu nhiều tham số hơn trong lớp/hàm chung chung và viết các ràng buộc đặc biệt thể hiện chuyển đổi được phép chỉ vì lợi ích của việc suy ra các loại.

+4

Ở trên dường như chạy tốt trong 'dmd 2.066'. Tôi đoán họ đã quyết định rằng mệnh đề không phải là 'xúc xắc' như họ nghĩ. – rcorre

+5

Tính năng này đã được giới thiệu khoảng một năm trước trong PR này: https://github.com/D-Programming-Language/dmd/pull/3353 –

Trả lời

1

Điều đầu tiên cần lưu ý là nó không nói rằng có một vấn đề với loại trừ, đó là có một vấn đề với loại trừ ngầm chuyển đổi cùng lúc.

Vì vậy, nếu bạn có:

a = find(a, 2.0); 

Sau đó, nó là hạnh phúc để suy luận double như các loại.

Và nếu được nhập một cách rõ ràng để tăng gấp đôi, thật vui khi suy ra rằng 2 nên được truyền hoàn toàn đến 2.0.

Những gì nó sẽ không làm là cả hai cùng một lúc.

Bây giờ, C# thực hiện điều đó. Và tôi nghĩ rằng phần lớn tôi đồng ý với bạn, nó nói chung là thuận tiện và thường hoạt động tốt đủ.

Đúng là đồng thời nó có thể gây nhầm lẫn, đặc biệt trong trường hợp nó dẫn đến nhiều hơn một tình trạng quá tải hợp lý.

Why type inference and implicit operator is not working in the following situations?Why does Assert.AreEqual on custom struct with implicit conversion operator fail? là cả hai câu hỏi về lý do tại sao một kết hợp cụ thể của chuyển đổi tiềm ẩn và suy luận loại không hoạt động.

Unexpected effect of implicit cast on delegate type inference có các yếu tố khác, nhưng lại từ chối xem xét phương pháp trong danh sách các kết quả phù hợp có thể do loại đối số không khớp sẽ có nghĩa là sự cố không xảy ra.

Cả hai sẽ đơn giản hơn rất nhiều nếu câu trả lời luôn là "bởi vì bạn đang thực hiện chuyển đổi ngầm và suy luận kiểu cùng một lúc và không được hỗ trợ". Câu trả lời là gì với D.

Mặt khác, các vấn đề như vậy không phát sinh thường xuyên, vì vậy tôi vẫn ủng hộ quyết định thiết kế C# cho phép cả hai, nhưng có một số vấn đề có nghĩa là vẫn là một quyết định thiết kế hợp lý để không cho phép họ.

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