2014-11-10 11 views
5

Tôi muốn xác định hàm f(x, t::Type) thực thi hành vi khác nhau tùy thuộc vào việc isa(x, t). Giả sử tôi muốn gọi b1(x) nếu có, và b2(x) nếu không.Trong Julia, làm cách nào để thực hiện phương thức gửi đúng trên các đối số của các loại (siêu) cũng được cung cấp bởi người gọi?

Tôi biết rằng tôi có thể làm một kiểm tra năng động trong thời gian chạy như thế này:

function f(x, t::Type) 
    if isa(x, t) 
    b1(x) 
    else 
    b2(x) 
    end 
end 

Tuy nhiên, có một cách để làm điều này hoàn toàn với phương pháp công văn tham số? Ví dụ, nếu tôi xác định

f{T}(x::T, t::Type{T}) = b1(x) 
f(x, t::Type) = b2(x) 

cho f(1, Int)f(1.0, Int) hành vi đúng được gọi. Nhưng tôi muốn điều này cũng làm việc cho tất cả các phân nhóm của t:

f(1, Number) 

Điều này thực sự gọi b2 vì chữ ký đầu tiên của f không phù hợp. Điều thú vị là, mặc dù, f(x::Number, t::Type{Number}) = b1(x) sẽ khớp trong trường hợp này.

Tôi có thiếu điều gì đó hiển nhiên ở đây không?

Đây dường như là lỗi và được sửa trong 0.4.


Câu hỏi:

  1. Tại sao f{T}(x::T, t::Type{T}) không phù hợp cho f(1, Number), mặc dù có là một loại thay thế cho T (Number) mà sẽ phù hợp?

  2. Sử dụng f{T2, T1 <: T2}(x::T1, t::Type{T2}) hoặc một cái gì đó tương tự không hoạt động vì tất cả các tham số tĩnh chỉ xuất hiện sau khi danh sách tham số tĩnh hoàn chỉnh được đóng lại. Tại sao?

  3. Có bất kỳ hình phạt về hiệu suất nào khi sử dụng phương pháp động không?

  4. gì về việc xác định các phương pháp như một chức năng bên trong, vì vậy tôi có thể ràng buộc t cho một biến địa phương, như thế này: function f(x, t::Type); g(x::t) = b1(x); g(x) = b2(x); g(x) end

    đó làm việc, nhưng chi phí thực hiện là gì?

  5. Cách thành ngữ/ưu tiên để giải quyết vấn đề này là gì?

(Tôi đã cố gắng này trên 0.3.2.)

+1

Tôi có phiên bản Julia Version 0.4.0-dev + 1307 và f (1, Number) gọi b1 –

+0

Bạn nói đúng, tôi đã xác nhận rằng điều này hoạt động trên 0.4.0-dev + 1521. Cảm ơn – user4235730

Trả lời

5

Để trả lời câu hỏi của bạn:

  1. AFAICT nó cần. Như user3580870 đã nhận xét, điều này dường như hoạt động ở Julia 0.4.
  2. Đây là "công văn tam giác" và chưa được triển khai. Xem #3766.
  3. Tùy thuộc. Trình biên dịch có thể đánh giá isa(x, t) tại thời gian biên dịch và loại bỏ nhánh. Tuy nhiên, vẫn còn một số cách có thể sử dụng isa có thể là tối ưu:
    • Nếu hai chi nhánh trở lại các loại khác nhau, loại suy luận sẽ không thể suy ra kiểu trả về đúng bởi vì nó xảy ra trước khi isa(x, t) được lập thành một hằng số . (Điều này có thể sẽ tốn kém; các sự phân tách có thể khác dưới đây có thể không phải là vấn đề lớn.)
    • Nếu một nhánh thực hiện phân bổ đống nhưng nhánh kia thì không, khung GC không cần thiết có thể được phát ra.
    • Chức năng có thể không được gạch chân.
  4. Một chức năng bên trong sẽ có vấn đề hiệu suất tương tự như sử dụng isa và nhiều hơn nữa. Do Julia 0.5, một hàm bên trong nên hiệu quả như một hàm mức cao nhất trong trường hợp này.
  5. Gửi lỗi ;-). Tôi nghĩ rằng đây là nghĩa vụ phải làm việc. Có thể bất cứ điều gì cố định trong 0.4 này có thể được trả về 0,3. Nhưng thất bại, isa không phải là một cách tiếp cận xấu với điều kiện là nó không gây ra vấn đề suy luận kiểu.
+0

Cảm ơn bạn vì câu trả lời nhanh và tuyệt vời này. Điều này thực sự làm việc trong 0.4, mà giải quyết vấn đề của tôi. – user4235730

+0

Nhưng bạn có thể vui lòng giải thích về các vấn đề hiệu suất với cách tiếp cận chức năng bên trong hay hướng tôi đến một nơi mà tôi có thể tìm hiểu thêm? Tại sao điều này lại tệ hơn nhiều so với việc xác định các hàm ở cấp cao nhất? Và chỉ cần làm rõ: Nếu các hàm được gọi thực sự trả về các đối tượng của các kiểu khác nhau, thì 'f {T} (x :: T, t :: Loại {T}) = b1 (x)' -ứng dụng sẽ nhanh hơn? – user4235730

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