compiler-constructionfunctional-programmingsmlcallbynamecall-by-value

What would this print under call-by-name and call-by-value?


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.


Solution

  • 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:

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