这有效:
$_ =
say "hi";
也就是说,您可以在任务和后面的内容之间放置任意数量的空格,它只会忽略它。您也可以使用任何变量(带有my
)。实际上,将为$ _分配say
的结果,即True
。
这是令人惊讶的,但是符合规范,还是仅仅是令人惊讶?
答案 0 :(得分:8)
运算符的两边可能有任意数量的空格。因此:
say 1
+ 2
+ 3;
就编译器而言,完全相同:
say 1 + 2 + 3;
分配(=
)只是另一个运算符,因此也要遵循这些规则。
此外,say
只是一个普通的内置子例程,因此就像:
my $answer = flip '24';
say $answer; # 42
除了具有更多的空格:
my $answer =
flip '24';
say $answer; # 42
在Perl 6中有 some 个空格,空格很大,但是中缀运算符之间的空格不是其中之一。
答案 1 :(得分:4)
TL; DR P6语法是自由格式。
悬挂主题(或任何其他)变量不会失败
您描述的问题是一个非常普遍的问题。绝对不只是关于变量声明/赋值!
在P6中,对语句(单个命令单元(“执行此操作”)的解析)通常会一直进行下去,直到到达显式语句分隔符(;
)为止,该分隔符将一条语句带到就像这个英语句子结尾处的句点(也称为句号)一样。
您可以放置任意数量的空格
与许多编程语言一样,标准P6通常为freeform。也就是说,只要 some 空格有效,那么通常任何数量的空格-水平和垂直空格-在语法上都是等效的。
$_ =
say "hi";
以上内容的工作原理完全与预期的一致,如果有人采用自由格式原理,这是将say
的值分配给$_
变量的单个语句。
这是令人惊讶的,但是符合规范,还是仅仅是令人惊讶?
我喜欢发明(希望是愚蠢的)俗语。我刚刚发明了“惊喜跟随惊喜”。
由规格决定。我知道可以期待。这并不令我惊讶。
如果有人接受P6通常是自由格式并且具有分号语句分隔的事实,那么我预测,(最终-可能很快)它将不再令人惊讶。
以上内容是您问题的直接答案。同样,请参见乔纳森的答案以获取更多信息。随意忽略此答案的其余部分。
对于此答案的其余部分,我使用“自由格式”来指代P6的自由格式语法,分号语句分隔和大括号({...}
)的组合。
此答案的其余部分分为三个部分:
自由格式语法的P6例外
自由格式vs面向行
自由格式和面向行?
@Larry总结说,在某些情况下,直觉,美观,方便和/或其他因素证明了标准P6中纯自由格式语法的例外。
如果满足以下条件,则语句可以省略结尾的分号
:是源文件或块中的最后一条语句;
以一个结尾的块结尾,该块的结尾卷曲后跟换行符(忽略注释)。
因此下面的三个语句(if
和两个say
)都不需要以分号结尾:
if 42 {
say 'no semicolon needed before the closing curly'
} # no semicolon needed after the closing curly
say 'no semicolon needed if last statement in source file'
有时候这可能不是想要的:
{ ... } # the closing } ends the statement (block)
.() # call is invoked on $_
一种更改方法是使用括号:
({ ... })
.() # calls the block on prior line
对于某些构造,空格是必需的或不允许的。例如,某些后缀必须直接跟随它们所应用的值,而某些后缀则不能。这些都是语法错误:
foo ++
foo«+»bar
对于某些编码方案,P6的自由格式语法可以说是强大的净肯定值,例如:
一个衬里可以使用块;
FP代码是自然的(一个人可以编写非平凡的闭包);
更直接的编辑/重构/复制/粘贴。
但是有缺点:
自由格式语法(分号和大括号)的读写开销。
无视可能导致您提出问题的直觉。
后者很有效。以下所有内容可能会使某人认为您的示例中的say
是新语句的一部分,而不是$_ =
语句的延续:
=
之后的换行符;
此后的空白行;
相对于say
行,在$_ =
行的开头没有缩进;
say
的性质(似乎say
必须是新语句的开始)。
上述直觉的结果是某些编程语言采用"line-oriented" syntax而不是自由格式的语言,其中最著名的是Python。 1
某些语言,例如Haskell,允许使用 面向行的或自由格式语法(至少对于 some 语言构造而言)。
P6支持slangs,这是一种会改变语言的用户界面模块。想象一下同时支持自由格式和面向行代码的语:
那些学习P6的人在学习基于Pem的 面向行的或自由格式代码以学习该语言的基础知识时,会遇到更多的熟悉和更少的惊喜;
熟悉P6的人可以通过使用 面向行的或自由格式语法编写更好的代码。
冒着使事情变得过于复杂的风险,想象一个既采用行定向又采用Python支持的the off-side rule的语,并为无类型的无sigil变量实现no strict;
(它会删除声明符和嘲笑并促进不变性。这是几周前我在a reddit comment中发布的用想象的语编写的一些代码片段:
sub egg(bar)
put bar
data = ["Iron man", "is", "Tony Stark"]
callbacks = []
也许上面的东西很难实现? (我目前不知道为什么。)
1 本节的其余部分使用Programming language statements上的Wikipedia部分作为指南来比较P6和Python:
语句分隔符用于划分两个单独的语句之间的边界。
在P6中,它是;
或块末。
在Python中,;
可用于单独的语句。但这主要是面向行的。
将行尾解释为语句结尾的语言称为“面向行”语言。
在Python中,除非适当地缩进了下一行(在这种情况下,这是相关子块的开始)或在行的末尾出现了显式的行继续符,否则行末会终止一条语句。
P6不是 面向行的。 (至少不是标准的P6。我将在此答案的末尾放置一个P6 s语,该语言同时支持自由格式和面向行的语法。)
“行继续”是面向行的语言的约定,它允许单个语句跨越多个行。
Python具有行继续功能;有关详细信息,请参见Wikipedia文章。
尽管不面向行,标准P6也具有行连续功能。 2
2 P6支持行继续。继续引用维基百科的话:
换行符通常会导致将令牌添加到令牌流中,除非检测到行连续。
(令牌是代码的最小片段-除了单个字符之外,解析器将其视为原子单位。)
如果标准P6遇到换行符,则总是假定令牌中断,唯一的例外是跨这样的行写入字符串:
say
'The
quick
fox';
这将编译OK,并在三行中分别显示The
,quick
和fox
。
Python中的等效项将生成语法错误。
反斜杠作为行的最后一个字符
在P6中,反斜杠:
不能出现在令牌的中间;
可用于在解析器忽略的源代码中引入空格,以避免语法错误。例如:
say @foo\
»++
say @foo\ »++
内联注释的某些形式可以作为行的延续
这有效:
say {;}#`( An embedded
comment ).signature
嵌入的评论:
不能出现在令牌的中间;
不像反斜杠那样普遍(say @foo#`[...]»++
不起作用)。