2017-08-01 16 views
5

Cách Perl 6 để nói sự khác biệt giữa một đối số và không có đối số trong một khối không có chữ ký rõ ràng là gì? Tôi không có bất kỳ thực tế sử dụng cho điều này, nhưng tôi tò mò.Đó là một đối số hoặc không có đối với một khối Perl 6?

Một khối không có chữ ký rõ ràng đặt giá trị vào $_:

my &block := { put "The argument was $_" }; 

Chữ ký thực sự là ;; $_? is raw. Đó là một đối số tùy chọn. Biến số @_ không được xác định trong khối vì không có chữ ký rõ ràng.

Có là không có đối số, nơi $_ sẽ được undefined:

&block(); # no argument 

Nhưng cũng có một tình huống một đối số nơi $_ sẽ được định nghĩa. Một đối tượng loại luôn undefined:

&block(Int); 

Nhưng, một $_ với không có gì ở trong đó thực sự là một Any (chứ không phải là, nói, Nil). Tôi không thể biết sự khác biệt giữa hai trường hợp sau đây:

&block(); 
&block(Any); 

Dưới đây là một ví dụ nữa:

my $block := { 
    say "\t.perl is {$_.perl}"; 

    if $_ ~~ Nil { 
     put "\tArgument is Nil" 
     } 
    elsif ! .defined and $_.^name eq 'Any' { 
     put "\tArgument is an Any type object" 
     } 
    elsif $_ ~~ Any { 
     put "\tArgument is {$_.^name} type object" 
     } 
    else { 
     put "\tArgument is $_"; 
     } 
    }; 

put "No argument: "; $block(); 
put "Empty argument: "; $block(Empty); 
put "Nil argument: "; $block(Nil); 
put "Any argument: "; $block(Any); 
put "Int argument: "; $block(Int); 

Thông báo sự không tranh cãi và bất kỳ hình thức lập luận cho thấy những điều tương tự:

No argument: 
    .perl is Any 
    Argument is an Any type object 
Empty argument: 
    .perl is Empty 
    Argument is Slip type object 
Nil argument: 
    .perl is Nil 
    Argument is Nil 
Any argument: 
    .perl is Any 
    Argument is an Any type object 
Int argument: 
    .perl is Int 
    Argument is Int type object 

Trả lời

1

Đây là cách tôi giải quyết này. Tôi rất muốn làm điều này một cách rõ ràng hơn nhưng sự thông minh của ngôn ngữ đã cản đường và tôi phải làm việc xung quanh nó. Điều này làm việc cho các tham số vị trí nhưng có những shenanigans sâu hơn cho các tham số được đặt tên và tôi sẽ không xử lý những thông số đó ở đây.

Tôi có một câu hỏi khác, Why does constraining a Perl 6 named parameter to a definite value make it a required value?, nơi các câu trả lời được làm rõ rằng thực tế không có thông số tùy chọn. Chỉ có các tham số có giá trị mặc định và có giá trị ngầm định mặc định nếu tôi không chỉ định một giá trị mặc định.

Điểm mấu chốt của vấn đề của tôi là tôi muốn biết khi nào tôi đưa ra thông số một giá trị và khi tôi không làm. Tôi cung cấp cho nó một giá trị thông qua một đối số hoặc một mặc định rõ ràng. Một mặc định ngầm định là một kiểu đối tượng của kiểu đúng. Đó là Any nếu tôi không chỉ định loại. Mặc định ngầm đó phải đáp ứng bất kỳ ràng buộc nào mà tôi chỉ định.

Mục tiêu đầu tiên là hạn chế chặt chẽ các giá trị mà người dùng có thể cung cấp khi họ gọi mã. Nếu giá trị không xác định không hợp lệ thì chúng không được phép chỉ định giá trị đó.

Mục tiêu thứ hai là dễ dàng phân biệt các trường hợp đặc biệt trong mã. Tôi muốn giảm số lượng kiến ​​thức đặc biệt một số phần của mã sâu hơn cần biết.

Tôi có thể nhận được trường hợp thứ ba (nơi tôi biết không có đối số hoặc mặc định phù hợp) bằng cách chỉ định rõ ràng một giá trị đặc biệt mà tôi biết không thể là bất cứ điều gì có ý nghĩa khác. Có một giá trị thậm chí còn vô nghĩa hơn Any. Đó là Mu. Đó là giá trị không xác định nhất của tất cả các giá trị không xác định. Any là một trong hai kiểu con của Mu (số khác là Junction) nhưng bạn hầu như không bao giờ thấy một số Mu kết thúc bằng một trong các giá trị của bạn trong mã thông thường. Những thứ không xác định trong mã người dùng bắt đầu tại Any.

