|
||||
Меню:
Главная
Форум
Литература: Программирование и ремонт Импульсные блоки питания Неисправности и замена Радиоэлектронная аппаратура Микросхема в ТА Рубрикатор ТА Кабельные линии Обмотки и изоляция Радиоаппаратура Гибкие диски часть 2 часть 3 часть 4 часть 5 Ремонт компьютера часть 2 Аналитика: Монтаж Справочник Электроника Мощные высокочастотные транзисторы 200 микросхем Полупроводники ч.1 Часть 2 Алгоритмические проблемы 500 микросхем 500 микросхем Сортировка и поиск Монады Передача сигнала Электроника Прием сигнала Телевидиние Проектирование Эвм Оптимизация Автомобильная электроника Поляковтрансиверы Форт Тензодатчик Силовые полевые транзисторы Распределение частот Резисторные и термопарные Оберон Открытые системы шифрования Удк |
[89] (if (has-value? me) (inform-about-value new-constraint)) done) (define (me request) (cond ((eq? request has-value?) (if informant true false)) ((eq? request value) value) ((eq? request set-value!) set-my-value) ((eq? request forget) forget-my-value) ((eq? request connect) connect) (else (error "Неизвестная операция -- CONNECTOR" request)))) me)) Внутренняя процедура соединителя set-my-value зовется, когда поступает требование установить значение соединителя. Если у соединителя нет текущего значения, он его устанавливает и запоминает ограничение, которое потребовало установки значения, в переменной informant.32 Затем соединитель оповещает все связанные с ним ограничения, кроме того, которое потребовало установить значение. Это проделывается с помощью следующего итератора, который применяет указанную процедуру ко всем элементам списка, кроме одного. (define (for-each-except exception procedure list) (define (loop items) (cond ((null? items) done) ((eq? (car items) exception) (loop (cdr items))) (else (procedure (car items)) (loop (cdr items))))) (loop list)) Если от соединителя требуют забыть значение, он запускает внутреннюю процедуру forget-my-value, которая первым делом убеждается, что запрос исходит от того же самого объекта, который значение установил. Если это так, соединитель оповещает связанные с ним ограничения о потере значения. Внутренняя процедура connect добавляет указанное ограничение к списку ограничений, если его там еще нет. Затем, если у соединителя есть значение, он сообщает об этом ограничению. Процедура соединителя me служит диспетчером для остальных внутренних процедур, а кроме того, представляет соединитель как объект. Следующие процедуры предоставляют синтаксический интерфейс к диспетчеру: (define (has-value? connector) (connector has-value?)) (define (get-value connector) (connector value)) (define (set-value! connector new-value informant) ((connector set-value!) new-value informant)) (define (forget-value! connector retractor) 32Setter может и не быть ограничением. В примере с температурой мы использовали символ user в качестве значения setter. ((connector forget) retractor)) (define (connect connector new-constraint) ((connector connect) new-constraint)) Упражнение 3.33. С помощью элементарных ограничений сумматор, умножитель и константа, определите процедуру averager (усреднитель), которая принимает три соединителя a, b и c, и обеспечивает условие, что значение c равно среднему арифметическому значений a и b. Упражнение 3.34. Хьюго Дум хочет построить квадратор, блок-ограничение с двумя выводами, такое, что значение соединителя b на втором выводе всегда будет равно квадрату значения соединителя a на первом выводе. Он предлагает следующее простое устройство на основе умножителя: (define (squarer a b) (multiplier a a b)) В такой идее есть существенная ошибка. Объясните ее. Упражнение 3.35. Бен Битобор объясняет Хьюго, что один из способов избежать неприятностей в упражнении 3.34 - определить квадратор как новое элементарное ограничение. Заполните недостающие части в Беновой схеме процедуры, реализующей такое ограничение: (define (squarer a b) (define (process-new-value) (if (has-value? b) (if (< (get-value b) 0) (error "квадрат меньше 0 -- SQUARER" (get-value b)) (альтернатива!)) (альтернатива2))) (define (process-forget-value) (тело!)) (define (me request) (тело2)) (остаток определения) me) Упражнение 3.36. Допустим, что мы выполняем следующую последовательность действий в глобальном окружении: (define a (make-connector)) (define b (make-connector)) (set-value! a 10 user) В какой-то момент при вычислении set-value! будет выполнено следующее выражение из внутренней процедуры соединителя: (for-each-except setter inform-about-value constraints) Нарисуйте диаграмму, изображающую окружение, в котором выполняется указанное выражение. Упражнение 3.37. Процедура celsius-fahrenheit-converter выглядит громоздко по сравнению со стилем определения в формате выражения: (define (celsius-fahrenheit-converter x) (c+ (c* (c/ (cv 9) (cv 5)) x) (cv 32))) (define C (make-connector)) (define F (celsius-fahrenheit-converter C)) Здесь c+, c* и т. п. - «ограничительные» версии арифметических операций. Например, c+ берет в виде аргументов два соединителя, и возвращает соединитель, который связан с ними ограничением-сумматором: (define (c+ x y) (let ((z (make-connector))) (adder x y z) z)) Определите аналогичные процедуры для c-, c*, c/ и cv (константа), так, чтобы можно было определять составные ограничения, как в вышеприведенном примере.33 3.4 Параллелизм: время имеет значение Мы убедились в мощности вычислительных объектов с внутренним состоянием в качестве инструмента моделирования. Однако, как было сказано в разделе 3.1.3, за эту мощность приходится платить потерей референциальной прозрачности, которая ведет в дебри вопросов об идентичности и изменении, и необходимостью замены подстановочной модели вычислений на более сложную модель с окружениями. 33Представление в виде выражений удобно, потому что при этом отпадает необходимость давать имена промежуточным выражениям в вычислении. Наша исходная формулировка языка ограничений громоздка по той же причине, по которой многие языки оказываются громоздкими при работе с составными данными. Например, если нам нужно вычислить произведение (а + b) • (c + d), где переменные представляют вектора, мы можем работать в «императивном» стиле, с процедурами, которые присваивают значения указанным векторным аргументам, но сами не возвращают вектора как значения: (v-sum a b templ) (v-sum c d temp2) (v-prod templ temp2 answer) С другой стороны, мы можем работать с выражениями, используя процедуры, которые возвращают вектора как значения, и таким образом избежать прямого упоминания tempi и temp2: (define answer (v-prod (v-sum a b) (v-sum c d))) Поскольку Лисп позволяет возвращать составные объекты как результаты процедур, мы можем преобразовать свой императивный язык ограничений в язык на основе выражений, как показано в этом упражнении. В языках, где средства работы с составными объектами бедны, как в Алголе, Бейсике и Паскале (если явно не использовать паскалевские переменные-указатели), обычно при решении таких задач программист ограничен императивным стилем. Поскольку формат выражений предпочтителен, можно спросить, есть ли причина строить систему императивно, как мы поступили в этом разделе. Одна из причин состоит в том, что язык ограничений, не ориентированный на выражения, дает нам возможность работать не только с объектами-соединителями, но и с объектами-ограничениями (например, значением, порождаемым процедурой adder). Это будет полезно, если мы захотим расширить систему новыми операциями, которые работают с ограничениями напрямую, а не только косвенным образом через операции над соединителями. Хотя реализовать работу с выражениями на основе императивной реализации просто, сделать обратное значительно труднее. |
Среды: Smalltalk80 MicroCap Local bus Bios Pci 12С ML Микроконтроллеры: Atmel Intel Holtek AVR MSP430 Microchip Книги: Емкостный датчик 500 схем для радиолюбителей часть 2 (4) Структура компьютерных программ Автоматическая коммутация Кондиционирование и вентиляция Ошибки при монтаже Схемы звуковоспроизведения Дроссели для питания Блоки питания Детекторы перемещения Теория электропривода Адаптивное управление Измерение параметров Печатная плата pcad pcb Физика цвета Управлении софтверными проектами Математический аппарат Битовые строки Микроконтроллер nios Команды управления выполнением программы Перехода от ahdl к vhdl Холодный спай Усилители hi-fi Электронные часы Сердечники из распылённого железа Анализ алгоритмов 8-разрядные КМОП Классификация МПК История Устройства автоматики Системы и сети Частотность Справочник микросхем Вторичного электропитания Типы видеомониторов Радиобиблиотека Электронные системы Бесконтекстный язык Управление техническими системами Монтаж печатных плат Работа с коммуникациями Создание библиотечного компонента Нейрокомпьютерная техника Parser Пи-регулятор ч.1 ПИ-регулятор ч.2 Обработка списков Интегральные схемы Шина ISAВ Шина PCI Прикладная криптография Нетематическое: Взрывной автогидролиз Нечеткая логика Бытовые установки (укр) Автоматизация проектирования Сбор и защита Дискретная математика Kb радиостанция Энергетика Ретро: Прием в автомобиле Управление шаговым двигателем Магнитная запись Ремонт микроволновки Дискретные системы часть 2 | ||