查看以下定义:
let rec extractOdds list =
match list with
| [] -> []
| x::xs ->
if x%2=0 then extractOdds xs else x::extractOdds xs
和
let rec extractOdds list =
match list with
| [] -> []
| x::xs ->
let rest = extractOdds xs
if x%2=0 then rest else x::rest
我想知道两者是否相同。由于第一个定义立即使用了递归调用。而第二个则创建与extractOdds xs
的let绑定,并在if
表达式中使用它。
如果两者的实现方式相同或不同,请指导我。
答案 0 :(得分:1)
两者之间的差别很小,实际上没有作用:
x%2=0
之前先评估条件extractOdds xs
extractOdds xs
之前先调用x%2=0
顺序将保留在编译后的代码中(对于第一个版本可能会更长一些),因此两个版本略有不同,但是无论如何都无法观察到-两个调用都没有任何副作用-效果和对extractOdds xs
的调用,无论x%2=0
是true
还是false
都是如此。
如果您也使用let
绑定重写第一个版本,这可能会更明显:
let rec extractOdds list =
match list with
| [] -> []
| x::xs ->
if x%2=0 then
let rest = extractOdds xs
rest
else
let rest = extractOdds xs
x::rest
现在您可以清楚地看到条件和let绑定的顺序是与以下内容的唯一区别:
let rec extractOdds list =
match list with
| [] -> []
| x::xs ->
let rest = extractOdds xs
if x%2=0 then
rest
else
x::rest
编辑:可以使用“累加器”参数编写尾部递归版本。这样,您将以错误的顺序收集元素,因此您需要在返回结果列表之前对其进行反转:
let rec extractOdds acc list =
match list with
| [] -> List.rev acc
| x::xs ->
extractOdds (if x%2=0 then acc else x::acc) xs