混淆的SML语句

混淆的SML语句,sml,smlnj,Sml,Smlnj,我有以下声明: 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) 我一直在试图追踪这个答案是如何产生的,但我感到困惑。有没有更好的方法来写这篇文章,帮助我理解在哪里使用了哪些变量?谢谢大家! 首先,一些alpha转换: let val fnPairOfIn

我有以下声明:

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)

我一直在试图追踪这个答案是如何产生的,但我感到困惑。有没有更好的方法来写这篇文章,帮助我理解在哪里使用了哪些变量?谢谢大家!

首先,一些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
)被声明“封闭”(因此术语“闭包”)。因此,函数总是返回一对,由输入和输入加上五组成。

您可以将其简化为

let fun f y = (y,5+y)
    val y=3 and z=10
in
  f z
end;

请注意,y的两个实例是独立的。x的内部出现(我已经排除)与外部出现(现在改名为f)无关。

可以通过手动评估和详细解释来理解

从您的初始表达式开始:

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行是一个类型为函数的表达式,如您在部分的
中所见。它不依赖于任何外部上下文,因此可以简化为仅
fn y=>(y,5+y)
,根据
let
中给出的绑定,将
x
替换为
5

现在你有了这个:

let val x = fn y => (y, 5 + y)
in
   let val y = 3 and z = 10
   in x z 
   end 
end;
替换
x
后(并移除
let
,现在不再需要它):

请注意,
(y,5+y)
中出现的
y
绑定到函数的参数,而不是
3
。没有引用此外部
y
,因此其投标可能会被删除

现在你有:

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);

谢谢这使情况变得明朗了许多。我仍然对什么是“fnPairofinputAndInputPlus5输入”感到困惑。你用输入参数调用那个值?对。对于函数
f
和参数
x
,ML中的函数调用表示法只是
fx
(fx)
。两个参数的函数可以接受一个包含两个参数的元组,也可以是当前函数。在后一种情况下,
fx
返回另一个函数。
(10, 15);