Главная страница
Навигация по странице:

  • Введение

  • Язык программирования Лисп

  • 2. Особенности языка Лисп

  • Заключение

  • С

  • контрольная работа. контрольная работа по функциональному программированию. 1. 2 Арифметические функции


    Скачать 130.91 Kb.
    Название1. 2 Арифметические функции
    Анкорконтрольная работа
    Дата25.05.2022
    Размер130.91 Kb.
    Формат файлаdoc
    Имя файлаконтрольная работа по функциональному программированию.doc
    ТипРеферат
    #549609

    autoshape 1


    Содержание

    Введение……………………………………………………………………...3-4

    1. Язык программирования LISP ………………………………………..5-13

    1.1 Основные функции языка LISP……………………………………..5-7

    1.2 Арифметические функции……………………………………………..8

    1.3 Логические функции………………………………………………..9-10

    1.4 Специальные функции…………………………………………….11-13

    2. Особенности языка ЛИСП……………………………………………..14-18

    Заключение………………………………………………………………..19-20

    Список использованных источников……………………………………….21

    Введение

    LISP (от англ. LISt Processing - "обработка списков") - семейство языков программирования, основанных на представлении программы системой линейных списков символов, которые притом являются основной структурой данных языка. Лисп считается вторым после Фортрана старейшим высокоуровневым языком программирования.

    В 1950-х годах специалисты по искусственному интеллекту начали поиски языка программирования, который бы позволял манипулировать понятиями, выраженными словами и фразами на естественном языке. Первый результат был получен в виде семейства языков под названием ИПЛ (IPL, от Information Processing Languages - языки обработки информации), созданного одним из пионеров в области искусственного интеллекта Алленом Ньюэллом и его сотрудниками. Центральным для ИПЛ являлось понятие списка. Представляя данные в виде списка слов и символов, программист мог связать понятия в памяти компьютера приблизительно таким же образом, как, по мнению специалистов по искусственному интеллекту, они связываются в памяти человека.

    Понятием списка заинтересовался и Джон Маккарти, разносторонний математик, один из ведущих исследователей в области искусственного интеллекта (причем сам термин искусственный интеллект был предложен именно им в 1956 году). Язык Лисп был предложен Джоном Маккарти в работе в 1960 году и ориентирован на разработку программ для решения задач не численного характера. Английское название этого языка - LISP является аббревиатурой выражения LISt Processing (обработка списков) и хорошо подчеркивает основную область его применения. Понятие "список" оказалось очень емким. В виде списков удобно представлять алгебраические выражения, графы, элементы конечных групп, множества, правила вывода и многие другие сложные объекты.

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

    После появления LISP различными авторами был предложен целый ряд других алгоритмических языков ориентированных на решение задач в области искусственного интеллекта. Однако это не помешало LISP остаться наиболее популярным языком для решения таких задач. На протяжении почти сорокалетней истории его существования появился ряд диалектов этого языка: Common LISP, Mac LISP, InterLISP, Standard LISP и др. Различия между ними не носят принципиального характера и в основном сводятся к несколько отличающемуся набору встроенных функций и некоторой разнице в форме записи программ. Поэтому, программист, научившийся работать на одном из них, без труда сможет освоить и любой другой.

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

    1.  Язык программирования Лисп

    1.1 Основные функции языка LISP

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

    Списки языка Лисп имеют рекурсивную структуру: элементом списка может быть произвольное S-выражение - как атом, так и список, например: (1() (a b (c)) class). Некоторые S-выражения можно вычислять, получая в результате значения (тоже S-выражения); такие выражения называются формами.

    Формой может быть переменная, т.е. атом-идентификатор, которому было присвоено значение одной из функций Лиспа (значением такой формы является текущее значение переменной). Формой является также список-обращение к функции вида(f a1, a2 ... an), где f - имя функции, а ai - ее аргументы (n?0). Программа на Лиспе представляет собой последовательность таких форм, и ее выполнение заключается в их вычислении.

    В большинстве версий языка Лисп имеется много встроенных (стандартных) функций, на основе которых составляется программа. Все они есть в наиболее известных версиях Лиспа, таких как Common Lisp и MuLisp.

    Для определения новых функций используется встроенная функция defun, к которой возможны следующие (равноценные) обращения: (defun f (lambda (v1 v2 ... vn) e)) или (defun f (v1 v2 ... vn) e).

    Вычисление функции defun в качестве побочного эффекта приводит к появлению в программе новой функции с именем f ; vi - формальные параметры новой функции (n?0), а e - форма, зависящая от vi. Таким образом, определяется обычная ЛИСП-функция, т.е. функция с фиксированным количеством аргументов, которые всегда вычисляются при обращении к ней.

    При последующем обращении к этой уже определенной функции (f a1 a2 ... an) сначала вычисляются аргументы (фактические параметры) ai, затем вводятся локальные переменные vi, которым присваиваются значения соответствующих аргументов ai, и далее вычисляется форма e при этих значениях переменных vi, после чего эти переменные уничтожаются. Значением данной формы становится значение функции f при аргументах ai.

    Операции над списками (car l) - значением аргумента l должен быть непустой список, тогда значением функции является первый элемент (верхнего уровня) этого списка (cdr l) и значением функции является "хвост" этого списка, т.е. список, полученный отбрасыванием первого элемента.

    Кроме этих двух функций-селекторов элементов списка часто используются функции, являющиеся их суперпозициями. Имена всех таких функций начинаются на букву c, а заканчиваются на букву r, между ними же может стоять произвольная комбинация из не более чем 5 букв a и d, например, (cadar l)?(car(cdr(car l))) .

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

    (nth n l) - значением аргумента n должно быть положительное целое  число (обозначим его N), а значением  аргумента l - список. Значением функции  является N-й от начала элемент  этого списка.

    (last l) - функция выбирает  последний (от начала) элемент списка, являющегося значением ее аргумента. программирование диалект язык лисп

    (cons e l) - в отличие от  предыдущих функций эта функция  является конструктором, т.е. строит  новый список, который и выдает  в качестве своего результата. Первым элементом этого списка  будет значение аргумента e, а хвостом списка - значение аргумента l . Например, (append l1 l2)

    Эта функция осуществляет слияние (конкатенацию) двух списков, являющихся значением двух ее аргументов.

    (list e1 e2 ... en ) - еще одна  функция конструктор, она имеет произвольное количество аргументов, из их значений она строит список (количество элементов результирующего списка равно количеству аргументов).

    1.2 Арифметические функции

    (add1 n) - значением аргумента  этой функции должно быть число, функция прибавляет к этому числу 1 и выдает результат в качестве своего значения.

    (sub1 n) - значением аргумента  должно быть число, функция вычитает  из него 1 и выдает результат  в качестве своего значения.

    (+ n1 n2) - значениями обоих  аргументов функции должны быть  числа, результат вычисления функции - их сумма.

    (- n1 n2) - значениями аргументов  должны быть числа, значение функции - их разность.

    (length l) - значением аргумента l должен быть список, значением  функции является количество  элементов (верхнего уровня) этого  списка, например:

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

    (rem n1 n2) - значениями аргументов  функции должны быть целые числа, результат вычисления функции - остаток от деления первого числа на второе.

    1.3 Логические функции

    Предикатом обычно называется форма, значение которой рассматривается как логическое значение "истина" или "ложь". Особенностью языка Лисп является то, что "ложью" считается пустой список, записываемый как () или nil, а "истиной" - любое другое выражение (часто в этой роли выступает атом T).

    (null e) - эта функция проверяет, является ли значение ее аргумента  пустым списком: если да, то значение  функции равно T, иначе - ().

    (eq e1 e2) - функция сравнивает  значения своих аргументов, которые  должны быть атомами-идентификаторами. В случае их совпадения (идентичности) значение функции равно T, иначе - ().

    (eql e1 e2) - в отличие от  предыдущей функции eql сравнивает  значения своих аргументов, которыми  могут быть не только атомы-идентификаторы, но и атомы-числа. Если они равны, то значение функции равно T, иначе - ().

    (equal e1 e2) - пункция производит  сравнение двух произвольных S-выражений - значений своих аргументов. Если  они равны (имеют одинаковую структуру  и состоят из одинаковых атомов), то значение функции равно T, иначе - ().

    (neq e1 e2) - аналог, но значения  аргументов сравниваются на "не  равно".

    Функция (member a l) производит поиск атома, являющегося значением первого ее аргумента, в списке (на верхнем его уровне), являющемся вторым аргументом. В случае успеха поиска значение функции равно T, иначе - ().

    Значениями аргументов функции (gt n1 n2) или (> n1 n2) должны быть числа. Если первое из них больше второго, то значение функции равно T, иначе - ().

    (lt n1 n2) или (< n1 n2) - аналог, но  числа сравниваются на "меньше".

    Логическими функциями называются три функции, реализующие основные логические операции .

    Функция (not e), реализующая "отрицание", является дубликатом функции null: если значение аргумента равно () ("ложь"), то функция выдает результат T ("истина"), а при любом другом значении аргумента выдает результат ().

    (and e1 e2 ... ek) (k?1) - конъюнкция. Функция по очереди вычисляет  свои аргументы. Если значение  очередного из них равно () ("ложь"), то функция, не вычисляя оставшиеся  аргументы, заканчивает свою работу со значением (), а иначе переходит к вычислению следующего аргумента. Если функция дошла до вычисления последнего аргумента, то с его значением она и заканчивает свою работу.

    (or e1 e2 ... ek) (k?1) - дизъюнкция. Функция  по очереди вычисляет свои аргументы. Если значение очередного из них не равно () ("ложь"), то функция, не вычисляя оставшиеся аргументы, заканчивает свою работу со значением этого аргумента, в противном случае она переходит к вычислению следующего аргумента. Если функция дошла до вычисления последнего аргумента, то с его значением она и заканчивает свою работу.

    1.4 Специальные функции

    Функция блокировки вычислений (quote e) или 'e, выдает в качестве значения свой аргумент, не вычисляя его.

    Функция (gensym) генерации уникальных атомов, при каждом обращении к ней вычисляет (образует) новый атом-идентификатор. Этот идентификатор получается склеиванием специального префикса и очередного целого числа. Префикс и целое число, от которого начинается нумерация генерируемых атомов, могут быть установлены заранее, как например, в языке MuLisp: (setq *gensym-prefix* 'S) (setq *gensym-count* 2).

    После этого функция gensym будет последовательно выдавать атомы S2, S3, S4, ... .

    (prog (v1 v2 ... vn) e1 e2 ... ek) (n?0, k?1) - Блочная  и связанные с ней функции. Эту функцию называют "блочной", поскольку ее вычисление напоминает выполнение блоков в других языках программирования.

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

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

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

    (setq v e) - аналог оператора  присваивания. В качестве аргумента v должно быть задано имя переменной, существующей в данный момент. Функция присваивает этой переменной новое значение - значение аргумента е. Это же значение является значением и самой функции setq, хотя оно, как правило, не используется.

    В функции (pop v1 v2) обоими аргументами должны быть имена переменных, существующих в данный момент, причем переменная v2 должна иметь значение и им должен быть непустой список.

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

    В качестве второго аргумента функции (push е v) должно быть задано имя переменной, в качестве первого - произвольная форма. Функция вычисляет эту форму и строит новый список, первый элемент которого - вычисленное значение, а хвост - список, являющийся значением переменной v. Результирующий список присваивается в качестве нового значения переменной v (он также является значением самой функции push).

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

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

    2. Особенности языка Лисп

    От других языков программирования Лисп отличается следующими свойствами:

    1. одинаковая форма данных  и программ;

    2. хранение данных, не  зависящее от места;

    3. автоматическое и динамическое  управление памятью;

    4. функциональная направленность;

    5. Лисп является бестиповым  языком;

    6. интерпретирующий и  компилирующий режимы работы;

    7. пошаговое программирование;

    8. единый системный и  прикладной язык программирования.

    Рассмотрим эти свойства более подробно.

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

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

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

    При автоматическом и динамическом управлении памятью, который применен в Лиспе, пользователь не должен заботиться об учете памяти. Система резервирует и освобождает память автоматически в соответствии с потребностью. Когда память кончается, запускается специальный мусорщик. Мусорщик перебирает все ячейки и собирает являющиеся мусором ячейки в список свободной памяти для того, чтобы их можно было использовать заново. Среда Лиспа постоянно содержится в порядке. В современных ЛИСП-системах выполнение операции сборки мусора занимает от одной до нескольких секунд. В задачах большого объема сборщик мусора запускается весьма часто, что резко ухудшает временные характеристики прикладных программ. Во многих системах мусор не образуется, поскольку он сразу же учитывается. Управление памятью просто и не зависит от физического расположения, поскольку свободная память логически состоит из цепочки списочных ячеек.

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

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

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

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

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

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

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

    Лисп является одновременно как языком прикладного так и системного программирования. Он напоминает машинный язык тем, что как данные, так и программы представлены в одинаковой форме. Язык превосходно подходит для написания интерпретаторов и трансляторов как для него самого, так и для других языков. Наиболее короткий интерпретатор Пролога, написанный на Лиспе занимает несколько десятков строк.

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

     

    Заключение

    Современные диалекты языка LISP можно рассматривать как мощные интерактивные системы программирования. Это объясняется двумя причинами. Во-первых, сам язык LISP претерпевает серьезные изменения - развиваются средства языка, предназначенные для обработки нетрадиционных для LISP типов данных: массивов, векторов, матриц; появляются некоторые средства управления памятью (пакеты), отсутствующие в LISP. Серьезные изменения претерпевают и управляющие структуры. Появились несвойственные природе языка LISP функции, заимствованные из Фортрана, Алгола, Паскаля, Си: Do, Loop, Goto , Case и прочие, позволяющие пользователю, незнакомому с принципами функциональных языков, легко переходить на LISP. Качество программ снижается, зато возрастает популярность языка. Во-вторых, если на первом этапе развития LISP -системам была присуща небольшая скорость обработки данных и серьезные ограничения на емкость используемой оперативной памяти, то современные Лисп-системы уже могут соперничать по этим параметрам с такими языками, как Си, Паскаль и др. Использование LISP - машин вообще практически снимает ограничения памяти и быстродействия.

    Для ПЭВМ ограничения по памяти и быстродействию все еще остаются существенными. Однако положение не безнадежно. Развитие LISP - систем для ПЭВМ идет сегодня по трем различным направлениям. Первое связано с увеличением емкости памяти, которая может использоваться LISP - системой. С этой целью ряд компаний разработал версии языка Golden Common Lisp, использующие расширения оперативной памяти и виртуальную память. Второе направление связанно с повышением быстродействия LISP - систем. Третье направление состоит в разработке эффективных компиляторов программ с языка LISP в традиционные языки (чаще всего в язык Си).

    Положительным нововведением в современные диалекты языка можно считать псевдоассемблерные команды, которые позволяют оперировать основными регистрами машины и организовывать прерывания на уровне DOS и BIOS. Кроме того, многие LISP - системы имеют хорошие интерфейсы с другими языками (Фортран, Паскаль, Ассемблер, Си), что позволяет повысить эффективность прикладных LISP - программ.

    Если же говорить о глобальной тенденции развития самой идеологии языка LISP, то очевидно, что она связана с созданием объектно - ориентированных версий языка как наиболее пригодных для реализации систем ИИ.

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

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

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

    Список литературы

    1. "Программирование на  языке ЛИСП в системе muLISP-90". Байдун В.В., Кружилов С.И., Сергиевский  А.Е, Чернов П.Л. - М.: Моск. энеpг. ин-т, 1993. - 40 С. [Текст]

    2. "Функциональное программирование". Хендерсон П.: Пер. с англ.-М.: Мир, 2003. - 637 С. [Текст]

    3. "Мир Лиспа". Хювёнен  Э., Сеппянен Й. В 2-х т. / Пер. с финск.. -- М.: Мир, 2000. -- ISBN 5-03-001935-9 [Текст]

    4. Русскоязычное сообщество  лисперов [Электронный ресурс]. Режим  доступа: http://lisp.ru/

    5. Начальные сведения  о языках Лисп-семейства на  русском [Электронный ресурс]. Режим  доступа: lisp.narod.ru

    6. Русский перевод книги Practical Common Lisp(англ.) [Электронный ресурс]. Режим доступа: pcl.catap.ru/doku.php

    7. "Язык программирования XLISP". Тужилов И. В. Учеб. пособие. - Пенза: Изд-во Пенз. гос. техн. ун-та, 2004. - 126 С.[Текст]

    8. Личный сайт Дж. Маккарти  с текстами его публикаций [Электронный  ресурс]. Режим доступа: http://www-formal.stanford.edu/jmc/

    9. "Введение в программирование  на языке Лисп" Городняя Л.В.: Учебное пособие для начинающих. - Новосибирск: НГУ, 2005. - 93 с.

    10. Энциклопедия языков  программирования. [Электронный ресурс]. Режим доступа: http://progopedia.ru/language/lisp/


    написать администратору сайта