我有这样的声明:
let val x =
let val x = 5
in(fn y =>(y,x+y))
end
in
let val y=3 and z=10
in x z
end
end;
输出结果为:
(10,15)
我一直试图追踪这个答案是如何产生的,但我感到很困惑。有没有更好的方法来写这个有助于我理解在哪里使用哪些变量?谢谢!
答案 0 :(得分:4)
首先,一些alpha转换:
let val fnPairOfInputAndInputPlus5 =
let val five = 5
in ( fn input => ( input, five + input ) )
end
in let val ignored = 3 and input = 10
in fnPairOfInputAndInputPlus5 input
end
end;
此代码证明,当您声明函数值时,声明范围中的未绑定值(例如值five
)将被声明“封闭”(因此称为“闭包”)。因此,该函数总是返回一个由其输入和输入加上五个组成的对。
答案 1 :(得分:3)
您可以将其简化为
let fun f y = (y,5+y)
val y=3 and z=10
in
f z
end;
请注意,y的两个实例是独立的。 x的内部出现(我已经消除)独立于外部(现在重命名为f)。
答案 2 :(得分:0)
可以通过详细解释的手动评估来理解。
从您的初始表达开始:
let val x =
let val x = 5
in (fn y => (y,x + y))
end
in
let val y = 3 and z = 10
in x z
end
end;
第2,3,4行是一个表达式,其类型是一个函数,如in
部分所示。它不依赖于任何外部上下文,因此根据fn y => (y, 5 + y)
中给出的绑定,它可以简化为x
,将5
替换为let
。
所以你现在有了这个:
let val x = fn y => (y, 5 + y)
in
let val y = 3 and z = 10
in x z
end
end;
替换x
(并删除let
,然后现在不再需要了):
let val y = 3 and z = 10
in (fn y => (y, 5 + y)) z
end;
请注意y
中出现的(y, 5 + y)
与函数的参数绑定,而不是3
。没有引用此外部y
,因此可以删除它的biding。
现在你有:
let z = 10
in (fn y => (y, 5 + y)) z
end;
将z
替换为10
并删除不再需要的let
,您会得到:
(fn y => (y, 5 + y)) 10;
这是一个功能应用程序。您可以对其进行评估,以获得:
(10, 5 + 10);
这给出了你注意到的最终和持续的结果:
(10, 15);