Hạn chế chữ ký trong vai trò trong raku


8

Có thể tôi đang thiếu một cái gì đó, nhưng tôi muốn biết liệu có lý do chính đáng tại sao mã này nên biên dịch không

role L {
  method do-l (Int, Int --> Int ) { ... }
}

class A does L {
  method do-l (Int $a, Real $b --> Str) {
    .Str ~ ": Did you expect Int?" with $a + $b
  }
}

my $a = A.new;

say $a.do-l: 2, 3.323

Điều này sẽ xuất

5.323: Did you expect Int?

Tôi tò mò nếu ai đó biết một cách để trình biên dịch ít nhất đưa ra một số cảnh báo với chữ ký được thực hiện của vai trò L.


2
Sản lượng dự kiến ​​của bạn là gì? Những gì bạn đã thể hiện là những gì tôi mong đợi. Các L.do-lcó một phương pháp mà không phù hợp, và trong mọi trường hợp, phương pháp lớp được ưu tiên, vì vậy trên cả hai cơ sở, A's do-lnên được gọi. Việc thêm một IntRealsẽ là a Real.
user0721090601

1
À, giờ tôi hiểu rồi. Bạn thực sự đang hỏi về toán tử yada ...(phải thừa nhận, trong khi nó có ý nghĩa trong mã sản xuất, ở đây nó có thể gây nhầm lẫn)
user0721090601

Bạn không thể khởi tạo vai trò nếu một phương thức được đặt ra, nhưng không có vấn đề gì trong việc khởi tạo các lớp. `class L {phương thức yadda {,}}; nói L.new.raku`
jjmerelo

2
"Bạn không thể khởi tạo vai trò nếu một phương thức bị lỗi" Người đọc có thể hiểu sai ý kiến ​​này. Bạn không thể khởi tạo vai trò, thời gian. Chúng chỉ là những mảnh vỡ của một lớp học. Nếu bạn cố gắng khởi tạo một vai trò, raku cho rằng bạn có nghĩa là khởi tạo một lớp trống thực hiện vai trò đó và thực hiện điều đó cho bạn. Đương nhiên, điều này thất bại nếu vai trò đó chứa một phương thức còn sơ khai, bởi vì thực thi là toàn bộ ý nghĩa và ý nghĩa của một phương thức còn sơ khai trong một vai trò. Ngược lại, sơ khai trong một lớp chỉ có nghĩa là "Tôi chưa viết mã này".
raiph

2
@jjmerelo Có, đó là một kiểu chơi chữ ("thay thế hoặc phá vỡ hệ thống loại"). Người mà chúng ta đang nói ở đây ( role foo {}.newđược tự động chuyển đổi thành một cái gì đó giống như vậy anon class foo does role foo {}.new) minh bạch đến mức dân gian có thể không nhận ra đó là một cách chơi chữ, do đó nhận xét trước của tôi. Thật tuyệt khi cách chơi chữ này một tay cho phép thay thế chính cho thừa kế và ủy quyền, cụ thể là tổ chức và xây dựng các loại bằng cách sử dụng thành phần , nhưng imo, dân gian quan trọng không hoàn toàn đánh mất rằng đó .newlà một cách chơi chữ.
raiph

Câu trả lời:


6

ném một số cảnh báo với chữ ký thực hiện của vai trò L.

Bạn nhận được điều đó nếu bạn thêm tiền tố vào khai báo phương thức multi:

role L {
  multi method do-l (Int, Int --> Int ) { ... }
}

Với chương trình này, chương trình của bạn sẽ hiển thị:

===SORRY!=== Error while compiling ...
Multi method 'do-l' with signature :(A: Int $, Int $, *%_ --> Int)
must be implemented by A because it is required by a role ...

Tôi muốn biết liệu có lý do chính đáng tại sao mã này sẽ biên dịch [mà không có multi]

Tôi nghĩ rằng mục đích thiết kế là để hỗ trợ hai khái niệm về thành phần đa hình:

  • Nếu không có sựmulti , thi hành chỉ liên quan đến sự tồn tại của một phương pháp với quyền tên ; các tham số được bỏ qua.

  • Với việcmulti thực thi bao gồm tên và tất cả các tham số ( hoặc một số ).

Cá nhân tôi đảm nhận liệu có lý do chính đáng cho:

  • Hỗ trợ hai hương vị của đa hình phương pháp? Đôi khi thực thi tuân thủ nghiêm ngặt chữ ký là hữu ích. Đôi khi nó cản trở.

  • Phân biệt chúng qua multi? Thực thi chữ ký đầy đủ yêu cầu các lớp / vai trò thực hiện có một phương thức với chính xác chữ ký đó. Nhưng điều gì sẽ xảy ra nếu một lớp / vai trò thực hiện muốn xử lý intthay vì Intcho một tham số? Raku thỏa hiệp. Được cung cấp một lớp / vai trò thực hiện có một phương thức tuân thủ chính xác, nó cũng có thể có các biến thể. Cách hoàn hảo để truyền đạt điều này là tiền tố một phương pháp sơ khai với multi.

  • Có tên mặc định chỉ là đa hình? Chúng tôi có thể đã chọn multingữ nghĩa làm mặc định và người dùng sẽ viết onlytiền tố nếu họ chỉ muốn tên đa hình. Nhưng điều đó sẽ đảo ngược tình huống thông thường (tức là bỏ qua các phương pháp sơ khai). Tổng quát hơn, mục đích là Raku cung cấp một phạm vi nghiêm ngặt cho các tính năng của nó, từ thoải mái đến tăng tốc và chọn mặc định cho bất kỳ tính năng cụ thể nào được đánh giá đúng dựa trên phản hồi từ người dùng trong nhiều năm qua.

