Это расширение ответ Имон .
Семантика if <condition> then <stmt> else <stmt> fi
следующая:
- оценить
<condition>
;
- если это правда, выполнить оператор между
then
и else
;
- в противном случае выполнить оператор между
else
и fi
.
Семантика while <condition> do <stmt> od
следующая:
- оценить
<condition>
;
- если false, оператор
while
завершен;
- в противном случае выполнить инструкцию между
do
и od
и снова выполнить инструкцию while
.
Чтобы выразить if A then B else C
в терминах while
, выполните следующее преобразование:
Пусть gensymN
будет именем, не используемым ни для какой другой переменной; затем введите следующий код
gensymN := 0;
while gensymN = 0 and A do B; gensymN = 1; od;
while gensymN = 0 do C; gensymN = 1; od
Семантика этой программы:
- Назначьте 0 для
gensymN
.
- Оценка
gensymN = 0 and A
(это правда, если A
верно)
- Если это правда, то:
- выполнить
B
- выполнить
gensymN = 1
- оценить
gensymN = 0 and A
(неверно)
- оценка
gensymN = 0
(неверно)
- else (если
gensymN = 0 and A
было ложным):
- оценить
gensymN = 0
(это правда)
- выполнить
C
- выполнить
gensymN := 1
- оценить
gensymN = 0
(неверно)
Обратите внимание на следующую подструктуру вышеупомянутого:
- (эффективно) оценивает
A
;
- Если true, выполняется
B
, в противном случае C
.
- Помимо
A
, B
и C
, программа (фрагмент) работает только с gensymN
, которого нет во входной программе.
Следовательно, эта программа имеет ту же семантику, что и
if A then B else C fi; gensymN := 1
Одна сноска: если A
истинно при оценке, она будет оценена еще раз (если and
не имеет короткого замыкания). Если язык позволяет хранить логические значения в переменных, можно ввести еще одну фиктивную переменную и сделать dummy := A; <insert the above program here, with dummy instead of A>
. Тогда две оценки dummy
по сути являются просто нагрузкой. Если оценка булевых выражений не может иметь побочных эффектов, предотвращение повторной оценки не является необходимым для корректности; это может (или не может) быть оптимизацией.
Примите вышесказанное как «мягкое доказательство» с оговорками предыдущего абзаца, что это правильный полностью общий перевод if
в while
. На мой взгляд, полная общность отличает этот (= Eamon's) ответ от других.