Что бы это печаталось при вызове по имени и по запросу?

У меня есть эта строка кода на игрушечном языке. 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 мог оценить их в любом порядке (и любое количество раз).

Другие вопросы по тегам