Tôi không có nhiều kinh nghiệm với các ngôn ngữ gõ tĩnh (hiện đang học Scala và yêu thích nó!) Nhưng một điều tôi nhận thấy là chúng dường như không có bất cứ thứ gì giống như method_missing của Ruby hoặc onMissingMethod của Coldfusion. Có một số hạn chế vốn có trong các ngôn ngữ được nhập tĩnh có ngăn chặn hoặc làm cho điều này trở nên khó khăn không?Điều gì ngăn cản một ngôn ngữ được đánh máy tĩnh có một cái gì đó giống như method_missing của Ruby?
Điều gì ngăn cản một ngôn ngữ được đánh máy tĩnh có một cái gì đó giống như method_missing của Ruby?
Trả lời
Chắc chắn một cơ chế để xử lý chúng có thể được thêm vào, nhưng đó là tỷ lệ cược với cách gõ tĩnh là: Xác định thời gian biên dịch chương trình của bạn không có lỗi loại.
Phụ Lục
Scala 2.9 giới thiệu một tùy chọn cho phép thử nghiệm loại này xử lý năng động của các truy cập đến các loại theo những cách mà nếu không sẽ thất bại kiểm tra kiểu tĩnh. Nó đã được tinh chế và thực hiện không thử nghiệm trong 2,10, mặc dù nó vẫn được kiểm soát bởi một cờ tính năng mặc định vô hiệu hóa. Bạn có thể đọc về nó trong tài liệu SIP 17. Xem SIP 18 để có giải thích về cờ "mô đun hóa" và tính năng mô-đun hóa của Scala 2.10.
cũng vi phạm điều đó, nhưng chúng hiện diện và được sử dụng nhiều trong hầu hết các ngôn ngữ tĩnh hiện đại –
những gì Randall nói là chính xác. Đối với tốt hơn hoặc tồi tệ hơn "lịch sử" nó là một sự phân chia lớn cho "thời gian biên dịch" so với không. Điều đó đang được nói một số ngôn ngữ mới hơn đến gần hơn để bắc cầu khoảng cách (scala đến tâm trí, mà tôi nghĩ rằng có một REPL). – rogerdpack
@rogerdpack: Scala chắc chắn có một REPL, mặc dù tôi không nghĩ về nó như một khía cạnh của "năng động", chỉ là một tiện lợi rất lớn khi làm việc với ngôn ngữ. –
Trong ngôn ngữ được nhập tĩnh, các hàm thành viên được gọi trực tiếp. Nếu trình biên dịch không thể tìm ra hàm thành viên nào cần gọi, chương trình sẽ không biên dịch. Phương thức gọi là, theo nghĩa này, tĩnh.
Trong ngôn ngữ được nhập động, các hàm thành viên không được gọi trực tiếp. Thay vào đó, mã gọi sẽ gửi một tin nhắn đến một đối tượng, và sau đó thời gian chạy ngôn ngữ sẽ tìm ra những gì cần làm với thông điệp đó. Ví dụ, thời gian chạy sẽ quét đối tượng cho một phương thức có cùng tên, và sau đó sẽ quét đối tượng cho một phương thức có tên method_missing
. Phương thức gọi là, theo nghĩa này, năng động.
C# 4 kết hợp nhập tĩnh với tính năng nhập động. Biến có thể có loại biên dịch là dynamic
. Bất kỳ lời gọi phương thức nào trên biến này sẽ được xử lý như trong các ngôn ngữ được nhập động. Bất kỳ lời gọi phương thức nào trên các biến với các kiểu tĩnh sẽ được xử lý như trong các ngôn ngữ được gõ tĩnh.
# static invocation, bound at compile time by the compiler
var s = 6;
s.ToString();
# dynamic invocation, handled at runtime by the CLR
dynamic d = 6;
d.ToString();
Bạn đang pha trộn nội dung. Công văn động tồn tại trong tất cả ngôn ngữ OO được gõ tĩnh. Và chỉ có một số ngôn ngữ được nhập động sử dụng mô hình truyền thông điệp đi tiên phong bởi Smalltalk. Ví dụ Python không sử dụng tính năng truyền thông điệp (thay vào đó, 'obj.method (args)' dịch thành "nhận hàm mà thành viên' phương thức' của 'obj' trỏ tới, sau đó gọi nó là' obj' làm đối số đầu tiên và 'args'"). – delnan
'var' không có gì để làm với gõ động. Nó làm cho trình biên dịch suy ra kiểu tĩnh của biến từ giá trị được gán cho nó. –
Cảm ơn bạn đã sửa chữa, sửa chữa. – yfeldblum
Chỉ để tiếp tục bài viết của Randall, có thể, nhưng lý do nó đi ngược lại mô hình tĩnh là nó vượt ra ngoài "công văn động". Công văn động vui vẻ cho phép bạn gửi đến một hàm được liên kết động với một đoạn mã đã biết. tức là trình biên dịch thiết lập công văn được xác định thực thi tại thời gian chạy, từ quan điểm của nó.
Lệnh gọi method_missing
thực chất là tạo "bắt tất cả" nơi bạn quyết định làm gì dựa trên tên phương pháp sử dụng câu lệnh chuyển đổi hoặc nội dung tương đương (mà tôi chắc chắn bạn biết). Vì vậy, trình biên dịch không có ý tưởng gì sẽ xảy ra ở đây. Hãy nói rằng trình biên dịch đã làm một cái gì đó như:
if (function is known at compile time)
{
provide static call or dynamic call to "some" derivation
}
else
{
bind the function call to obj.method_missing(...) and pass in the "details"
}
Sau đó, bạn phải cung cấp method_missing
như thế này:
def method_missing(intendedFunctionName, arguments)
{
if (intendedFunctionName is "X")
{
X may not need arguments, so just do something
}
else if (intendedFunctionName is "Y")
{
Y expects 5 arguments of varying types
Throw exception if there isn't the right number or types
}
... etc ...
}
Yêu cầu trình biên dịch để gửi cho bạn "tùy ý" (tức là không được biết đến tại thời gian biên dịch) lập luận của các loại tùy ý, với intendedFunctionName
mà bạn có thể không được tính toán ... tốt, nó không phải là rất an toàn, và Scala được dự định là một ngôn ngữ tĩnh an toàn.
Có, có thể thực hiện được nhưng không theo tinh thần của ngôn ngữ tĩnh. Nếu bạn thực sự muốn loại tính linh hoạt đó, lập trình đa ngôn ngữ có lẽ là bạn của bạn.
Lưu ý: Mục tiêu-C không được nhập đúng kiểu tĩnh. Có một công cụ thời gian chạy trên đó mã thực hiện và hệ thống gõ động không cho phép mã bị tước bỏ hoặc được gạch chân như C/C++.
"Yêu cầu trình biên dịch gửi cho bạn" tùy ý "(tức là không biết tại thời gian biên dịch) đối số của các loại tùy ý" và "không phải là rất an toàn" âm thanh giống như C varargs. :) – bk1e
Mục tiêu-C có "method_missing" (cụ thể, forwardInvocation và methodSignatureForSelector) và được cho là được nhập tĩnh. Điều này làm việc bởi vì nó sẽ xử lý các lỗi kiểu tĩnh như các cảnh báo thay vì các lỗi tại thời gian biên dịch, vì việc gửi phương thức xảy ra ở thời gian chạy đến mức lớn hơn nhiều so với các phương thức ảo trong C++ (và đây là lý do tại sao bạn có thể có "method_missing").
Phiên bản Scala 2.9 giới thiệu chức năng này thông qua đặc điểm Dynamic
(scaladoc). Các lớp mở rộng Dynamic
có được phương pháp huyền diệu applyDynamic(methodName, args)
, tương tự với số method_missing
của Ruby. Kể từ Scala 2.9, tùy chọn -Xexperimental
phải được bật để sử dụng Dynamic
.
Ví dụ về ngôn ngữ được nhập tĩnh * có * có nội dung được tích hợp sẵn này, hãy xem [opDispatch in D] (http://www.digitalmars.com/d/2.0/operatoroverloading.html #Dispatch). 'opDispatch' là một phương thức mẫu được truyền tên phương thức và kiểu tham số tại thời gian biên dịch, vì vậy bạn có thể sử dụng lập trình meta để xác định cách" chạy "phương thức còn thiếu. Tất nhiên, mọi thứ vẫn được giải quyết tĩnh bởi trình biên dịch. [Liên quan SO câu hỏi] (http://stackoverflow.com/questions/3098242/fast-vector-struct-that-allows-i-and-xyz-operations-in-d). Các API phản chiếu – shambulator