为什么如果为False后的命令在Perl 6 REPL中产生一个空列表?

时间:2018-10-02 18:06:37

标签: perl6

如果if的条件是False,则REPL给出()(空List?),而不是空输出。

> put 1 if True
1
> put 1 if False
()               # ← What is this?

()是什么意思?

4 个答案:

答案 0 :(得分:9)

在这个经过不断编辑的答案的早期版本中,我写道:“ REPL并没有做任何特别的事情”。但是我当然是错的。 REPL评估一行代码。如果生成输出,则显示该输出,仅此而已。如果不是,它将say设置最后一条语句的值。参见JJ's answer

您获得的()意味着一个空列表。

在此答案的早期版本中,我同意您的看法,它是空的List。但是我当然是错的。在这种情况下,它是List子类型。参见Brad's answer。)


可以说我最好删除这个答案。 :)

以下是该答案可能仍然有价值的东西,直到其他人解释我还做错了什么...

Perl 6在做什么

一条语句求值。

一条语句可以只是一个表达式。

表达式可以只是一个文字值:

> 42
42

值的文字列表的计算结果为List

> 42, 99
(1 99)

一个空列表显示为()。这可能意味着一个空的List

> ()
()            # <-- empty `List`
> List.new
()            # <-- empty `List`
> 'aa' ~~ m:g/b/
()            # <-- empty `List`

或一个空列表,它是List的子类型,但重复使用了相同的字符串化,例如Slip

> Empty
()            # <-- empty `Slip`
> Slip.new
()            # <-- empty `Slip`

语句也可以求值为单个值:

> if True { 42 }
42

或列表:

> if True { 42, 99 }
(42 99)

某些语句计算为空列表。您的问题就是这样一个例子:

> if False {}
()

正如布拉德指出的那样,这是一个空的Slip,特别是Empty实例。

答案 1 :(得分:6)

实际上您的问题不正确。

您真正得到的是一个空的Slip
具体来说,您将获取名为Empty的特定实例。


Slip的作用是将其自身插入外部列表值。

say (1, 2, 3, (4, 5)).perl;
# (1, 2, 3, (4, 5))

say (1, 2, 3, (4, 5).Slip).perl;
# (1, 2, 3, 4, 5)

存在Slip的原因是Perl 6在默认情况下不会展平值。

sub return-list () { 4, 5 }

say (1, 2, 3, return-list()).perl;
# (1, 2, 3, (4, 5))

(在正式版本发布之前,它曾在某些情况下用于扁平化值,既令人困惑又难以解决)

因此Slip的功能是在您确实希望它展平的情况下引入的。

sub return-slip () { slip 4, 5 }

say (1, 2, 3, return-slip()).perl;
# (1, 2, 3, 4, 5)

请注意,它仅执行一次展平。

sub return-structured-slip () {
   slip 4, (5,)
}

say (1, 2, 3, return-structured-slip()).perl;
# (1, 2, 3, 4, (5,))

grep作为map代码的一部分非常有用。

say (0..10).map: { $_, $_² if .is-prime }
# ((2 4) (3 9) (5 25) (7 49))

它也可以用于在调用例程时舍弃值。

my $a;
my $b = 1;

say(
  ( $a.perl if $a ),
  ( $b.perl if $b ),
)

单数Empty的一个有用功能是您可以将其与之匹配。

multi sub foo ($_){.say}
multi sub foo (Empty){ say 'Hello, World' }

foo Empty; # Hello, World

foo (1 if 0); # Hello, World

请注意,有可能获得一个空Slip而不是奇异值Empty。在这种情况下,它将不匹配。

|()
().Slip

答案 2 :(得分:5)

返回的值为空SlipEmpty)。试试

 say {put 1 if False}() ~~ Empty

您可以使用… if FalseEmpty返回List

 dd (2..100).map: { $_² if .is-prime }

类似地,… with NilNil andthen …返回Empty

答案 3 :(得分:4)

到目前为止,所有答案都很好,解释了幕后情况。但我会尝试直接回答您的问题。

  

如果if的条件为False,则REPL给出()(一个空的List?)而不是空的输出

关键在于您正在使用REPL。如果有块,则REPL打印块的输出。如果没有输出,它将打印表达式返回的内容。然后,将您的两个选项作为块处理。括号内的内容是您实际在REPL中输入的内容:

from Cell import Cell

是的。 REPL将看到输出say (put 1 if True).^name # OUTPUT: «1␤Bool␤» ,并进行打印。由于1返回的结果是True,因此块结果被REPL丢弃。在第二种情况下会发生什么?

put

在这种情况下,没有输出。 REPL将使用say (put 1 if False).^name # OUTPUT: «Slip␤» 作为表达式,并打印(put 1 if False),在这种情况下为Slip。如@raiph答案中所示,这就是()返回的内容,这就是您在REPL中得到的内容。