Книги
чёрным по белому
Главное меню
Главная О нас Добавить материал Поиск по сайту Карта книг Карта сайта
Книги
Археология Архитектура Бизнес Биология Ветеринария Военная промышленность География Геология Гороскоп Дизайн Журналы Инженерия Информационные ресурсы Искусство История Компьютерная литература Криптология Кулинария Культура Лингвистика Математика Медицина Менеджмент Металлургия Минералогия Музыка Научная литература Нумизматика Образование Охота Педагогика Политика Промышленные производства Психология Путеводители Религия Рыбалка Садоводство Саморазвитие Семиотика Социология Спорт Столярное дело Строительство Техника Туризм Фантастика Физика Футурология Химия Художественная литература Экология Экономика Электроника Энергетика Этика Юриспруденция
Новые книги
Янин В.Л. "Новгородские акты XII-XV Хронологический комментарий" (История)

Майринк Г. "Белый доминиканец " (Художественная литература)

Хусаинов А. "Голоса вещей. Альманах том 2" (Художественная литература)

Петров Г.И. "Отлучение Льва Толстого " (Художественная литература)

Хусаинов А. "Голоса вещей. Альманах том 1 " (Художественная литература)
Реклама

Структура и интерпритация компьютерных программ - Абельсон Х.

Абельсон Х. Структура и интерпритация компьютерных программ — М.: Добросвет, 2006. — 608 c.
ISBN 978-5-98227-708-4
Скачать (прямая ссылка): strukturaiinterpretacii2006.pdf
Предыдущая << 1 .. 13 14 15 16 17 18 < 19 > 20 21 22 23 24 25 .. 269 >> Следующая


Важность декомпозиционной стратегии не просто в том, что задача разделяется на части. В конце концов, можно взять любую большую программу и поделить ее на части: первые десять строк, следующие десять строк и так далее. Существенно то, что каждая процедура выполняет точно определенную задачу, которая может быть использована при определении других процедур. Например, когда мы определяем процедуру good-enough? с помощью square, мы можем рассматривать процедуру square как «черный ящик». В этот момент нас не интересует, как она вычисляет свой результат, — важно только то, что она способна вычислить квадрат. О деталях того, как вычисляют квадраты, можно сейчас забыть и рассмотреть их потом. Действительно, пока мы рассматриваем процедуру good-enough?, square — не совсем процедура, но скорее абстракция процедуры, так называемая процедурная абстракция (procedural abstraction). На этом уровне абстракции все процедуры, вычисляющие квадрат, одинаково хороши.

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

25

числа25.

(define (square x) (* x x))

(define (square x)

(exp (double (log x))))

(define (double x) (+ x x))

Таким образом, определение процедуры должно быть способно скрывать детали. Мо-

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

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

45

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

Локальные имена

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

(define (square x) (* x x))

(define (square y) (* y y))

Этот принцип — что значение процедуры не должно зависеть от имен параметров, которые выбрал ее автор, — может сначала показаться очевидным, однако он имеет глубокие следствия. Простейшее из этих следствий состоит в том, что имена параметров должны быть локальными в теле процедуры. Например, в программе вычисления квадратного корня при определении good-enough? мы использовали square:

(define (good-enough? guess x)

(< (abs (- (square guess) x)) 0.001))

Намерение автора good-enough? состоит в том, чтобы определить, достаточно ли близко квадрат первого аргумента лежит ко второму. Мы видим, что автор good-enough? обращается к первому аргументу с помощью имени guess, а ко второму с помощью имени x. Аргументом square является guess. Поскольку автор square использовал имя x (как мы видели выше), чтобы обратиться к этому аргументу, мы видим, что x в good-enough? должно отличаться от x в square. Запуск процедуры square не должен отразится на значении x, которое использует good-enough?, поскольку это значение x понадобится good-enough?, когда square будет вычислена.

Если бы параметры не были локальны по отношению к телам своих процедур, то параметр x в square смешался бы с параметром x из good-enough?, и поведение good-enough? зависело бы от того, какую версию square мы использовали. Таким образом, процедура square не была бы черным ящиком, как мы того хотим.

У формального параметра особая роль в определении процедуры: не имеет значения, какое у этого параметра имя. Такое имя называется связанной переменной (bound variable), и мы будем говорить, что определение процедуры связывает (binds) свои формальные параметры. Значение процедуры не изменяется, если во всем ее определении параметры последовательным образом переименованы26. Если переменная не связана, мы говорим, что она свободна (free). Множество выражений, для которых связывание определяет имя, называется областью действия (scope) этого имени. В определении процедуры связанные переменные, объявленные как формальные параметры процедуры, имеют своей областью действия тело процедуры.

В приведенном выше определении good-enough?, guess и x — связанные переменные, а <, -, abs и square — свободные. Значение good-enough? должно быть

26 Понятие последовательного переименования на самом деле достаточно тонкое и трудное для определения. Знаменитым логикам случалось делать здесь ужасные ошибки.

46

Глава 1. Построение абстракций с помощью процедур

независимо от того, какие имена мы выберем для guess и x, пока они остаются отличными друг от друга и от <, -, abs и square. (Если бы мы переименовали guess в abs, то породили бы ошибку, захватив (capture) переменную abs. Она превратилась бы из свободной в связанную.) Однако значение good-enough? не является независимым от ее свободных переменных. Разумеется, оно зависит от того факта (внешнего по отношению к этому определению), что символ abs называет процедуру вычисления модуля числа. Good-enough? будет вычислять совершенно другую функцию, если в ее определении мы вместо abs подставим cos .
Предыдущая << 1 .. 13 14 15 16 17 18 < 19 > 20 21 22 23 24 25 .. 269 >> Следующая