Điều gì xảy ra nếu mặc định có vẻ không đúng? Điều gì xảy ra nếu phạm vi nghiêm ngặt hiện tại không đủ? Điều gì xảy ra nếu một nhóm nghĩ rằng chúng ta nên đi bên trái và một nhóm khác nghĩ rằng chúng ta nên đi bên phải?

Raku có (imo) các cơ chế quản trị đáng chú ý để hỗ trợ sự phát triển ngôn ngữ do người dùng điều khiển. Ở cấp độ cao nhất có các yếu tố như kiến trúc bện . Ở cấp độ dưới cùng có các yếu tố như các loại phiên bản . Ở giữa là các yếu tố như RoleToClassApplierlàm trung gian cho quá trình áp dụng vai trò cho một lớp, đó là điểm mà tại đó một phương thức cần thiết phải được tìm thấy hoặc việc xây dựng lớp sẽ thất bại. Nói tóm lại, nếu ngôn ngữ không hoạt động theo cách bạn muốn, bao gồm cả những thứ như sự nghiêm ngặt, ít nhất về nguyên tắc, bạn có thể thay đổi ngôn ngữ đó.


1
Wow đây chính xác là thông tin mà tôi đang tìm kiếm, tôi ước rằng tôi đã đọc về điều này trong các tài liệu raku cho các vai trò, hoặc có thể tôi đã bỏ lỡ, nếu điều này không có ở đó chắc chắn sẽ giúp nhiều người viết các vai trò súc tích, ngay từ đầu tầm nhìn phải đặt multivào ths vẫn còn không trực quan, nhưng bây giờ nhờ lời giải thích của bạn, nó thực sự có ý nghĩa.
margolari

1
@margolari Thật tốt khi biết bạn có thông tin bạn cần. Xem thêm github.com/Raku/doc/issues/3330
raiph

2

Tôi giả sử ở đây bạn đang hỏi về lý do tại sao không có cảnh báo nào liên quan đến việc khai thác. Thật vậy, thông thường một phương pháp sơ khai phải được thực hiện - nhưng đó là phương pháp.

Bạn có thể thấy cách các vai trò được tạo thành lớp ở đây trong nguồn của Rakudo ( $yadavề cơ bản là $is-stubbed):

if $yada {
    unless has_method($!target, $name, 0)
            || $!target.HOW.has_public_attribute($!target, $name) {
        my @needed;
        for @!roles {
            for nqp::hllize($_.HOW.method_table($_)) -> $m {
                if $m.key eq $name {
                    nqp::push(@needed, $_.HOW.name($_));
                }
            }
        }
        nqp::push(@stubs, nqp::hash('name', $name, 'needed', @needed, 'target', $!target));
    }
}

Vì vậy, bạn có thể thấy rằng logic chỉ để xem liệu một phương thức có tồn tại cùng tên hay không. Chắc chắn có thể viết một mô-đun sẽ cập nhật logic này bằng cách tăng phương thức áp dụng () hoặc thay thế hoàn toàn RoleToClassApplierlớp. Tuy nhiên, nó có thể khó khăn. Ví dụ: xem xét:

class Letter { }
class A is Letter { } 
class B is Letter { }

role Foo {
  method foo (Letter) { ... }
}

class Bar does Foo { 
  method foo (A) { 'a' }
  method foo (B) { 'b' }
}

Chúng ta có nên xem xét phương pháp sơ khai để được thực hiện chính xác? Nhưng một người khác sau đó có thể nói class C is Lettervà đột nhiên nó không được thực hiện. (Tất nhiên, chúng ta có thể nói rằng logic tốt nhất sẽ được yêu cầu, ít nhất là, giống hệt hoặc siêu kiểu, nhưng điều đó gây khó chịu hơn mức cần thiết cho các ngôn ngữ động, IMO).

Không có, AFAICT, một phương thức được gọi là vai trò trong quá trình sáng tác cũng tham chiếu lớp (thực ra, không có phương thức nào được gọi cả add_method), vì vậy không có cách nào để viết séc của riêng bạn trong vai trò đó. (nhưng tôi có thể sai, có thể raiph, lizmat hoặc jnthn có thể sửa tôi).

Khuyến nghị của tôi trong trường hợp này là, thay vì khai thác nó, chỉ cần thêm vào một tuyên bố chết:

role L {
  method do-l(Int $a, Int $b --> Int) {
    die "SORRY! Classes implementing role L must support the signature (Int, Int)";
  }
}

Điều này sẽ không nắm bắt được nó trong quá trình biên dịch, nhưng nếu tại bất kỳ thời điểm nào, một phương thức khác Lcần phải gọi tới do-l(Int, Int)trêneveneven nếu lớp soạn thảo thực hiện các chữ ký khác, thì nó sẽ được gọi và lỗi được xử lý khá nhanh.


Err, tôi đã không nghĩ về việc tạo ra sự khác biệt lớn vì raiph đã tìm thấy tôi nên cập nhật câu trả lời theo cách đó
user0721090601
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.