在函数中§

请参阅主要文档 在上下文中 了解子例程

创建子例程的基本方法是使用 sub 声明符,后跟可选 标识符

sub my-func { say "Look ma, no args!" }
my-func;

sub 声明符返回类型为 Sub 的值,该值可以存储在任何容器中

my &c = sub { say "Look ma, no name!" }
c;     # OUTPUT: «Look ma, no name!␤» 
 
my Any:D $f = sub { say 'Still nameless...' }
$f();  # OUTPUT: «Still nameless...␤» 
 
my Code \a = sub { say raw containers don't implement postcircumfix:<( )> };
a.();  # OUTPUT: «raw containers don't implement postcircumfix:<( )>␤»

声明符 sub 将在编译时在当前作用域中声明一个新名称。因此,任何间接引用都必须在编译时解决

constant aname = 'foo';
sub ::(aname{ say 'oi‽' };
foo;

一旦将宏添加到 Raku,这将变得更有用。

要让子例程获取参数,Signature 放在子例程的名称和主体之间,用括号括起来

sub exclaim ($phrase{
    say $phrase ~ "!!!!"
}
exclaim "Howdy, World";

默认情况下,子例程是 词法作用域 的。也就是说,sub foo {...}my sub foo {...} 相同,并且仅在当前作用域内定义。

sub escape($str{
    # Puts a slash before non-alphanumeric characters 
    S:g[<-alpha -digit>] = "\\$/" given $str
}
 
say escape 'foo#bar?'# OUTPUT: «foo\#bar\?␤» 
 
{
    sub escape($str{
        # Writes each non-alphanumeric character in its hexadecimal escape 
        S:g[<-alpha -digit>] = "\\x[{ $/.ord.base(16}]" given $str
    }
 
    say escape 'foo#bar?' # OUTPUT: «foo\x[23]bar\x[3F]␤» 
}
 
# Back to original escape function 
say escape 'foo#bar?'# OUTPUT: «foo\#bar\?␤» 

子例程不必命名。如果未命名,它们被称为匿名子例程。

say sub ($a$b{ $a ** 2 + $b ** 2 }(34# OUTPUT: «25␤»

但在这种情况下,通常需要使用更简洁的 Block 语法。子例程和块可以在原地调用,如上例所示。

say -> $a$b { $a ** 2 + $b ** 2 }(34)    # OUTPUT: «25␤»

或者甚至

say { $^a ** 2 + $^b ** 2 }(34)            # OUTPUT: «25␤»