在raku中,当不匹配的值时,常规不返回吗?

发布于 2025-02-12 13:32:31 字数 1691 浏览 1 评论 0 原文


根据 raku documentation ,常规 first 首先返回 nil 当不匹配值时。但是,为什么行不说($ result === nil); (下图)打印 true

sub MAIN()
  {
  my @myNumberList is Array[Int] = [2, 2, 5, 7] ;
  my $result = @myNumberList.first( {$_ > 10} ) ;
  say '$result' ;
  say $result ;
  say $result.WHAT ;
  say ($result === Nil) ;
  } # end sub MAIN

程序输出是…

$result
(Any)
(Any)
False

更新

我的目标是确定列表或数组是否包含满足给定谓词的一个或多个元素。在以下示例程序中, elems 例程返回一个大于0的值,并且仅当给定列表或数组中至少包含一个满足相应调用中给出的谓词> >的谓词GREP

sub MAIN()
  {
  my $myList = (2, 2, 5, 7) ;
  say '$myList' ;
  say $myList ;
  say $myList.WHAT ;

  my $grepResult1 = $myList.grep( * > 10, :p ) ;
  say '$grepResult1' ;
  say $grepResult1 ;
  say $grepResult1.WHAT ;
  say ($grepResult1.elems <= 0) ;

  my $grepResult2 = $myList.grep( * > 4, :p ) ;
  say '$grepResult2' ;
  say $grepResult2 ;
  say $grepResult2.WHAT ;
  say ($grepResult2.elems <= 0) ;

  my @myArray = [2, 2, 5, 7] ;
  say '@myArray' ;
  say @myArray ;
  say @myArray.WHAT ;

  my $grepResult3 = @myArray.grep( * > 10, :p ) ;
  say '$grepResult3' ;
  say $grepResult3 ;
  say $grepResult3.WHAT ;
  say ($grepResult3.elems <= 0) ;
  } # end sub MAIN

程序输出是…

$myList
(2 2 5 7)
(List)
$grepResult1
()
(Seq)
True
$grepResult2
(2 => 5 3 => 7)
(Seq)
False
@myArray
[2 2 5 7]
(Array)
$grepResult3
()
(Seq)
True


According to Raku documentation, routine first returns Nil when no values match. However, why doesn't the line say ($result === Nil) ; (below) print True?

sub MAIN()
  {
  my @myNumberList is Array[Int] = [2, 2, 5, 7] ;
  my $result = @myNumberList.first( {$_ > 10} ) ;
  say '$result' ;
  say $result ;
  say $result.WHAT ;
  say ($result === Nil) ;
  } # end sub MAIN

Program output is …

$result
(Any)
(Any)
False

Update

My goal was to determine whether a list or an array contains one or more elements satisfying a given predicate. In the following sample program, the elems routine returns a value that is greater than 0 if and only if the given list or array contains at least one element satisfying the predicate given in the corresponding call to grep .

sub MAIN()
  {
  my $myList = (2, 2, 5, 7) ;
  say '$myList' ;
  say $myList ;
  say $myList.WHAT ;

  my $grepResult1 = $myList.grep( * > 10, :p ) ;
  say '$grepResult1' ;
  say $grepResult1 ;
  say $grepResult1.WHAT ;
  say ($grepResult1.elems <= 0) ;

  my $grepResult2 = $myList.grep( * > 4, :p ) ;
  say '$grepResult2' ;
  say $grepResult2 ;
  say $grepResult2.WHAT ;
  say ($grepResult2.elems <= 0) ;

  my @myArray = [2, 2, 5, 7] ;
  say '@myArray' ;
  say @myArray ;
  say @myArray.WHAT ;

  my $grepResult3 = @myArray.grep( * > 10, :p ) ;
  say '$grepResult3' ;
  say $grepResult3 ;
  say $grepResult3.WHAT ;
  say ($grepResult3.elems <= 0) ;
  } # end sub MAIN

Program output is …

$myList
(2 2 5 7)
(List)
$grepResult1
()
(Seq)
True
$grepResult2
(2 => 5 3 => 7)
(Seq)
False
@myArray
[2 2 5 7]
(Array)
$grepResult3
()
(Seq)
True

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

2025-02-19 13:32:31

“避免陷阱以避免” 文档页面上的有趣问题。请参阅特定的小标题:。另外, nil nil nil 的Raku文档页面。

推测的那样 - 是在右侧 上使用连接 使用智能

简短的答案 - 就像我

