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

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

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

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

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

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

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


Внутренние определения и блочная структура

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

(define (sqrt x)

(sqrt-iter 1.0 x))

(define (sqrt-iter guess x)

(if (good-enough? guess x) guess

(sqrt-iter (improve guess x) x)))

(define (good-enough? guess x)

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

(define (improve guess x)

(average guess (/ x guess)))

Проблема здесь состоит в том, что единственная процедура, которая важна для пользователей sqrt — это сама sqrt. Остальные процедуры (sqrt-iter, good-enough? и improve) только забивают им головы. Теперь пользователи не могут определять других процедур с именем good-enough? ни в какой другой программе, которая должна работать совместно с программой вычисления квадратного корня, поскольку sqrt требуется это имя. Эта проблема становится особенно тяжелой при построении больших систем, которые пишут много различных программистов. Например, при построении большой библиотеки численных процедур многие числовые функции вычисляются как последовательные приближения и могут потому иметь в качестве вспомогательных процедуры good-enough? и improve. Нам хотелось бы локализовать подпроцедуры, спрятав их внутри sqrt, так, чтобы sqrt могла сосуществовать с другими последовательными приближениями, при том что у каждой из них была бы своя собственная процедура good-enough?. Чтобы сделать это возможным, мы разрешаем процедуре иметь внутренние определения, локальные для этой процедуры. Например, при решении задачи вычисления квадратного корня мы можем написать

(define (sqrt x)

(define (good-enough? guess x)

1.2. Процедуры и порождаемые ими процессы

47

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

(define (improve guess x)

(average guess (/ x guess)))

(define (sqrt-iter guess x)

(if (good-enough? guess x) guess

(sqrt-iter (improve guess x) x)))

(sqrt-iter 1.0 x))

Такое вложение определений, называемое блочной структурой (block structure), дает правильное решение для простейшей задачи упаковки имен. Но здесь таится еще одна идея. Помимо того, что мы можем вложить определения вспомогательных процедур внутрь главной, мы можем их упростить. Поскольку переменная x связана в определении sqrt, процедуры good-enough?, improve и sqrt-iter, которые определены внутри sqrt, находятся в области действия x. Таким образом, нет нужды явно передавать x в каждую из этих процедур. Вместо этого мы можем сделать x свободной переменной во внутренних определениях, как это показано ниже. Тогда x получит свое значение от аргумента, с которым вызвана объемлющая их процедура sqrt. Такой порядок называется лексической сферой действия (lexical scoping) переменных27.

(define (sqrt x)

(define (good-enough? guess)

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

(define (improve guess)

(average guess (/ x guess)))

(define (sqrt-iter guess)

(if (good-enough? guess) guess

(sqrt-iter (improve guess))))

(sqrt-iter 1.0))

Мы будем часто использовать блочную структуру, чтобы разбивать большие программы на куски разумного размера28. Идея блочной структуры происходит из языка программирования Алгол 60. Она присутствует в большинстве современных языков программирования. Это важный инструмент, который помогает организовать построение больших программ.

1.2. Процедуры и порождаемые ими процессы

В предыдущем разделе мы рассмотрели элементы программирования. Мы использовали элементарные арифметические операции, комбинировали их и абстрагировали получившиеся составные операции путем определения составных процедур. Но всего

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

28 Внутренние определения должны быть в начале тела процедуры. За последствия запуска программ, перемешивающих определения и их использование, администрация ответственности не несет.

48

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

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

Способность предвидеть последствия рассматриваемых действий необходима для того, чтобы стать квалифицированным программистом, — равно как и для любой другой синтетической, творческой деятельности. Например, квалифицированному фотографу нужно при взгляде на сцену понимать, насколько темным каждый ее участок покажется после печати при разном выборе экспозиции и разных условиях обработки. Только после этого можно проводить обратные рассуждения и выбирать кадр, освещение, экспозицию и условия обработки так, чтобы получить желаемый результат. Чтобы стать специалистами, нам надо научиться представлять процессы, генерируемые различными типами процедур. Только развив в себе такую способность, мы сможем научиться надежно строить программы, которые ведут себя так, как нам надо.
Предыдущая << 1 .. 14 15 16 17 18 19 < 20 > 21 22 23 24 25 26 .. 269 >> Следующая