Question

Firstly, I'm not entirely familiar with the concepts in question so forgive me if I misuse any terminology. What I was wondering was, if I have something like:

int someGlobal = 7;
int sumThree(int a, int b){
    return (a + b + someGlobal);
}

If it was possible to partially apply/curry that function by calling sumThree(3), then would this be converted into the equivalent of:

int sumThree(int b){
    return (3 + b + someGlobal);
}

or into:

int sumThree(int b){
    return (3 + b + 7); //or, return (10+b) 
}

Would one of these be 'more correct'? Or if they're just different forms of the same thing, what terminology would one use to distinguish between the two of them? The above two pieces of code differ in that if the value of someGlobal was changed after sumThree(3) was called but before the rest of the function was applied, the former would produce a different result to the latter, as the latter captures the value (7) of someGlobal at the time sumThree(3) is called.

Was it helpful?

Solution

How would partial application work in an impure language? Not very well :-P

Jokes aside, closures in impure languages are hard to reason about when they are allowed to refer to mutable variables. For instance:

x = 0;
f = function (y) { return x+y; }
x = 1;
y = f(10); // 10 or 11 ?

There is no "right" answer to the question above: both 10 and 11 are reasonable outcomes, and the programmer must know which one is taken by the programming language at hand. Java, for instance, disallows the (Java-equivalent of the) code above. Java allows instead (the equivalent of)

x = 0;
const xc = x;
f = function (y) { return xc+y; }
x = 1;
y = f(10); // 10

because here there is no ambiguity: xc is a const, so its value at closure-construction-time will be the same at closure-application-time. Java rules are slightly more relaxed than requiring that all the caprtured variables are constants.

Further, note that the problem is not merely theoretical. The blogged article Closing over the loop variable considered harmful shows that the semantics of C# was recently changed because programmers tripped into problems.

Ocaml, which is impure, can partially mitigate the issue when using ref types. If x : int ref then

let f1 = fun y -> !x + y

will use the value of x at application-time, while

let f2 = let xv = !x in fun y -> xv + y

will use the value of x at closure time.

Finally, C++11 took the choice of allowing many kinds of captures: you can capture a variable value (as in f2 above) or a variable reference (as in f1).

OTHER TIPS

Partial application requires closures, there's no way without (unless you don't actually need the first argument, or resort to very horrible mutable-global-state hackery). Neither of your options do anything like it, though closures can without problem (if clumsily) be done in any OO language. Strictness is not a problem at all. In C++, your example could be done thus:

class SumThree {
  int a;
 public:
  SumThree(int a): a(a) {}
  int operator() (int b) const { return a + b + someGlobal; }
};

int main () {
  std::cout << SumThree(3)(7) << std::endl;
  return 0;
}

The first option is correct. This way, sumThree(3)(0) is always the same as sumThree(3, 0). E.g. (imaginary syntax):

int(int) sumThree1 = sumThree(3);
someGlobal = 0;
println(sumThree1(0)); // prints 3 + 0 + someGlobal = 3
println(sumThree(3, 0); // again prints 3
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top