Programming Taskbook 0


Download 1.62 Mb.
Pdf ko'rish
bet25/71
Sana21.06.2023
Hajmi1.62 Mb.
#1644761
TuriУчебное пособие
1   ...   21   22   23   24   25   26   27   28   ...   71
Bog'liq
Abramyan-Pascal2016-1


0.01 
0.04 
0.09 
0.16 
0.25 
0.36 
0.49 
0.64 
0.81 


0.81 
0.64 
0.49 
0.36 
0.25 
0.16 
0.09 
0.04 
0.01 



Глава 3. Массивы и последовательности 
45 
Завершив на этом обсуждение функции Range, обратимся к функции 
SeqWhile. Она имеет два перегруженных варианта со следующими заголов-
ками (напомним, что мы условились для краткости не указывать текст  
после имени обобщенной функции): 
function SeqWhile(first: T; next: T -> T; pred: T -> boolean):
sequence of T 
function SeqWhile(first, second: T; next: (T,T) -> T;
pred: T -> boolean): sequence of T 
Данная функция имеет в числе своих параметров два лямбда-выраже-
ния. Первое из них, next, определяет правило, по которому следующий 
элемент последовательности будет сгенерирован на основе одного или 
двух предыдущих, а второе, pred (от слова predicate — предикат), опреде-
ляет, когда следует прекратить заполнение последовательности. Последо-
вательность заполняется до тех пор, пока предикат pred возвращает True 
для очередного значения, полученного функцией next; только в этом случае 
полученное значение добавляется в последовательность. Как только значе-
ние, возвращенное функцией next, перестанет удовлетворять предикату, 
построение последовательности завершится; таким образом, можно утвер-
ждать, что все элементы полученной последовательности будут удовле-
творять предикату pred. Параметры first и second функции SeqWhile задают 
начальные значения формируемой последовательности (одно, если рекур-
рентная формула next использует одно предыдущее значение, и два, если 
формула next использует два предыдущих значения). Эти начальные значе-
ния также проверяются предикатом pred; если, например, для параметра 
first предикат pred вернет значение False, то функция SeqWhile вернет пу-
стую последовательность. 
Интересной особенностью функции SeqWhile является то, что при ее 
вызове неизвестен размер той последовательности, которую она создаст. 
Это отличает ее от всех функций-генераторов, которые являются общими 
для массивов и последовательностей (ArrFill и SeqFill, ArrGen и SeqGen, 
ArrRandom и SeqRandom и т. п.). Во всех функциях-генераторах массивов 
вначале выделяется память для хранения элементов массива, а затем они 
заполняются по тому или иному алгоритму. Именно поэтому в наборе ге-
нераторов для массивов отсутствует аналог функции SeqWhile: любая реа-
лизация подобного генератора для массива была бы неэффективной.
В случае же последовательностей никаких проблем с реализацией 
функции SeqWhile не возникает, поскольку при генерации последователь-
ности ее элементы не размещаются в памяти. Фактический перебор эле-
ментов последовательности выполняется либо в цикле foreach, либо при 
выполнении некоторых видов запросов (например, уже использовавшегося 


46 
нами запроса Sum), либо при ее выводе с помощью соответствующих про-
цедур или методов. 
При анализе функции SeqWhile можно задаться таким вопросом: что 
произойдет, если предикат pred никогда не вернет значение False? Если бы 
предикат использовался в качестве условия обычного цикла while, то про-
изошло бы зацикливание программы. В нашем случае ситуация будет ин-
тереснее: последовательность будет успешно создана (поскольку для ее со-
здания не требуется генерировать все ее элементы; достаточно сохранить 
каким-либо образом способ их генерации). Проблемы возникнут при по-
пытке перебрать все элементы этой «бесконечной» последовательности. 
Предположим, например, что мы создадим с помощью функции Se-
qWhile бесконечную последовательность Фибоначчи: 
var fib := SeqWhile(1.0, 1.0, (a, b) -> a + b, e -> True); 
Для того чтобы в этой последовательности правильно вычислялись 
числа Фибоначчи с большими номерами, мы указали в качестве начальных 
значений вещественные числа.
Данный оператор успешно откомпилируется и не приведет к каким-
либо проблемам при запуске программы. Однако при попытке вывести 
элементы этой последовательности в цикле foreach мы, как и следовало 
ожидать, получим зациклившуюся программу. Зацикливание произойдет и 
при попытке подсчитать, например, сумму всех элементов нашей последо-
вательности с помощью вызова fib.Sum. 

Download 1.62 Mb.

Do'stlaringiz bilan baham:
1   ...   21   22   23   24   25   26   27   28   ...   71




Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©fayllar.org 2024
ma'muriyatiga murojaat qiling