Tôi có thể tạo ràng buộc kiểm tra loại tôi muốn hoặc cho Mu và đặt mặc định là Mu. Nếu tôi thấy một số Mu Tôi biết không có tranh cãi nào và rằng đó là số Mu vì ràng buộc của tôi đã đặt ra điều đó.

Vì tôi đang sử dụng Mu có một số điều tôi không thể làm, như sử dụng toán tử ===. Kết hợp thông minh sẽ không hoạt động vì tôi không muốn kiểm tra chuỗi kế thừa. Tôi có thể kiểm tra tên đối tượng trực tiếp:

my $block := -> 
    $i where { $^a.^name eq 'Mu' or $^a ~~ Int:D } = Mu 
    { 
    say "\t.perl is {$i.perl}"; 

    put do given $i { 
     when .^name eq 'Mu' { "\tThere was no argument" } 
     when Nil    { "\tArgument is Nil"  } 
     when (! .defined and .^name eq 'Any') { 
      "\tArgument is an Any type object" 
      } 
     when .defined { 
      "\tArgument is defined {.^name}" 
      } 
     default { "\tArgument is {.^name}" } 
     } 
    }; 

put "No argument: ";   $block(); 
put "Empty argument: ";  try $block(Empty); # fails 
put "Nil argument: ";  try $block(Nil); # fails 
put "Any type argument: "; try $block(Any); # fails 
put "Int type argument: "; try $block(Int); # fails 
put "Int type argument: "; $block(5); 

Bây giờ hầu hết các yêu cầu này đều thất bại vì chúng không chỉ định đúng thứ.

Nếu đây là những thói quen tôi có thể làm cho nhiều cho một số ít trường hợp nhưng đó là một giải pháp thậm chí còn tồi tệ hơn cuối cùng. Nếu tôi có hai tham số, tôi cần bốn multis. Với ba thông số như vậy tôi cần sáu. Đó là rất nhiều mã soạn sẵn. Tuy nhiên, khối không phải là thói quen vì vậy đó là tranh luận ở đây.

2
{ put $_.perl } 

Tương tự như sau: (không hoạt động)

-> ;; $_? is raw = CALLERS::<$_> { put $_.perl } 

Kể từ khi mặc định is default cho $_ bên ngoài của khối là Any, nếu bạn không đặt bất cứ điều gì vào $_ trước khi bạn gọi hàm bạn nhận được Any.


Để có được một cái gì đó ở tất cả tương tự như nơi bạn có thể biết sự khác biệt sử dụng một Capture:

my &foo = -> ;; |C ($_? is raw) { 
    unless C.elems { 
     # pretend it was defined like the first Block above 
     CALLER::<$_> := CALLER::CALLERS::<$_> 
    } 
    my $called-with-arguments := C.elems.Bool; 


    if $called-with-arguments { 
     say 'called with arguments'; 
    } else { 
     say 'not called with arguments'; 
    } 
} 
+0

Tôi biết tất cả điều đó. Tôi hỏi về trường hợp tôi đặt 'Any' vào đó. –

+0

@briandfoy Nếu bạn cần thông tin này, không sử dụng tính năng được thiết kế để tạo sự khác biệt vô hình. –

+1

Nó không phải là tôi cần nó. Tôi đang xem cách ngôn ngữ hoạt động và các ranh giới của nó để tôi có thể nói cho người khác biết họ sẽ không thể làm gì. –

3

Theo như tôi biết, cách duy nhất để biết số các thông số thông qua mà không có một chữ ký rõ ràng, là sử dụng @_ bên trong cơ thể, sẽ tạo chữ ký :(*@_).

my &block := { say "Got @_.elems() parameter(s)" }; 
block;    # Got 0 parameter(s) 
block 42;   # Got 1 parameter(s) 
dd block.signature; # :(*@_) 

Yeah, tốt cũ @_ vẫn còn đó, nếu bạn muốn nó :-)

+1

Đó là bạn không muốn giá trị trong '$ _'. Và các giá trị trong @_ là không thay đổi. –

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