sub MAIN()
  {
  my @myNumberList is Array[Int] = [2, 2, 5, 7] ;
  my $result = @myNumberList.first( {$_ > 10} ) ;
  say '$result' ;
  say $result ;
  say $result.WHAT ;

"\n".say;

  say  Nil ~~ all($result);  #True
  say  Nil ~~ any($result);  #True
  say  Nil ~~ one($result);  #True
  say  Nil ~~ none($result); #False

"\n".say;

  my $result2 = @myNumberList.first( {$_ < 10} ) ;
  say  Nil ~~ all($result2);  #False
  say  Nil ~~ any($result2);  #False
  say  Nil ~~ one($result2);  #False
  say  Nil ~~ none($result2); #True

  } # end sub MAIN

可以

$result
(Any)
(Any)


True
True
True
False


False
False
False
True

匹配 可以简化上述代码(并清理输出)。

  1. 可以使用 .Defined

    for 结果上面的(其中没有匹配值) SAD SAD SADE $结果,

    如果$ result.defined; 什么都没有返回;

  2. 对于 result2 上面(其中第一个匹配值为2) say $ result2如果$ result2.defined; 返回 2 。。。 P>

要进一步阅读以了解上面发布的SmartMatch解决方案是如何产生的,请查看以下github问题:”通常,~~的左侧不应是自动线程”

