Что бы это печаталось при вызове по имени и по запросу?
У меня есть эта строка кода на игрушечном языке. print
-функция принимает список аргументов и печатает их.
print(a, (a := 5, a))
Будет ли разница в выводе, если я использую call-by-value или call-by-name? Если так, то какими будут результаты.
Можно предположить, что a
инициализируется в 0
,
1 ответ
С аргументами "call-by-value" обычно оцениваются слева направо (в большинстве языков), поэтому выражение будет эквивалентно примерно так:
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)
"вызов по имени", по-видимому, является формой ленивой оценки, которая выдает что-то вроде этого:
arg1 := function() {return a;}
arg2 := function() {a := 5; return a;}
print(arg1, arg2)
Так что в этом случае результат будет зависеть от двух вещей:
- на этом языке закрытия захватывают переменные по ссылке или по значению. Если захватить по значению, то
a := 5
не повлияет на стоимостьa
что первое закрытие захватило. Тем не менее, большинство языков, которые позволяют переназначать локальные переменные, реализуют захват по ссылке (например, JavaScript). - Порядок, в котором
print
Функция решает оценить свои аргументы - зависит от того, как она написана.
Если замыкания захватываются по значению, print(…)
даст 0 5
, потому что назначение a := 5
влияет только на копию второго закрытия a
,
Если замыкания захватываются по ссылке, я могу только догадываться, каким может быть результат. Но вполне вероятно, что print
функция будет делать что-то вроде этого:
print := function(lazy x, lazy y) {
writeToOutput(x())
writeToOutput(y())
}
В этом случае результат будет таким же (0 5
), так как x()
оценивается сначала, результат обрабатывается, затем y()
оценивается. В этом случае значение a
не изменяется до тех пор, пока функция не будет завершена с x
,
Но это только предположение; print
мог оценить их в любом порядке (и любое количество раз).