I have this line of code in a toy-language. The print
-function takes a list of arguments and prints those.
print(a, (a := 5, a))
Would there be a difference in the output if I used call-by-value or call-by-name? If so, what would the outputs be.
It can be asumed that a
is initialized to 0
.
With "call-by-value" arguments are usually evaluated left-to-right (in most languages), so the expression would be equivalent to something like this:
arg1 := a // copy value of a to arg1
a := 5 // copy 5 to a
arg2 := a // copy value of a to arg2
print(arg1, arg2) // print(0, 5)
"call-by-name" is apparently a form of lazy evaluation which would yield something like this:
arg1 := function() {return a;}
arg2 := function() {a := 5; return a;}
print(arg1, arg2)
So in this case the result will depend on two things:
a := 5
won't affect the value of a
that the first closure has captured. However, most languages which allow reassigning of local variables implement capture-by-reference (e.g. JavaScript).print
function decides to evaluate its arguments - depends how it's written.If the closures capture by value, the print(…)
will yield 0 5
, because the assignment a := 5
only affects the second closure's copy of a
.
If closures capture by reference then I can only guess at what the output might be. But it's quite likely the print
function will do something like this:
print := function(lazy x, lazy y) {
writeToOutput(x())
writeToOutput(y())
}
In which case the result will be the same (0 5
), because x()
is evaluated first, the result processed, then y()
is evaluated. In this case the value of a
doesn't change until after the function is done with x
.
But this is only a guess; print
could evaluate them in any order (and any number of times).