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