Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску

Лисп ароматизированное Erlang ( LFE ) является функциональным , одновременно , сбор мусора , универсальный язык программирования и Lisp диалект построен на ядре Erlang и виртуальной машины Erlang ( ЛУЧ ). LFE основан на Erlang, чтобы предоставить синтаксис Lisp для написания распределенных, отказоустойчивых , непрерывных приложений , работающих в режиме мягкого реального времени . LFE также расширяет Erlang для поддержки метапрограммирования с помощью макросов Lisp и улучшенного взаимодействия с разработчиками с помощью многофункционального цикла чтения-оценки-печати (REPL). [1]LFE активно поддерживается во всех последних выпусках Erlang; Самая старая поддерживаемая версия Erlang - R14.

История [ править ]

Первый выпуск [ править ]

Первоначальная работа над LFE началась в 2007 году, когда Роберт Вирдинг начал создавать прототип Lisp, работающий на Erlang. [2] Эта работа была сосредоточена в первую очередь на синтаксическом анализе и изучении того, как может выглядеть реализация. В то время система контроля версий не использовалась, поэтому отслеживать точные начальные даты несколько проблематично. [2]

Вирдинг объявил о первом выпуске LFE в списке рассылки Erlang Questions в марте 2008 года. [3] Этот выпуск LFE был очень ограниченным: он не обрабатывал рекурсивные letrecs, binarys receive, или try; он также не поддерживает оболочку Lisp. [4]

Первоначальная разработка LFE была выполнена с помощью Erlang [5] версии R12B-0 на ноутбуке Dell XPS. [4]

Мотивы [ править ]

Роберт Вирдинг заявил, что он основал язык программирования LFE по нескольким причинам: [2]

  • У него был предыдущий опыт программирования на Лиспе.
  • Учитывая его предыдущий опыт, он был заинтересован в реализации своего собственного Лиспа.
  • В частности, он хотел реализовать Lisp на Erlang: ему не только было любопытно посмотреть, как он будет работать и интегрироваться с Erlang, он хотел увидеть, как это будет выглядеть .
  • С момента оказания помощи в создании языка программирования Erlang у него была цель создать Lisp, который был специально разработан для работы в BEAM и мог полностью взаимодействовать с Erlang / OTP.
  • Он хотел поэкспериментировать с компиляцией другого языка на Erlang. Таким образом, он рассматривал LFE как средство для изучения этого, создав Core Erlang и вставив его в бэкэнд компилятора Erlang.

Особенности [ править ]

  • Виртуальная машина Erlang с языковым таргетингом (BEAM)
  • Полная интеграция с Erlang : вызовы функций Erlang без штрафных санкций (и наоборот)
  • Метапрограммирование с помощью макросов Лиспа и гомоиконность Лиспа
  • Документация в стиле Common Lisp через комментарии к исходному коду и строки документации
  • Параллельное программирование архитектуры без общего доступа через передачу сообщений ( модель акторов )
  • Акцент на рекурсию и высшие порядки функций вместо побочного эффекта основанного зацикливание
  • Полный цикл чтения-оценки-печати (REPL) для интерактивной разработки и тестирования (в отличие от оболочки Erlang, LFE REPL поддерживает определения функций и макросов)
  • Сопоставление с образцом
  • Горячая загрузка кода
  • Лисп-2 разделение пространств имен для переменных и функций
  • Взаимодействие с Java через JInterface и Erjang
  • Возможность написания сценариев с обоими lfeиlfescript

Синтаксис и семантика [ править ]

Символьные выражения (S-выражения) [ править ]

Как и Лисп, LFE - это язык, ориентированный на выражения . В отличии от не- homoiconic языков программирования, лепечет не делают или мало синтаксических различий между выражениями и заявлениями : весь код и данные записываются в виде выражений. LFE привнесла гомиконность в Erlang VM.

Списки [ править ]

