Опубликован: 19.03.2004 | Доступ: платный | Студентов: 12 / 0 | Оценка: 3.98 / 3.79 | Длительность: 17:50:00
ISBN: 978-5-9556-0008-6
Лекция 2:

Элементарный Лисп

< Лекция 1 || Лекция 2: 1234 || Лекция 3 >
Аннотация: Изучается ключевой метод функционального программирования — выбор семантического базиса для класса решаемых задач на примере организации информационной обработки символьными выражениями в языке Лисп. Вводятся базовые понятия, достаточные для символьного представления программ. Формализм рекурсивных функций и простые алгоритмы символьной обработки привлечены для обоснования и демонстрации функционального подхода к представлению программ. Анализируются требования к полноте и эффективности их обработки. В качестве исторической иллюстрации полномасштабного применения функционального программирования для решения достаточно сложной задачи используется символика языка Лисп, выбранная при организации символьной обработки для решения задач искусственного интеллекта.
Ключевые слова: символьная обработка, информация, слово, преобразования формул, парадигма программирования, функциональный подход, определение, программирование, данные, Лисп, S-выражение, структура, подвыражение, функция, график функции, универсальная функция, кратность, значение, атом, символ, хэш-таблица, блок памяти, consolidation, пустой список, список, списочная запись, истинностное значение, константа, точечная нотация, тождество, составной объект, предикат, имя, notation, переменная, ветвление, вызов функции, форма, аргумент функции, Common Lisp, определение функции, формальный результат, имя новой функции, процесс обработки данных, композиция функций, аппликативная система, Sisal, основное тождество, специальная функция, базовая функция, блокировка вычислений, условное выражение, cond, predicate, defun, GNU Clisp, рекурсивное определение, процесс исполнения, число, элементарный тип, лямбда-исчисление, лямбда-конструктор, формальный аргумент, псевдо-функция, конструирование определения функции, глобальные связи, чистый Лисп, функциональный аргумент, базис Лисп-интерпретатора, правило интерпретации выражений, ассоциативный список

Основы символьной обработки. Базовые средства

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

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

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

Функциональное программирование отличается от большинства подходов к программированию тремя важными принципами:

1) Природа данных

Все данные представляются в форме символьных выражений. В Лиспе Дж. Маккарти назвал их S-выражениями. Состав S-выражений и типы их элементов не ограничиваются, что позволяет их использовать как древообразные структуры . Это позволяет локализовывать любые важные подвыражения. Система программирования над такими структурами обычно использует для их хранения всю доступную память, поэтому программист освобожден от распределения памяти под отдельные блоки данных.

2) Самоописание обработки символьных выражений

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

3) Подобие машинным языкам

Система функционального программирования допускает, что программа может интерпретировать и/или компилировать программы, представленные в виде S-выражений. Это сближает методы функционального программирования с методами низкоуровнего программирования и отличает от традиционной методики применения языков высокого уровня.

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

Наиболее очевидные следствия из выбранных принципов:

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

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

Данные

Любые структуры   данных начинаются с элементарных значений. Следуя Лиспу, в функциональном программировании такие значения называют атомами или символами. Внешне атом обычно выглядит как последовательность из букв и цифр, начинающаяся с буквы. В первых реализациях Лиспа было принято ограничивать длину атома, но ограничение было не слишком жестким (30 литер). Теперь ограничивают лишь число значащих литер (порядка 60), по которым атомы распознаются как различимые объекты с помощью хэш-таблицы объектов.

A
ATOM
ВотВесьмаДлинныйАтомНоЕслиНадоТоАтомМожетБытьЕщеДлинннее
Ф4длш139к131б

Одинаково выглядящие атомы не различимы по своим свойствам, хотя проявления этих свойств могут быть обусловлены контекстом использования атомов. Термин "атом" выбран по аналогии с химическими атомами. Согласно этой аналогии атом может иметь достаточно сложное строение, но оно не рассматривается как обычное S-выражение. Устройство атома реализационно зависимо и лишь соответствует некоторой спецификации, содержание которой будет рассмотрено в девятой лекции. Атом не предназначен для разбора на части базовыми средствами языка.

Более сложные данные выстраиваются из унифицированных структур данных — одинаково устроенных блоков памяти. В Лиспе это бинарные узлы, содержащие пары объектов произвольного вида. Каждый бинарный узел соответствует минимальному блоку памяти, выделяемому системой программирования при организации и обработке структур данных . Выделение блока памяти и размещение в нем пары данных выполняет функция CONS (от слова consolidation), а извлечение левой и правой частей из блока выполняют функции CAR и CDR, соответственно. (В других языках функционального программирования используются векторы, кортежи, последовательности, потоки, множества, сети и другие структуры данных, обладающие достаточной гибкостью, т.е. способностью к организации единого доступа к любому числу элементов произвольного типа.)

CONS =>> [CAR | CDR]

Бинарный узел, содержащий пару атомов   ATOM и NIL, рассматривается как одноэлементный список:

(ATOM) = [ ATOM | NIL ]

Если вместо атома   ATOM рекурсивно подставлять произвольные атомы, а вместо NIL — произвольные списки, затем вместо ATOM — построенные списки и так далее, то мы получим множество всех возможных списков. Атом   NIL играет роль пустого списка и фактически эквивалентен ему. Можно сказать, что список — это заключенная в скобки последовательность из атомов, разделенных пробелами, или списков .

ATOM
(A B)
(A B C D E F G H I J K L M N O P R S T U V W X Y Z)
(C (A B))
((A B) C)
((A B) (D C))
((A B)(D(C E)))

Такая форма представления информации называется списочной записью (list-notation). Ее основные достоинства — лаконичность, удобство набора и отсутствие "синтаксического сахара". Она достаточно отражает взаимосвязи структур данных, размещаемых в памяти, и помогает задавать процедуры доступа к их компонентам.

Любой список может быть построен из пустого списка и атомов с помощью CONS, и любая его часть может быть выделена с помощью подходящей композиции CAR-CDR.

Функция CONS строит списки из бинарных узлов, заполняя их парами объектов, являющихся значениями пары ее аргументов. Первый аргумент произвольного вида размещается в левой части бинарного узла, а второй, являющийся списком, — в правой.

Функция CAR обеспечивает доступ к первому элементу списка — его "голове", а функция CDR — к укороченному на один элемент списку — его "хвосту", т.е. к тому, что остается после удаления головы.

Функция ATOM позволяет различать составные и атомарные объекты: на атомах ее значение "истина", а на структурированных объектах — "ложь".

Функция EQ выполняет проверку атомарных объектов на равенство.

Различие истинностных значений в Лиспе принято отождествлять с разницей между пустым списком и остальными объектами, которым программист может придать в программе некоторый другой смысл. Таким образом, значение "ложь" — это всегда   NIL. (Во многих языках программирования используется 0 – 1 или идентификаторы True — False и др.)

Если требуется явно изобразить истинностное значение, то для определенности в качестве значения "истина" используется константаатом   T (true) как стандартное представление, но роль такого значения может выполнить любой, отличный от пустого списка, объект.

< Лекция 1 || Лекция 2: 1234 || Лекция 3 >
Дарья Федотова
Дарья Федотова
Сергей Березовский
Сергей Березовский

В рамках проф. переподготовки по программе "Программирование"

Есть курсы, которые я уже прошел. Но войдя в курс я вижу, что они не зачтены (Язык Ассемблера и архитектура ЭВМ, Программирование на С++ для профессионалов). Это как?

Алина Ленкова
Алина Ленкова
Россия, Ставрополь, СФ МГУПИ, 2014
Валерий Ромашов
Валерий Ромашов
Россия