令人困惑的SML声明

时间:2013-12-16 03:56:11

标签: 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)

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

3 个答案:

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