39 haskell pattern-matching variable-assignment let assignment-operator
如果我说let 5 = 10,为什么5 + 1返回6而不是11?
n. *_* m. 53
当你说
let 5 = 10
Run Code Online (Sandbox Code Playgroud)
它不是5的重新定义,它是一种模式匹配,就像你说的那样
foo 5 = undefined
... foo 10 ...
Run Code Online (Sandbox Code Playgroud)
如果匹配,模式就会失败.
在let-expressions中,匹配是懒惰的.这意味着匹配仅在评估由其约束的变量时完成.这允许我们写出类似的东西
let foo = undefined in 10
Run Code Online (Sandbox Code Playgroud)
在表达式中,没有绑定变量,因此模式永远不会匹配.
可以说这种没有变量的模式在let-bindings中没有任何意义,应该由编译器检测,但语言并不禁止它们.
chi*_*chi 17
基本上,
let 5 = 10 in ...
Run Code Online (Sandbox Code Playgroud)
相当于
case 10 of ~5 -> ...
Run Code Online (Sandbox Code Playgroud)
注意~,这标志着一种懒惰或无可辩驳的模式.这是一个匹配所有内容的模式,并将匹配推迟到实际需要某个变量的点.模式中没有变量5,所以什么都没发生.
这个角落的情况很无用,可以说编译器应该在这里发出警告.
为了澄清懒惰模式的含义,请考虑以下事项:
case f 3 of
(x,y) -> g 10 x y
Run Code Online (Sandbox Code Playgroud)
这里f 3首先进行评估(到WHNF),公开对构造函数.然后x,y绑定到(尚未评估的)对组件.最后,g 10计算,结果应用于x(现在可能需要),然后应用于y(可能导致x或y要求).
通过比较,
case f 3 of
~(x,y) -> g 10 x y
Run Code Online (Sandbox Code Playgroud)
不是从评估开始f 3.相反x,必然会受到无价值的影响fst (f 3),y并且必然会受到无价值的影响snd (f 3).我们首先从评估开始g 10.然后,我们将其应用于x:这可能导致x需要,触发评估f 3.然后,我们将结果应用于y,导致类似的评估.大部分实施实际上将共享的结果f 3之间x,并y使其计算最多一次.