[此外,((出于混淆读者的危险),请查看以下 raku 代码发布在以下 perl5 文档页面:https://perldoc.perl。 org/perlsyn#差异与raku]。

附录:进行有关'do-something-fly-if定义的'习惯的讨论,请参见Damian Conway的演讲“巨人肩上” ,其中包括他的用户定义?= (“分配 - 如果定义”)操作员的代码。

Interesting question that appears to be (somewhat) addressed on the "Traps To Avoid" documentation page. See the specific subheading: "Assignment of Nil can produce a different value, usually 'Any' ". Also, the Raku documentation page on class Nil .

The short answer--as near as I can surmise--is to use smartmatching with a Junction on the right-hand-side:

Sample Code:

sub MAIN()
  {
  my @myNumberList is Array[Int] = [2, 2, 5, 7] ;
  my $result = @myNumberList.first( {$_ > 10} ) ;
  say '$result' ;
  say $result ;
  say $result.WHAT ;

"\n".say;

  say  Nil ~~ all($result);  #True
  say  Nil ~~ any($result);  #True
  say  Nil ~~ one($result);  #True
  say  Nil ~~ none($result); #False

"\n".say;

  my $result2 = @myNumberList.first( {$_ < 10} ) ;
  say  Nil ~~ all($result2);  #False
  say  Nil ~~ any($result2);  #False
  say  Nil ~~ one($result2);  #False
  say  Nil ~~ none($result2); #True

  } # end sub MAIN

Returns:

$result
(Any)
(Any)


True
True
True
False


False
False
False
True

Alternatively, you can simplify the above code (and clean up your output) using .defined:

  1. for result above (where there are no matching values) say $result if $result.defined; returns nothing;

  2. for result2 above (where the first matching value is 2) say $result2 if $result2.defined; returns 2.

For further reading to understand how the smartmatch solution(s) posted above came about, look at the following Github issue: "In general, the left side of ~~ should not be auto-threading".

[Also, (at the risk of confusing the reader), take a look at the Raku code posted on the following Perl5 doc page: https://perldoc.perl.org/perlsyn#Differences-from-Raku ].

ADDENDUM: For a discussion on the 'do-something-only-if-defined' idiom in Raku, see Damian Conway's talk "On The Shoulders of Giants", which includes his code for a user-defined ?= ("assign-if-defined") operator.

メ斷腸人バ 2025-02-19 13:32:31

tl; dr 是, first 返回 nil 当不匹配的值时。获得想要的一种方法是绑定结果(使用:= ),而不是分配( = )。

一个简单的解决方案

开关从分配运算符( = )到:= ):

sub MAIN()
  {
  my @myNumberList is Array[Int] = [2, 2, 5, 7] ;
  my $result := @myNumberList.first( {$_ > 10} ) ;     # <-- Add colon
  say '$result' ;
  say $result ;
  say $result.WHAT ;
  say ($result === Nil) ;
  } # end sub MAIN

显示:

$result
Nil
Nil
True

原始代码中发生了什么

在raku中,不例行第一个返回 nil 当不匹配的值时?

是的。那不是问题。

nil 表示“缺乏值...”。。

因此不要将其视为一个值,例如 42 'string''< /代码>或空列表²。

nil 分配变量将变量的值重置为其默认值:

my $foo is default(42) = Nil;
say $foo; # 42

default 变量的默认值是 任何³,所以:

my $bar = Nil;
say $bar; # (Any)

这就是发生的事情在您的原始代码中。

选项

您可以设置 $ result 的默认值为 nil ,因此当您分配 nil 时,您会得到什么您想要:

my $result is default (Nil) = @myNumberList.first( {$_ > 10} ) ;

但这很麻烦。很少需要。

通常,如果要变量到 keep a nil ,则只是 bind 它而不是分配:

my $qux := Nil;      # <-- use `:=` instead of `=`
say $qux; # Nil

只需设置您的心理模型为了匹配Raku的工作,您会发现这都非常简单。

footnotes〜

per 其doc nil 是“没有值或良性失败”。如果您调用 first 在与谓词匹配的值列表中找到第一个值,则适用“缺乏值”的方面,但没有这样的值。如果您调用首先,则适用“良性失败”,并且遇到某些错误条件,并且决定其良性,但应该终止其处理,或者抛出一个例外,以使得进一步的评估继续以代码继续,以至于接收由 first 返回的值。

当您阅读此脚注时,您可能会认为这两种情况最好单独处理。但是,如果您想进一步考虑,希望他们能像同一枚硬币的两个方面一样工作。任何称为代码都可以返回 nil ,并且调用代码知道呼叫的结果是没有值。这可能是由于完全正常的处理,该处理无值,或者是由于遇到错误的处理,但是该错误是由所谓的代码考虑到如此良性,以至于不值得通过返回 nil ,或导致抛出的例外,随后处理以清除误差条件 - 从而将处理返回正常状态。 Raku优雅而实用的 nil 是我❤raku的另一个原因。

²空列表仍然是一个值。尽管一个空的。

³任何都是一种类型。当被视为“值”时,它是 type object代码>任何或子类型。它为变量和参数提供了自然的默认值。

⁴我怀疑我写了我的“正义...”句子来冒犯了人们。我想到了删除或编辑它,但是后来人们不会有 @jubilatious1的评论的背景,而我的观点,我认为这是 @jubilatious1被误解的好主意,它会丢失。我现在将此脚注留下来,希望有人认为这是一个问题,并且/或者如果我将其删除是个好主意,或者相反,请与我互动。

TL;DR Yes, first returns Nil when no values match. One way to get what you want is to bind the result (with :=) instead of assigning it (with =).

A simple solution

Switch from the assignment operator (=) to the binding operator (:=):

sub MAIN()
  {
  my @myNumberList is Array[Int] = [2, 2, 5, 7] ;
  my $result := @myNumberList.first( {$_ > 10} ) ;     # <-- Add colon
  say '$result' ;
  say $result ;
  say $result.WHAT ;
  say ($result === Nil) ;
  } # end sub MAIN

displays:

$result
Nil
Nil
True

What's happening in your original code

In Raku, doesn't routine first return Nil when no values match?

Yes. That's not the problem.

Nil represents "Absence of a value ...".¹

So don't think of it as a value like, say, 42 or 'string' or an empty list².

Assigning Nil to a variable resets the variable's value to its default:

my $foo is default(42) = Nil;
say $foo; # 42

The default default value for a variable is Any³, so:

my $bar = Nil;
say $bar; # (Any)

That's what happened in your original code.

Options

You could set $result's default to Nil so that when you assign Nil to it you get what you want:

my $result is default (Nil) = @myNumberList.first( {$_ > 10} ) ;

But that's cumbersome. And seldom desirable.

Usually, if you want a variable to keep a Nil, you just bind it instead of assigning it:

my $qux := Nil;      # <-- use `:=` instead of `=`
say $qux; # Nil

Just set your mental model to match what Raku's doing and you'll find it's all really simple.

Footnotes

¹ Per its doc, Nil is "Absence of a value or a benign failure". The "Absence of a value" aspect applies if you call first to find the first value in some list of values that matches a predicate, but there were no such values. The "benign failure" applies if you call first and it encounters some error condition and either decides it's benign but ought terminate its processing, or throws an exception that gets handled such that further evaluation continues with the code that receives the value returned by first.

As you read this footnote you might think these two cases would best be handled separately. But if you think further you will hopefully see that they work beautifully as two sides of the same coin. Any called code can return Nil, and calling code knows that the result of the call is an absence of a value. This may be due to entirely normal processing which yields no value, or due to processing that encountered an error, but that error was either considered by the called code as so benign as to not be worth reporting to the caller other than by returning Nil, or resulted in an exception being thrown that was subsequently handled to clear the error condition -- thus returning processing to normal status. Raku's elegant and practical Nil is yet another reason why I ❤ Raku.

² An empty list is a still a value. Albeit an empty one.

³ Any is a type. When treated as a "value" it's a type object representing an undefined value of type Any or a subtype thereof. It makes a natural default default value for variables and parameters.

⁴ I suspect I offended folk by writing my "Just ..." sentence. I thought about deleting or editing it, but then folk wouldn't have context for @jubilatious1's comment and my point, which I think is a good one that @jubilatious1 misunderstood, would be lost. I'm leaving it in with this footnote for now in the hope someone will engage with me if they think it is a problem and/or if it would be a good idea for me to remove it or, conversely, unstrike it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文