Raku 中的 IIFE 替代方案

hhc*_*nut 9 raku

在 Ruby 中,我可以使用 begin 块将一些代码行组合在一起:

x = begin
  puts "Hi!"
  a = 2
  b = 3
  a + b
end

puts x # 5
Run Code Online (Sandbox Code Playgroud)

它会立即被评估,并且它的值是块的最后一个值(a + b此处)(Javascripters 使用IIFE做类似的事情)

在 Raku 中有哪些方法可以做到这一点?还有比以下更顺利的事情吗?

my $x = ({
  say "Hi!";
  my $a = 2;
  my $b = 3;
  $a + $b;
})();

say $x; # 5
Run Code Online (Sandbox Code Playgroud)

rai*_*iph 12

do在块前面插入一个。这告诉 Raku:

  • 立即执行do其右侧的操作;

  • 将值返回到 的do左侧:

my $x = do {
  put "Hi!";
  my $a = 2;
  my $b = 3;
  $a + $b;
}
Run Code Online (Sandbox Code Playgroud)

也就是说,人们很少需要使用do.

相反,Raku 中还有许多其他 IIFE 形式,可以自然地工作,无需大惊小怪。我只提其中两个,因为它们在 Raku 代码中被广泛使用:

with whatever { .foo } else { .bar }
Run Code Online (Sandbox Code Playgroud)

你可能认为我很傻,但那是两个 IIFE。它们形成词法作用域,具有参数列表,从参数绑定,这些都是有效的。许多 Raku 结构都是这样工作的。

在上面的情况下,我没有编写明确的参数列表,这并不明显。事实上,如果.foo已定义,则调用它,如果未定义,则调用它,这一事实既是隐式的,又是由于 的特定 IIFE 调用行为造成的。whateverwhatever.barwith

另请参阅ifwhilegiven和许多许多其他内容。


如果您使用以下命令引入显式参数列表,则发生的情况会变得更加明显->

for whatever -> $a, $b { say $a + $b }
Run Code Online (Sandbox Code Playgroud)

迭代whatever,将两个连续元素绑定到$a$b,直到whatever为空。如果它有奇数个元素,可以写:

for whatever -> $a, $b? { say $a + $b }
Run Code Online (Sandbox Code Playgroud)

等等。


底线:Raku 中大量出现的{...}都是 IIFE,即使它们看起来并不像。但如果它们紧接在 a 之后=,Raku 默认假设您想要分配 lambda 而不是立即执行它,因此您需要do在这种特殊情况下插入 a。


Eli*_*sen 4

欢迎来到乐库!

my $x = BEGIN {
    say "Hi!";
    my $a = 2;
    my $b = 3;
    $a + $b;
}
Run Code Online (Sandbox Code Playgroud)

我猜 Raku 和 Ruby 的共同祖先表明:-)

另请注意,要创建常量,您还可以使用constant

my constant $x = do {
    say "Hi!";
    my $a = 2;
    my $b = 3;
    $a + $b;
}
Run Code Online (Sandbox Code Playgroud)

如果您可以有一个语句,则可以省略大括号:

my $x = BEGIN 2 + 3;
Run Code Online (Sandbox Code Playgroud)

或者:

my constant $x = 2 + 3;
Run Code Online (Sandbox Code Playgroud)

关于块:如果它们位于接收器上下文中(类似于某些语言中的“void”上下文),那么它们将像这样执行:

{
    say "Executing block";
}
Run Code Online (Sandbox Code Playgroud)

无需明确调用它:它将为您调用:-)

  • Raku 中的“BEGIN”与 Ruby 中的“begin”非常不同。如果前者出现在循环、函数或其他可重用构造中,则只会评估一次,而不是每次循环迭代。 (3认同)
  • @SilvioMayolo Ruby 中的 `begin` / `end` 几乎不是遵循 Pascal 系列 PL 的块分隔符,因此相当于 Raku 中的 `{` / `}` 来编写代码块,至少松散地说? (2认同)