越位規則(**')是指程式語言中,用縮排來表示块结构的範圍。该名詞來自彼得·兰丁,是足球中越位(offside)的雙關語。
定义
越位规则,定义于彼得·兰丁在1966年叫做《The Next 700 Programming Languages》的文章中:
这个规则被解读为是一种词法约定:任何非空白记号,当出现在上一行这种记号左侧之时,被接受为一个新宣布的开始。
以Haskell语言的黄金规则为示例:作为某个表达式一部份的代码应该比这个表达式的开始处要缩排进去,即使这个表达式不是此行的最左元素。所有组合起来的表达式必须精确的对齐,在表达式的左侧的所有东西都被当作缩排,即使不是空白。当一个表达式的开始处不是一行的开始的时候,表达式的后续部分可以只比包含这个表达式开始的那一行要缩排进去。由花括号{……}和分号;组织起来的代码块可不采用越位规则。下面以将适用越位规则的do控制结构嵌入if……then……else为例:
:
程式範例
以下是一個Python語言程式的例子,其中用縮排表示其程式區塊:
def is_even(a: int) -> bool:
"""确定数a是否是偶数."""
if a % 2 == 0:
print('偶数!')
return True
print('奇数!')
return False
Python中括号内多行代码会隐式的接合在一起,也有着相应的缩排规则:
参数比后续部份多一层缩进
def long_function_name(
var_one, var_two, var_three,
var_four):
# 可选的圆括号内后续行多一层缩进,注意这里关键字在行首
if (this_is_first_thing
and that_is_second_thing):
do_something()
# 可选的圆括号内后续行不额外缩进,同类语言元素垂直对齐
elif (this_is_third_thing and
that_is_fourth_thing):
do_something_different()
悬挂缩进,参数比行首缩进一层
spam = long_function_name(
arg_one, arg_two,
arg_three, arg_four)
按开定界符垂直对齐
eggs = long_function_name(arg_one, arg_two,
arg_three, arg_four)
#可选的闭括号位置
my_list = [
1, 2, 3,
4, 5, 6,
]
可选的闭括号位置
my_set = {
1, 2, 3,
4, 5, 6,
}
实现
越位规则可以在词法分析阶段实现,就像Python那样,在这里增加缩进导致词法器输出一个INDENT记号,而减少缩进导致词法器输出一个DEDENT记号。这些记号分别对应于使用花括号表示块结构的语言中的开花括号{和闭花括号},并且意味着短语语法不依赖于使用的是缩进还是花括号。这要求词法器保持状态,也就是当前的缩进层级,因而在缩进变更的时候可以检测到,因此这种词法文法不是上下文无关的,INDENT/DEDENT依赖于以前缩进层级的上下文信息。
遵循越位規則的語言
编程语言
- ABC
- BOO
*
*
- CoffeeScript
- Curry
- F#(如果未指定#light "off")
- Genie
- Haskell(只用于where、let、do或of子句在花括号省略的时候)
- ISWIM,越位規則就是設計此抽象語言時介入的
- Miranda
- Nemerle
- Occam
*
- Python
*
*
- Nim
其他语言
- Haml
- reStructuredText
- Sass
- YAML
參考資料
评论 (0)