问题描述
这里的问题是我不太了解控制流中的语句和块之间的区别。
寻找三元运算符,我可以使用它来分配变量。但这是一个运算符,所以就像应用一个函数一样,不是吗?
> my $variable = True ?? 34 !! 42;
34
因为raku文档中说:
if
要有条件地运行代码块,请使用
if
,后跟一个 健康)状况。条件,即表达式,将立即求值if
前的语句之后。附加到 仅当条件表示True
时,才会评估条件 被逼到布尔。与某些语言不同,该条件不必 请加上括号,而必须在该块周围使用{
和}
:
do
运行不能成为独立语句的块的最简单方法是在其前面写入
do
:
所以这在两种情况下都应该起作用:
> my $variable = do {34};
34
> my $variable = if True {34;} else {43;}
===SORRY!===
Word 'if' interpreted as a listop; please use 'do if' to introduce the statement control word
------> my $variable = if⏏ True {34;} else {43;}
Unexpected block in infix position (two terms in a row)
------> my $variable = if True⏏ {34;} else {43;}
> my $variable = do if True {34;} else {43;}
34
所以if
确实没有运行该块...或者这里的真正问题是什么?
解决方法
TL; DR:实际差异是陈述和表达式之间的差异,而不是陈述和 block 。 do
是创建表达式的语句前缀。
if
实际上会创建一条语句(Raku中运行的所有语句),但是它不是expression。 do
是语句前缀,它的作用是将语句转换为表达式。
但是,if
并不是真正可以分配给变量或处理的一流函数。每当您发现某种语法片段(例如{或for
)时,都需要在其前面加上do
来“表达”它们。
say &say.^name;# OUTPUT: «Sub» say &do.^name; # OUTPUT: «===SORRY!=== Error while compiling <tmp>Undeclared routine:...
say &if.^name; # OUTPUT: «===SORRY!=== Error while compiling <tmp>Undeclared routine: if used at line 1»
因此,if
本身不会创建块,不会创建表达式,而只是创建语句。如果要使其实际变成表达式,则需要在do
之前加上它。但是,它会运行它后面的代码块。
让我们回到原始的问题,陈述和方块。 Blocks是客体,一等公民。您可以使用它们,应用它们,然后将它们传递出去。
my &ifs = { if $_ {34} else {43}};
ifs(True).say; # OUTPUT: «34»
语句是您只需运行的一次性块。在某些情况下,它们也是表达式:它们产生一个结果,然后您可以分配该结果。
my &ifs = { if $_ {34} else {43}};
my $result = ifs(True).say; # OUTPUT: «34»
say $result; # OUTPUT: «True»
ifs(True).say
语句打印输出,它还会产生可以分配的结果。所有这三行也是语句,实际上也是表达式。
但是,某些控制结构不会创建表达式。
其他一些人这样做;
for
创建一个表达式;while
不会。
if
就是一个例子。他们不会产生结果。您将它们用于副作用:运行一个语句(如果为true)或另一个(如果不是)。您可以像上面一样将它们变成一个块,然后传递它们。或者,您可以在它们前面加上do
,使它们产生一个一次性的结果,然后可以使用它。
因此,这在很大程度上取决于您的实际用例。您可以将if语句括在花括号中并创建一个块;或者您可以简单地使用结果创建表达式。或者您可能只想将其用于副作用,什么也不做。