Цикл while
Наиболее примитивной циклической конструкцией во многих языках программирования является цикл while
(англ. пока). Цикл while
, как правило, имеет следующий вид:
пока
верно условие
выполнять
действия
В качестве примера while
-цикла напишем на языке Java программу вычисления факториала в итеративном стиле:
int factorial(int n) {
int i = n;
int result = 1;
while (i != 0) {
result = result * i;
i--;
}
return result;
}
В этой функции условием
является отличие значения переменной i
от 0, а действиями — умножение значения переменной result
на значение переменной i
, и уменьшение значения этой переменной на 1.
Цикл while
не может быть запрограммирован в XSLT итеративно потому как действия, как правило, изменяют значения переменных, в контексте которых вычисляется условие, определяющее, продолжать выполнение цикла или нет. Дадим другую общую запись цикла while
, выделив изменение переменных:
пока
верно условие(x1,x2, ...,xn)
выполнить
x1' := функция1(x1,x2,...,xn)
х2' := функция2(x1,x2,...,xn)
...
xn' := функцияn(x1,x2,...,xn)
действия(x1,x2,...,хn)
x1 := x1'
x2 := x2'
...
xn := xn'
иначе
вернуть результат(x1,...,хn)
Переопределение значений переменных x
1, … , х
n в этом случае выполняют n
функций: функция
1 …, функция
n. И если изменить значение переменной мы не могли, переопределить связанное с ней значение мы вполне в состоянии, добавив в контекст новый параметр или переменную с тем же именем.
Теперь мы можем записать весь цикл while
как одну рекурсию:
while(x1, ..., xn) ::=
если
выполняется условие(x1, ..., xn)
то
действия(x1, ..., хn)
while(функция1(x1, ..., хn),
функция2(x1, ..., хn),
...,
функцияn(x1, ..., xn))
иначе
результат(x1, ..., хn)
Теперь уже совершенно очевидно, как while
-цикл должен выглядеть в преобразовании.
<xsclass="underline" template name="while">
<xsclass="underline" param name="x1"/>
<!-- ... -->
<xsclass="underline" param name="xn"/>
<xsclass="underline" choose>
<xsclass="underline" when test="условие($x1,...,$xn)">
<!-- Действия -->
<xsclass="underline" call-template name="while">
<xsclass="underline" with-param name="x1" select="функция_1($x1, ... $xn) "/>
<!-- ... -->
<xsclass="underline" with-param name="xn" select="функция_n($x1, ... $xn) "/>
</xsclass="underline" call-template>
</xsclass="underline" when>
<xsclass="underline" otherwise>
<xsclass="underline" value-of select="результат($x1, ..., $xn)"/>
</xsclass="underline" otherwise>
</xsclass="underline" choose>
</xsclass="underline" template>
В качестве примера приведем while
-цикл для программы, вычисляющей факториал. Java-код был следующим:
while (i != 0) {
result = result * i;
i--;
}
В этом цикле участвуют две переменные — i
и result
. Функции, использующиеся в этом цикле, запишутся следующим образом:
условие($1, $result) ::= ($i != 0)
функцияi($i, $result) ::= ($i - 1)
функцияresult($i, $result) ::= ($i * $result)
результат($I, $result) ::= ($result)
Именованный шаблон для этого случая будет иметь вид.
<xsclass="underline" template name="while">
<xsclass="underline" param name="i"/>
<xsclass="underline" param name="result"/>
<xsclass="underline" choose>
<xsclass="underline" when test="$i != 0">
<xsclass="underline" call-template name="while">
<xsclass="underline" with-param name="i" select="$i — 1"/>
<xsclass="underline" with-param name="result" select="$result * $i"/>
</xsclass="underline" call-template>
</xsclass="underline" when>
<xsclass="underline" otherwise>
<xsclass="underline" value-of select="$result"/>
</xsclass="underline" otherwise>
</xsclass="underline" choose>
</xsclass="underline" template>
Вызвать этот шаблон можно следующим образом:
<xsclass="underline" template match="/">
<xsclass="underline" call-template name="while">
<xsclass="underline" with-param name="i" select="6"/>
<xsclass="underline" with-param name="result" select="1"/>
</xsclass="underline" call-template>
</xsclass="underline" template>
Результатом будет, естественно, число 720
.
Цикл for
Частным случаем цикла while
является цикл for
. В разных языках программирования for
имеет различную семантику; мы будем рассматривать циклы for
вида
for (int i = 0; i < n; i++) { ... }
в языках Java и С или
for i := 0 to n-1 do begin ... end;
в Pascal. Иными словами, нас будет интересовать циклическое выполнение определенных действий при изменении значения некоторой переменной (называемой иногда индексом цикла) в интервале целых чисел от 0 до n включительно.
Цикл for
может быть определен через while
с использованием следующих условных и изменяющих функций: