应用于 sub 时,.first 和 .return 是什么?

zen*_*nix 8 raku

我在某处找到了该运算符,当我在https://docs.raku.org/routine/andthen中查找它时,我发现了这个:

\n
#!/bin/env raku\nsub load-data\n{\n  rand  > .5 or return; # simulated load data failure; return Nil\n  (rand > .3 ?? \'error\' !! \'good data\') xx 10 # our loaded data \n}\n\nload-data.first: /good/ andthen say "$_ is good";\n# OUTPUT: \xc2\xab(good data is good)\xe2\x90\xa4\xc2\xbb \n\nload-data() andthen .return; # return loaded data, if it\'s defined \ndie "Failed to load data!!";  \n
Run Code Online (Sandbox Code Playgroud)\n

那么,当应用于 subs 时,它是如何.first工作.return的?\n我以前从未见过这样的事情。

\n

Sil*_*olo 11

那么,应用于 subs 时如何工作.first.return

事实并非如此。您没有调用.first .return调用某个Sub对象。

当 Raku 中的子例程不带参数出现时,就会调用它。因此,只需编写load-data其自己的调用 load-data即可,就像添加括号一样。(注意:如果你获取子例程对象本身,你使用一个&印记,&load-data子例程对象也是如此)所以这个

load-data.first: /good/ andthen say "$_ is good";
Run Code Online (Sandbox Code Playgroud)

相当于更熟悉的类似 Python 的语法中的类似内容。

load_data().first("good") and say(...)
Run Code Online (Sandbox Code Playgroud)

首先,load-data被称为。它返回数据Nil或数据列表。现在first叫就行了。

返回智能匹配的列表的第一项,当没有值匹配时$matcher返回。Nil可选的命名参数:end指示搜索应该从列表的末尾开始,而不是从开头开始。

您已将其称为load-data.first: /good/,因此它将返回正则表达式/good/匹配的列表的第一个元素,否则返回Nil

andthen类似于&&,除了在&&检查真实性(通过布尔上下文)时,andthen通过 multi 方法检查定义性defined。像 和 失败这样的对象Nil是未定义的,而大多数“普通”对象(例如数字和字符串)是定义的。特别是,像零或空字符串这样传统上“假”的东西仍然被定义。与 一样&&andthen短路,因此如果左侧未定义,则右侧永远不会计算。

最后,还有一个使这条线能够工作的怪癖。andthen旨在处理这个确切的用例:执行第 1 件事,如果该事件成功,则执行第 2 件事。通常,第 2 件事取决于第 1 件事的结果。因此,andthen将左侧的结果分配给特殊变量$_在评估右侧时。实在是太拗口了,我们就写出来吧。x andthen y执行以下操作。

  1. 评价x
  2. 如果x未定义,则停止。我们完成了。返回x
  3. 否则,设置$_为 的结果x
  4. 现在评估y(使用$_集合)并返回它。

所以,把这一切都考虑进去……

load-data.first: /good/ andthen say "$_ is good";
Run Code Online (Sandbox Code Playgroud)

加载数据,找到加载数据中与正则表达式匹配的第一个元素,如果存在,则将其打印出来。

现在让我们看一下第二个例子。对于这个,您还需要了解另一个有趣的小语法糖。一般来说,语句开头的点带有隐含的$_. 因此.say等价于$_.say, 等价于say($_:), 在方法解析为 后求值say($_)

不管你信不信,它return是一个子程序。严重地。它不是一个关键字;而是一个关键字。这是一个潜艇。&return.WHAT立即在您的 REPL 中进行评估。它会说(Sub)

load-data() andthen .return;
die "Failed to load data!!";
Run Code Online (Sandbox Code Playgroud)

load-data被调用,如果它返回任何定义的值,则该定义的值将被分配给$_. 然后.return发生,这相当于$_.return(最终)成为return($_)。如果定义了该值,它将从函数返回,并且第二行永远不会运行。如果没有,我们die会提供相应的错误消息。

请注意,在这种情况下实际上需要括号。如果我们写

load-data andthen .return;
Run Code Online (Sandbox Code Playgroud)

然后 Raku 尝试解释为andthen .return参数load-data抱怨不andthen存在调用的子例程。它认为我们的意思是

load-data(andthen(.return));
Run Code Online (Sandbox Code Playgroud)

总而言之,Raku 是一个装满语法糖的大袋子,包裹在来自地狱第六圈的解析器中,它对空格和上下文敏感,其结果是一种真正美丽的语言。