82 lines
5.8 KiB
HTML
82 lines
5.8 KiB
HTML
<html>
|
||
|
||
<head>
|
||
<object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e">
|
||
<param name="Keyword" value="yield">
|
||
<param name="Keyword" value="Итератор">
|
||
<param name="Keyword" value="Захват переменных в yield">
|
||
</object>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
|
||
<title></title>
|
||
<link rel="StyleSheet" href="../../default.css">
|
||
</head>
|
||
|
||
<body>
|
||
<H1>Оператор yield</H1>
|
||
<p>Оператор yield используется в функциях, генерирующих последовательности, и
|
||
имеет вид:</p>
|
||
<blockquote>
|
||
<p><b><code>yield</code></b> <i>выражение</i></p>
|
||
</blockquote>
|
||
<p>Функция, содержащая yieldы, называется <em>итератором</em>. При каждом вызове
|
||
такая функция выполняет код до следующего
|
||
yieldа, после чего заканчивает свою работу, возвращая значение выражения,
|
||
указанного в yieldе, и сохраняет своё состояние до следующего вызова. </p>
|
||
<p>Например:</p>
|
||
<blockquote>
|
||
<p><code><strong>function</strong> Squares(n: integer): <strong>sequence</strong>
|
||
<strong>of</strong> integer;<br><strong>begin</strong><br> <strong>for</strong> <strong>var</strong>
|
||
i:=1 <strong>to</strong> n <strong>do</strong><br> yield
|
||
i*i<br><strong>end</strong>;<br><br><strong>begin</strong><br> <strong>
|
||
var</strong> q := Squares(5);<br><br> <strong>foreach</strong> <strong>
|
||
var</strong> x <strong>in</strong> q <strong>do</strong><br>
|
||
Print(x);<br> Println;<br><br> q.Println;<br><strong>end</strong>. </code></p>
|
||
</blockquote>
|
||
<p>В данном примере переменная q хранит <a href="../Types/sequences.html">
|
||
последовательность</a>, т.е. алгоритм вычисления квадратов первых n чисел,
|
||
который будет запущен либо в цикле foreach по последовательности q, либо вызовом
|
||
метода расширения Println для последовательности q. Данные последовательности
|
||
поочередно возвращаются вызовами оператора yield в теле функции Squares.</p>
|
||
<p>После каждого вызова оперматора yield функция возвращает следующее значение
|
||
i*i, заканчивает свою работу и сохраняет значения всех своих переменных во
|
||
внутреннем контексте. При следующем вызове этой функции её тело как бы начинает
|
||
выполняться с той точки, в которой мы оказались в конце предыдущего вызова.</p>
|
||
<p>В выражении yield могут фигурировать внешние относительно функции переменные.
|
||
Говорят, что оператор yield осуществляет захват таких переменных. Например:</p>
|
||
<blockquote>
|
||
<p><code><strong>var</strong> a := 2;<br><br><strong>function</strong>
|
||
Squares(n: integer): <strong>sequence of</strong> integer;<br><strong>begin</strong><br>
|
||
<strong>for var</strong> i:=1 <strong>to</strong> n <strong>do</strong><br>
|
||
yield i*a<br><strong>end</strong>;<br><br><strong>begin</strong><br>
|
||
<strong>var</strong> q := Squares(5);<br><br> q.Println;<br> a
|
||
:= 3;<br> q.Println;<br><strong>end</strong>. </code></p>
|
||
</blockquote>
|
||
<p>В данном коде оператор yield захватывает переменную a из внешнего контекста.
|
||
Захват производится по ссылке: если изменить переменную a в основной программе и
|
||
повторно вызвать функцию-итератор, то при генерации последовательности будет
|
||
использовано измененное значение переменной a. В итоге вывод данной программы
|
||
будет иметь вид:</p>
|
||
<blockquote>
|
||
<p><code>
|
||
2 4 6 8 10<br>3 6 9 12 15</code></p>
|
||
</blockquote>
|
||
<p>Для функций, в теле которых присутствуют yield, имеется ряд ограничений:</p>
|
||
<ol>
|
||
<li>Функции, содержащие yield, могут возвращать только последовательности.</li>
|
||
<li>Среди параметров функций-итераторов не может быть const, var,
|
||
params-параметров и параметров по умолчанию.</li>
|
||
<li>Если функция использует yield, в ней запрещено использовать переменную
|
||
Result, и наоборот.</li>
|
||
<li>Функции с yield не могут содержать операторы lock, try...except,
|
||
try..finally.</li>
|
||
<li>Yield не может быть вложена в оператор with.</li>
|
||
<li>Yield не может быть использована внутри лямбда-выражений.</li>
|
||
<li>Функции с yield не могут содержать вложенные подпрограммы и сами быть
|
||
вложенными подпрограммами.</li>
|
||
<li>Функции с yield не могут содержать локальные определения типов</li>
|
||
<li>Методы расширения с yield не могут быть рекурсивными.</li>
|
||
</ol>
|
||
</body>
|
||
|
||
</html>
|