Toptic Variable

楽土

$_ 变量

$_ 是主题变量。它是没有显式签名的块的默认参数,因此 for @array {...}given $var {...} 这样的构造通过调用块绑定到 $_

for

for <a b c> { say $_ }  # sets $_ to 'a', 'b' and 'c' in turn
say $_ for <a b c>;     # same, even though it's not a block

given

given 'a'   { say $_ }  # sets $_ to 'a'
say $_ given 'a';       # same, even though it's not a block

设置默认的主题变量可以省去很多打字:

for Date.new('2018-01-01') .. Date.new('2018-01-07') {
  printf("%04d%02d%02d%02d%02d%02d\n", .year, .month, .day, .hour, .minute, .second) given .DateTime
}

# 20180101000000
# 20180102000000
# 20180103000000
# 20180104000000
# 20180105000000
# 20180106000000
# 20180107000000

对象初始化:

class Employee {
    subset Salary         of Real where * > 0;
    subset NonEmptyString of Str  where * ~~ /\S/; 

    has NonEmptyString $.name    is rw;
    has NonEmptyString $.surname is rw;
    has Salary         $.salary  is rw;

    method gist {
        return qq:to[END];
        Name:    {$.name}
        Surname: {$.surname}
        Salary:  {$.salary}
        END
    }
}
my $employee = Employee.new();

given $employee {
    .name    = 'Sally';
    .surname = 'Ride';
    .salary  = 200;
}

say $employee;

regex

在方法上调用 $_ 可以通过省略变量名来缩的更短:

.say;                   # same as $_.say

m/regex//regex/ 正则匹配 $_s/regex/subst/ 替换作用于 $_

say "Looking for strings with non-alphabetic characters...";
for <ab:c d$e fgh ij*> {
    .say if m/<-alpha>/;
}

# OUTPUT: «Looking for strings with non-alphabetic characters...
#          ab:c
#          d$e
#          ij*␤»

with/without

with 不引入块时也能设置 $_ 主题变量:

say $_ with 42; # 42
.say with 42;   # 42

with/without 会把条件设置为 $_

# The below code says "Found a at 0"
my $s = "abc";
with   $s.index("a") { say "Found a at $_" }
orwith $s.index("b") { say "Found b at $_" }
orwith $s.index("c") { say "Found c at $_" }
else                 { say "Didn't find a, b or c" }

when

when 语句使主题变量 $_ 和所提供的表达式进行智能匹配,以使在指定匹配的时候能检查值、正则表达式和类型:

for 42, 43, "foo", 44, "bar" {
    when Int { .say }
    when /:i ^Bar/ { .say }
    default  { say "Not an Int or a Bar" }
}
# OUTPUT: «42␤43␤Not an Int or a Bar␤44␤Bar␤»
> for ('Swift', 'PHP', 'Python', 'Perl')  { .say if  Str }
Nil
> for ('Swift', 'PHP', 'Python', 'Perl')  { .say if  $_ ~~ Str }
Swift
PHP
Python
Perl

for ('Swift', 'PHP', 'Python', 'Perl')  { .say when Str }
Swift
PHP
Python
Perl

列表解析:

(.ord when /7$/ for 1..99)

when 和 if

when 块类似于 if 块,并且其中一个或两个都可以在外部块中使用,它们也都具有“语句修饰符”形式。但是如何处理相同的外部块中的代码是有区别的:当执行 when 块时,控制被传递到封闭块并忽略后面的语句; 但是当执行 if 块时,执行以下语句。 (注意,还有其他方法可以修改其他部分中讨论的每个的默认行为。)以下示例应说明 ifwhen 块的默认行为,假设 ifwhen 块中不包含特殊退出或其他副作用语句:

{
    if X {...} # if X is true in boolean context, block is executed
    # following statements are executed regardless
}
{
    when X {...} # if X is true in boolean context, block is executed
                 # and control passes to the outer block
    # following statements are NOT executed
}

如果上面的 ifwhen 块出现在文件范围内,则在每种情况下都会执行以下语句。

有一个 when 有而 if 没有的功能:when 的布尔上下文测试默认为 $_ ~~if 不是。这影响人们怎么在不带 $_ 值的 when 块中使用 X (在那种情况下, 它是 Any,并且 AnyTrue 智能匹配:Any ~~ True 产生 True )。请看下面的例子:

{
    my $a = 1;
    my $b = True;
    when $a    { say 'a' }; # no output
    when so $a { say 'a' }  # a (in "so $a" 'so' coerces $a to Boolean context True
                            # which matches with Any)
    when $b    { say 'b' }; # no output (this statement won't be run)
}

最后,when 的语句修饰符形式不影响如下语句在另一个块内部或外部的执行:

say "foo" when X; # if X is true statement is executed
                  # following statements are not affected

签名

块的默认签名是一个名为 $_ 的位置参数:

my &block =  { 'oi' };
&block.signature.say; # (;; $_? is raw)
my class Employee {
   has Str $.name;
   has Rat $.wage;
}

my $boss     = Employee.new( name => "Frank Myers"     , wage => 6755.85 );
my $driver   = Employee.new( name => "Aaron Fast"      , wage => 2530.40 );
my $worker   = Employee.new( name => "John Dude"       , wage => 2200.00 );
my $salesman = Employee.new( name => "Frank Mileeater" , wage => 4590.12 );

my @team = $boss, $driver, $worker, $salesman;

say @team.sort({.wage} )».name;
.name.say for @team.sort: {.wage};

块里面会默认有一个 $_

my $tiles := (< T S R E A N D >).Bag;
my $total := $tiles.total;

my @results = lazy '/usr/share/dict/SOWPODS'.IO.lines.grep: {
    .chars ≤ $total &&
    .substr(0, 1) ∈ $tiles &&
    .comb.Bag ⊆ $tiles
}

for @results -> $word {
    say $word;
}

say "\n" ~ "Found {@results.elems} words in {now - INIT now} seconds";
Toptic 
comments powered by Disqus