如何以严格,不纯的语言进行currying /部分应用程序的工作?

Log*_*ins 2 closures haskell functional-programming currying

首先,我并不完全熟悉有问题的概念,如果我滥用任何术语,请原谅我.我想知道的是,如果我有类似的东西:

int someGlobal = 7;
int sumThree(int a, int b){
    return (a + b + someGlobal);
}
Run Code Online (Sandbox Code Playgroud)

如果可以通过调用部分应用/ curry该函数sumThree(3),那么这将被转换为等效于:

int sumThree(int b){
    return (3 + b + someGlobal);
}
Run Code Online (Sandbox Code Playgroud)

或者:

int sumThree(int b){
    return (3 + b + 7); //or, return (10+b) 
}
Run Code Online (Sandbox Code Playgroud)

其中一个会"更正确"吗?或者,如果它们只是同一种形式的不同形式,那么用什么术语来区分它们中的两种?上面两段代码的不同之处在于,如果someGlobal的值在sumThree(3)被调用之后但在应用函数的其余部分之前发生了变化,则前者会对后者产生不同的结果,因为后者捕获了值(7)当时有些全球人sumThree(3)称之为.

chi*_*chi 8

部分应用程序如何以不纯的语言工作?不是很好:-P

除了笑话外,当允许他们引用可变变量时,很难解释不纯语言中的闭包.例如:

x = 0;
f = function (y) { return x+y; }
x = 1;
y = f(10); // 10 or 11 ?
Run Code Online (Sandbox Code Playgroud)

上面的问题没有"正确"的答案:10和11都是合理的结果,程序员必须知道手头的编程语言采用了哪一个.例如,Java不允许上面的(Java等价的)代码.Java允许(相当于)

x = 0;
const xc = x;
f = function (y) { return xc+y; }
x = 1;
y = f(10); // 10
Run Code Online (Sandbox Code Playgroud)

因为这里没有歧义:xc是一个const,所以它在闭包构造时的值在闭包 - 应用时也是一样的.Java规则比要求所有捕获变量都是常量稍微放松一些.

此外,请注意问题不仅仅是理论问题.博客文章 Closing over loop variable被认为是有害的,这表明C#的语义最近发生了变化,因为程序员遇到了问题.

Ocaml是不纯的,在使用ref类型时可以部分缓解这个问题.如果x : int ref那么

let f1 = fun y -> !x + y
Run Code Online (Sandbox Code Playgroud)

将使用x应用程序时的值,而

let f2 = let xv = !x in fun y -> xv + y
Run Code Online (Sandbox Code Playgroud)

将使用x关闭时的值.

最后,C++ 11选择允许多种捕获:您可以捕获变量值(f2如上所述)或变量引用(如f1).