Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Накапливающий параметр — аккумулятор

Элементы программирования

Локальные переменные

Охрана

При написании функций в абстрактной нотации допустимо использовать так называемую охрану, т.е. ограничения на значения переменных образца. Например, при использовании охраны функция Length будет выглядеть примерно следующим образом:

Length (L) = 0 when L == []

Length (L) = 1 + Length (tail (L)) otherwise

В рассмотренном коде слова when (когда) и otherwise (в противном случае) являются зарезервированными словами языка. Однако использование этих слов не является необходимым условием для организации охраны. Охрану можно организовывать различными способами, в том числе и с помощью l-исчисления:

Append = l[].(lL.L)

Append = l(H:T).(lL.H: Append (T, L))

Представленная запись не очень читабельна, поэтому использоваться она будет только в крайних случаях по необходимости.

Как уже говорилось, использование локальных переменных представляет собой побочный эффект, поэтому оно недопустимо в функциональных языках. Однако в некоторых случаях использование локальных переменных носит оптимизирующий характер, что позволяет сэкономить время и ресурсы во время вычислений.

Пусть f и h — функции, и необходимо вычислить выражение h (f (X), f(X)). Если в языке нет оптимизирующих методов, то в этом случае произойдет двойное вычисление выражения f (X). Чтобы этого не произошло, можно прибегнуть к такому изощренному способу: (lv.h (v, v))(f (X)). Естественно, что в этом случает выражение f (X) вычислится первым и один раз. Для того, чтобы минимизировать использование l-исчисления, далее будет применяться следующая форма записи:

let v = f (X) in h (v, v)

(слова let, = и in — зарезервированы в языке). В этом случае v будет называться локальной переменной.

Бывает так, что при выполнении функции исключительно серьезно встает проблема расхода памяти. Эту проблему можно пояснить на примере функции, вычисляющей факториал числа:

Factorial (0) = 1

Factorial (N) = N * Factorial (N – 1)

Если провести пример вычисления этой функции с аргументом 3, то можно будет увидеть следующую последовательность:

Factorial (3)

3 * Factorial (2)

3 * 2 * Factorial (1)

3 * 2 * 1 * Factorial (0)

3 * 2 * 1 * 1

3 * 2 * 1

3 * 2

На примере этого вычисления наглядно видно, что при рекурсивных вызовах функций очень сильно используется память. В данном случае количество памяти пропорционально значению аргумента, но аргументов может быть большее число, к примеру. Возникает резонный вопрос: можно ли так написать функцию вычисления факториала (и ей подобные), чтобы память использовалась минимально?

Чтобы ответить на данный вопрос положительно, необходимо рассмотреть понятие аккумулятора (накопителя). Для этого можно рассмотреть следующий пример:

Пример 10. Функция вычисления факториала с аккумулятором.

Factorial_A (N) = F (N, 1)

 

F (0, A) = A

F (N, A) = F ((N – 1), (N * A))

В этом примере второй параметр функции F выполняет роль аккумулирующей переменной, именно в ней содержится результат, который возвращается по окончании рекурсии. Сама же рекурсия в этом случае принимает вид «хвостовой», память при этом расходуется только на хранение адресов возврата значения функции.

Хвостовая рекурсия представляет собой специальный вид рекурсии, в которой имеется единственный вызов рекурсивной функции и при этом этот вызов выполняется после всех вычислений.

При реализации вычисления хвостовой рекурсии могут выполняться при помощи итераций в постоянном объеме памяти. На практике это обозначает, что «хороший» транслятор функционального языка должен «уметь» распознавать хвостовую рекурсию и реализовывать её в виде цикла. В свою очередь, метод накапливающего параметра не всегда приводит к хвостовой рекурсии, однако он однозначно помогает уменьшить общий объём памяти.

<== предыдущая лекция | следующая лекция ==>
Образцы и клозы | Программная реализация
Поделиться с друзьями:


Дата добавления: 2014-01-07; Просмотров: 348; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.01 сек.