|
||||
Меню:
Главная
Форум
Литература: Программирование и ремонт Импульсные блоки питания Неисправности и замена Радиоэлектронная аппаратура Микросхема в ТА Рубрикатор ТА Кабельные линии Обмотки и изоляция Радиоаппаратура Гибкие диски часть 2 часть 3 часть 4 часть 5 Ремонт компьютера часть 2 Аналитика: Монтаж Справочник Электроника Мощные высокочастотные транзисторы 200 микросхем Полупроводники ч.1 Часть 2 Алгоритмические проблемы 500 микросхем 500 микросхем Сортировка и поиск Монады Передача сигнала Электроника Прием сигнала Телевидиние Проектирование Эвм Оптимизация Автомобильная электроника Поляковтрансиверы Форт Тензодатчик Силовые полевые транзисторы Распределение частот Резисторные и термопарные Оберон Открытые системы шифрования Удк |
[7] Looking for a: bool I have found a: int Тип size показывает, что она получает аргумент типа string и возвращает результат типа int (как мы и могли предполагать). Аналогично, not является функцией, получающей логический аргумент и возвращающей логический результат. Поскольку функции не имеют никакого внешнего представления, все они печатаются как f п. Применение not к 3 вызывает ошибку, поскольку тип области определения not есть bool, в то время как тип 3 есть int. Поскольку функции являются значениями, мы можем привязать идентификатор к функции, используя обычный механизм привязки идентификатора к значению, введенный в предыдущем разделе. Например: -val len = size; >vai len = fn : string -> int -len "abc"; >3 : int Идентификатор size привязан к некоторой (предопределенной) функции типа string->int. Приведенная выше привязка выполняется так: извлекается значение идентификатора size (которое является функцией), и затем к этому значению привязывается идентификатор len. Аппликация len "abc" вычисляется путем извлечения функции, к которой привязан идентификатор len, вычисления значения "abc" (которым является сама эта строка) и применения функции к строке. Результатом является 3, поскольку функция, к которой в ML привязан идентификатор size, возвращает количество литер в строке-аргументе. Функции являются составными объектами; однако они не являются построенными путем соединения других объектов в том смысле, в каком, например, упорядоченная пара построена из своих компонент. Поэтому их структура недоступна программисту, и, в частности, к функциям неприменимо сопоставление с образцом. Кроме того, невозможно проверить экстенсиональное равенство функций (т.е. выдают ли две функции равные результаты при равных аргументах), поскольку это является алгоритмически неразрешимой задачей. Заметим, что для всех других ранее введенных типов равенство имелось. В дальнейшем мы будем говорить, что тип допускает проверку на равенство, если мы можем для любых двух значений этого типа проверить, равны они или нет. Никакой функциональный тип не допускает проверки на равенство, а любой атомарный тип - допускает. Что же можно сказать относительно других составных типов? Напомним, что равенство упорядоченных пар было определено как "покомпонентное": две упорядоченных пары равны тогда и только тогда, когда равны их левые компоненты и равны их правые ство. Аналогичные правила применимы и к типам, построенным другими способами. Грубое, но часто дающее правильный ответ правило состоит в том, что тип, при построении которого использовались функциональные типы, не допускает проверки на равенство (это не всегда верно; когда вы лучше познакомитесь с ML, изучите точное определение допустимости проверки на равенство в [7]). После приведенных выше замечаний мы готовы перейти к обсуждению способов определения функций пользователем. Синтаксис определения функции во многом похож на используемый в других языках. Приведем несколько примеров: -fun twice х = 2*х; >val twice = fn : int->int -twice 4; >8 : int -fun fact x = if x=0 then 1 else x*fact(x-l); >val fact = fn : int->int -fact 5; >120 : int -fun plus(x.y) : int = x+y >val plus = fn : int*int->int -plus(4,5); >9 : int Функции определяются путем привязки идентификатора к функциональному значению; эта конструкция начинается ключевым словом fun. За именем функции следуют ее параметры, которые задаются образцом. В первых двух примерах параметр является простым образцом, состоящим из одного идентификатора; в третьем примере образец является упорядоченной парой, левая компонента которой есть х и правая у. Когда выполняется применение определенной пользователем функции, значение аргумента сопоставляется с параметром-образцом - точно так же, как и при привязке к значению; результатом этого сопоставления является некоторая среда, в которой и выполняется вычисление тела функции. Например, в случае функции twice, х привязывается к аргументу (который должен быть целым числом, поскольку тип функции twice есть int->int) и затем вычисляется тело функции twice (т.е. 2*х); результатом является 8. В случае функции plus сопоставление с образцом несколько более сложное, поскольку аргумент является упорядоченной парой, - однако это сопоставление ничем не отличается от привязки к значению, рассмотренной в предыдущем разделе: значение аргумента сопоставляется с образцом (х,у), в результате чего х и у привязываются к значениям. Затем в полученной среде вычисляется значение тела функции, и результат определяется по обычным правилам. ": int" в определение plus называется явным ограничением типа, оно здесь необходимо, поскольку из контекста невозможно определить, о сложении значений какого типа - int или real - идет речь. Позже мы обсудим явные ограничения типа более подробно. Упражнение 2.5.1 Запишите функции circumference и area, вычисляющие соответственно длину окружности и площадь круга по радиусу. Упражнение 2.5.2 Запишите функцию, вычисляющую модуль действительного числа. Определение функции fact иллюстрирует важную особенность определения функций в ML: функции, определяемые с помощью конструкции fun, являются рекурсивными; это означает, что вхождения идентификатора fact в правую часть определения функции fact ссылаются на определяемую функцию (а не какое-либо другое значение, к которому мог бы быть привязан идентификатор fact в окружающей среде). Таким образом, функция fact в процессе вычисления ее тела вызывает саму себя. Обратите внимание на то, что при каждом следующем рекурсивном вызове аргумент функции fact становится меньше, что гарантирует, что процесс вычисления функции завершится (если исходное значение аргумента было неотрицательным). Конечно, возможны и определения функций, вычисление которых никогда не завершается. Например: - fun f(x) = f(x); > val f = fn : a->b Любой вызов f приведет к возникновению бесконечного цикла, в котором f вызывает себя снова и снова. Упражнение 2.5.3 Альтернативный синтаксис для условного выражения может быть определен как: fun new if ( А, В, С ) = if A then В else С Объясните, что станет неправильным в определении функции fact, если в нем использовать этот новый вариант условного выражения. Теперь мы готовы продолжить построение новых интересных функций и примеров программирования на ML. Рекурсия является ключевым моментом функционального программирования, и поэтому, если вы еще не очень хорошо овладели этим приемом, мы советуем вам внимательно разбирать все приводимые примеры и проводить вычисление рекурсивны х функций "вручную". |
Среды: 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 | ||