В LFE тип данных списка записывается с элементами, разделенными пробелами и заключенными в круглые скобки. Например, это список, элементами которого являются целые числа и , а также атом . Эти значения неявно типизированы: они представляют собой соответственно два целых числа и специфичный для Лиспа тип данных, называемый символическим атомом , и их не нужно объявлять как таковые.(list 1 2 'foo)12foo

Как видно из приведенного выше примера, выражения LFE записываются в виде списков с использованием префиксной нотации . Первый элемент в списке - это имя формы , т. Е. Функции, оператора или макроса. Остальная часть списка - аргументы.

Операторы [ править ]

Аналогичным образом используются операторы LFE-Erlang. Выражение

 ( *  ( +  1  2  3  4  5  6 )  2 )

принимает значение 42. В отличие от функций в Erlang и LFE, арифметические операторы в Lisp являются вариативными (или n-мерными ), способными принимать любое количество аргументов.

Лямбда-выражения и определение функции [ править ]

LFE , как и Common Lisp, имеет лямбда . Однако он также имеет лямбда-сопоставление для учета возможностей сопоставления шаблонов Erlang при вызове анонимных функций.

Идиомы Erlang в LFE [ править ]

Этот раздел не представляет собой полного сравнения Erlang и LFE, но должен дать представление.

Сопоставление с образцом [ править ]

Эрланг:

 1 >  { Len , Status , Msg }  =  { 8 , ok , "Trillian" }.  { 8 , хорошо , "Триллиан" }  2 >  Msg .  "Триллиан"

LFE:

 >  ( set  ( tuple  len  status  msg )  # ( 8  ok  "Trillian" ))  # ( 8  ok  "Trillian" )  >  msg  "Trillian"

Составьте список [ править ]

Эрланг:

 1 >  [ trunc ( math : pow ( 3 , X ))  ||  X  <-  [ 0 , 1 , 2 , 3 ]].  [ 1 , 3 , 9 , 27 ]

LFE:

 >  ( list-comp  (( <-  x  ' ( 0  1  2  3 )))  ( trunc  ( math: pow  3  x )))  ( 1  3  9  27 )

Или идиоматический функциональный стиль:

 >  ( списки: map  ( lambda  ( x )  ( trunc  ( math: pow  3  x )))  ' ( 0  1  2  3 ))  ( 1  3  9  27 )

Охранники [ править ]

Эрланг:

 right_number ( X ),  когда  X  ==  42 ;  X  ==  276709  ->  верно ;  right_number (_)  ->  ложь .

LFE:

 ( defun  right-number?  (( x )  ( when  ( orelse  ( ==  x  42 )  ( ==  x  276709 )))  'истина )  (( _ )  ' ложь ))

в заголовках функций [ править ]

Эрланг:

 сумма ( L )  ->  сумма ( L , 0 ).  сумма ([],  Итого )  ->  Итого ;  sum ([ H | T ],  Total )  ->  sum ( T ,  H + Total ).

LFE:

 ( defun  sum  ( l )  ( sum  l  0 ))  ( defun  sum  (( ' ()  total )  total )  ((( cons  h  t )  total )  ( sum  t  ( +  h  total ))))

или используя литерал cons вместо формы конструктора:

 ( defun  sum  ( l )  ( sum  l  0 ))  ( defun  sum  (( ' ()  total )  total )  (( ` ( , h  .  , t )  total )  ( sum  t  ( +  h  total )))))

Соответствующие записи в заголовках функций [ править ]

Эрланг:

handle_info ( ping ,  #state  { remote_pid  =  undefined }  =  State )  ->  gen_server : cast ( self (),  ping ),  { noreply ,  State }; handle_info ( ping ,  State )  ->  { noreply ,  State };

LFE:

( defun  handle_info  (( 'ping  ( =  ( match-state  remote-pid  ' undefined )  state ))  ( gen_server: cast  ( self )  'ping )  `# ( noreply  , state ))  (( ' ping  state )  ` # ( noreply  , состояние )))

Получение сообщений [ править ]

Эрланг:

 universal_server ()  ->  получить  { стать ,  Func }  ->  Func ()  end .

LFE:

 ( DEFUN  универсальный-сервер  ()  ( получить  (( кортеж  «стать  Func )  ( FUNCALL  Func ))))

или же:

 ( defun  universal-server  ()  ( receive  ( `# ( стать  , func )  ( funcall  func ))))

Примеры [ править ]

Совместимость с Erlang [ править ]

Вызов функций Erlang принимает форму (<модуль>: <функция> <аргумент1> ... <аргумент>) :

( io: формат  «Hello, World!» )

Функциональная парадигма [ править ]

Использование рекурсии для определения функции Аккермана :

( defun  ackermann  (( 0  n )  ( +  n  1 ))  (( m  0 )  ( ackermann  ( -  m  1 )  1 ))  (( m  n )  ( ackermann  ( -  m  1 )  ( ackermann  m  ( -  n  1 )) )))

Составные функции:

( defun  compose  ( f  g )  ( lambda  ( x )  ( funcall  f  ( funcall  g  x ))))( defun  check  ()  ( let *  (( sin-asin  ( compose  # ' sin / 1  #' asin / 1 ))  ( ожидается  ( sin  ( asin  0.5 )))  ( compose-result  ( funcall  sin-asin  0.5 )))  ( io: формат  «Ожидаемый ответ: ~ p ~ n»  ( ожидаемый список  )) ( io: формат «Ответ с составлением: ~ p ~ n» ( список -результат составления ))))    

Параллелизм [ править ]

Передача сообщений с помощью легких «процессов» Erlang:

( defmodule  messenger-back  ( экспорт  ( результат печати  0 )  ( отправка сообщения  2 )))( defun  print-result  ()  ( receive  (( tuple  pid  msg )  ( io: format  "Полученное сообщение: '~ s' ~ n"  ( list  msg ))  ( io: format  "Отправка сообщения для обработки ~ p ... ~ n "  ( идентификатор списка  )) ( ! pid ( сообщение кортежа )) ( результат печати ))))     ( defun  send-message  ( вызывающий-pid  msg )  ( let  (( spawned-pid  ( spawn  'messenger-back  ' print-result  ())))  ( !  spawned-pid  ( кортеж,  вызывающий-pid  msg ))))

Несколько одновременных HTTP-запросов:

( defun  parse-args  ( flag )  «Учитывая один или несколько аргументов командной строки, извлеките переданные значения. Например, если через командную строку было передано следующее: $ erl -my-flag мое-значение-1 -my-flag мое-значение-2 Затем его можно было извлечь в программе LFE, вызвав эту функцию: (let ((args (parse-args 'my-flag)))  ...  )  В этом примере значение, присвоенное переменной arg, будет списком,  содержащим значения my-value-1 и my-value-2. "  ( let  (( ` # ( ok  , data )  ( init: get_argument  flag )))  ( списки: объединить  данные )))( defun  get-pages  ()  «Без аргумента, предположим, что 'параметр url был передан через командную строку.»  ( let  (( urls  ( parse-args  ' url )))  ( URL get-pages  )))( defun  get-pages  ( urls )  «Запустить inets и сделать (потенциально много) HTTP-запросов.»  ( inets: start )  ( plists: map  ( lambda  ( x )  ( get-page  x ))  urls ))( defun  get-page  ( url )  «Сделать один HTTP-запрос.»  ( let *  (( method  'get )  ( headers  ' ())  ( request-data  `# (, url  , headers ))  ( http-options  () )  ( параметры-запроса  ' ( # ( синхронизация  ложь ))))  ( httpc:  метод  запроса данные  -  запросы http-параметры-параметры- запроса )  ( получить  ( `# ( http  # (,идентификатор-запроса  # ( ошибка  , причина )))  ( io: format  "Ошибка: ~ p ~ n"  ` ( , причина )))  ( ` # ( http  # (, идентификатор-запроса  , результат ))  ( io: формат  " Результат: ~ p ~ n "  ` ( , результат ))))))

Ссылки [ править ]

  1. ^ Вирдинг, Роберт. "Эрланг, приправленный Лиспом" (PDF) . Фабрика Эрланг . Проверено 17 января 2014 .
  2. ^ a b c "История LFE в списке рассылки Erlang, приправленного Lisp" . Проверено 28 мая 2014 .
  3. ^ "Объявление LFE в списке рассылки вопросов Erlang" . Проверено 17 января 2014 .
  4. ^ а б Армстронг, Джо; Вирдинг, Роберт (30 декабря 2013). «Оборудование, используемое при разработке Erlang и LFE» (обмен электронной почтой). Беседовал Дункан МакГреггор . Проверено 17 января 2014 .
  5. ^ "Продолжение объявления LFE в списке рассылки вопросов Erlang" . Проверено 17 января 2014 .

Внешние ссылки [ править ]

  • Официальный веб-сайт
  • LFE на GitHub
  • LFE Быстрый старт
  • Руководство пользователя LFE
  • LFE по Rosetta Code