LFE (язык программирования)
![]() | |
Парадигма | Мультипарадигмальность : параллельная , функциональная |
---|---|
Семья | Эрланг , Лисп |
Разработано | Роберт Вирдинг |
Разработчик | Роберт Вирдинг |
Впервые появился | 2008 год |
Стабильная версия | 2.1.1
/ 6 января 2023 г |
Дисциплина набора текста | динамичный , сильный |
Язык реализации | Эрланг |
ТЫ | Кросс-платформенный |
Лицензия | Апач 2.0 |
Расширения имен файлов | .lfe .hrl |
Веб-сайт | жизнь |
Под влиянием | |
Эрланг , Common Lisp , Maclisp , Scheme , Elixir , Clojure , Hy | |
Под влиянием | |
Джокса, одновременно интриган |
Lisp Flavored Erlang ( LFE ) — функциональный , параллельный , со сборкой мусора общего назначения , язык программирования и Lisp, диалект построенный на Core Erlang и виртуальной машине Erlang ( BEAM ). LFE основан на Erlang и обеспечивает синтаксис Lisp для написания распределенных, отказоустойчивых , программных реального времени , непрерывных приложений . LFE также расширяет Erlang для поддержки метапрограммирования с помощью макросов Lisp и улучшенного опыта разработки с помощью многофункционального цикла чтения-оценки-печати (REPL). [1] LFE активно поддерживается во всех последних выпусках Erlang; самая старая поддерживаемая версия Erlang — R14.
История [ править ]

Первоначальный выпуск [ править ]
Первоначальная работа над LFE началась в 2007 году, когда Роберт Вирдинг начал создавать прототип Lisp, работающий на Erlang. [2] Эта работа была сосредоточена в первую очередь на анализе и изучении того, как может выглядеть реализация. В то время не использовалась никакая система контроля версий, поэтому отслеживать точные начальные даты довольно проблематично. [2]
Вирдинг объявил о первом выпуске LFE в списке рассылки Erlang Questions в марте 2008 года. [3] Эта версия LFE была очень ограниченной: она не поддерживала рекурсивные операции. letrec
с, binary
с, receive
, или try
; он также не поддерживал оболочку Lisp. [4]
Первоначальная разработка LFE была выполнена с использованием версии R12B-0 Erlang. [5] на ноутбуке Dell XPS. [4]
1958 | 1960 | 1965 | 1970 | 1975 | 1980 | 1985 | 1990 | 1995 | 2000 | 2005 | 2010 | 2015 | 2020 | ||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ЛИСП 1, 1.5, ЛИСП 2 (заброшенный) | |||||||||||||||
Маклисп | |||||||||||||||
Интерлисп | |||||||||||||||
леев | |||||||||||||||
Лисп-машина Лисп | |||||||||||||||
Схема | Р5РС | Р6РС | R7RS маленький | ||||||||||||
НОЛЬ | |||||||||||||||
ЗИЛ (язык реализации Zork) | |||||||||||||||
Франц Лисп | |||||||||||||||
Общий Лисп | стандарт ANSI | ||||||||||||||
Лисп | |||||||||||||||
Схема СО | |||||||||||||||
XLISP | |||||||||||||||
Т | |||||||||||||||
На схеме | |||||||||||||||
Эмакс Лисп | |||||||||||||||
АвтоЛИСП | |||||||||||||||
ПикоЛисп | |||||||||||||||
Гамбит | |||||||||||||||
EuLisp | |||||||||||||||
ИСЛИСП | |||||||||||||||
ОпенЛисп | |||||||||||||||
Схема PLT | Ракетка | ||||||||||||||
новыйLISP | |||||||||||||||
GNU Коварство | |||||||||||||||
Визуальный ЛИСП | |||||||||||||||
Кложур | |||||||||||||||
Дуга | |||||||||||||||
ЛФЭ | |||||||||||||||
Он | |||||||||||||||
Хиалисп |
Мотивы [ править ]
Роберт Вирдинг заявил, что было несколько причин, по которым он начал использовать язык программирования LFE: [2]
- Ранее у него был опыт программирования на Lisp.
- Учитывая его предыдущий опыт, он был заинтересован в реализации своего собственного Lisp.
- В частности, он хотел реализовать Lisp на Erlang: ему было не только любопытно посмотреть, как он будет работать и интегрироваться с Erlang, но и посмотреть, как он будет выглядеть .
- Со времени участия в создании языка программирования Erlang у него была цель создать Lisp, специально разработанный для работы на BEAM и способный полностью взаимодействовать с Erlang/OTP.
- Он хотел поэкспериментировать с компиляцией другого языка на Erlang. Таким образом, он рассматривал LFE как средство для изучения этой проблемы путем создания Core Erlang и подключения его к серверной части компилятора Erlang.
Особенности [ править ]
- Язык, ориентированный на виртуальную машину Erlang (BEAM).
- Бесшовная интеграция Erlang : вызовы функций Erlang без штрафов (и наоборот)
- Метапрограммирование с помощью макросов Lisp и гомоиконичность Lisp
- Документация в стиле Common Lisp через комментарии к исходному коду и строки документации.
- Параллельное программирование в архитектуре без разделяемого доступа посредством передачи сообщений ( модель актера )
- Акцент на рекурсии и функциях высшего порядка вместо побочных эффектов. на основе циклов
- Полный цикл чтения-оценки-печати (REPL) для интерактивной разработки и тестирования (в отличие от оболочки Erlang, LFE REPL поддерживает определения функций и макросов).
- Сопоставление с образцом
- Горячая загрузка кода
- Разделение пространств имен в Lisp -2 для переменных и функций.
- Java через JInterface и Erjang Взаимодействие
- Способности к написанию сценариев с обоими
lfe
иlfescript
Синтаксис и семантика [ править ]
Символические выражения (S-выражения) [ править ]
Как и Лисп, LFE — это язык, ориентированный на выражения . В отличие от негомоиконных языков программирования, Лисп не делает или делает небольшое синтаксическое различие между выражениями и операторами : весь код и данные записываются как выражения. LFE привнес гомоконичность в виртуальную машину Erlang.
Списки [ править ]
В LFE тип данных списка записывается так, что его элементы разделяются пробелами и заключаются в круглые скобки. Например, (list 1 2 'foo)
это список, элементами которого являются целые числа 1
и 2
, а атом [[foo| foo
]]. Эти значения неявно типизированы: они представляют собой соответственно два целых числа и тип данных, специфичный для Lisp, называемый символическим атомом , и их не нужно объявлять как таковые.
Как видно из примера выше, выражения LFE записываются в виде списков с использованием префиксной записи . Первый элемент в списке — это имя формы , т. е. функции, оператора или макроса. Остальная часть списка — это аргументы.
Операторы [ править ]
Операторы LFE-Erlang используются таким же образом. Выражение
(* (+ 1 2 3 4 5 6) 2)
оценивается как 42. В отличие от функций в Erlang и LFE, арифметические операторы в Lisp являются вариативными (или n-арными ) и могут принимать любое количество аргументов.
Лямбда-выражения и определение функции [ править ]
В LFE есть лямбда , как и в Common Lisp. Однако он также имеет лямбда-соответствие для учета возможностей Эрланга по сопоставлению с образцом при анонимных вызовах функций.
Идиомы Эрланга в LFE [ править ]
Этот раздел не представляет собой полное сравнение Erlang и LFE, но должен дать представление.
Сопоставление с образцом [ править ]
Эрланг:
1> {Len,Status,Msg} = {8,ok,"Trillian"}.
{8,ok,"Trillian"}
2> Msg.
"Trillian"
ЛФЭ:
lfe> (set (tuple len status msg) #(8 ok "Trillian"))
lfe> ;; or with LFE literal tuple syntax:
lfe> (set `#(,len ,status ,msg) #(8 ok "Trillian"))
#(8 ok "Trillian")
lfe> 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)
Или идиоматический функциональный стиль:
lfe> (lists:map
(lambda (x) (trunc (math:pow 3 x)))
'(0 1 2 3))
(1 3 9 27)
Охранники [ править ]
Эрланг:
right_number(X) when X == 42; X == 276709 ->
true;
right_number(_) ->
false.
ЛФЭ:
(defun right-number?
((x) (when (orelse (== x 42) (== x 276709)))
'true)
((_) 'false))
минусы в заголовках функций [ править ]
Эрланг:
sum(L) -> sum(L,0).
sum([], Total) -> Total;
sum([H|T], Total) -> sum(T, H+Total).
ЛФЭ:
(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};
ЛФЭ:
(defun handle_info
(('ping (= (match-state remote-pid 'undefined) state))
(gen_server:cast (self) 'ping)
`#(noreply ,state))
(('ping state)
`#(noreply ,state)))
Получение сообщений [ править ]
Эрланг:
universal_server() ->
receive
{become, Func} ->
Func()
end.
ЛФЭ:
(defun universal-server ()
(receive
((tuple 'become func)
(funcall func))))
или:
(defun universal-server ()
(receive
(`#(become ,func)
(funcall func))))
Примеры [ править ]
Совместимость с Erlang [ править ]
Вызовы функций Erlang принимают форму (<модуль>:<функция> <arg1> ... <argn>) :
(io:format "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))
(expected (sin (asin 0.5)))
(compose-result (funcall sin-asin 0.5)))
(io:format "Expected answer: ~p~n" (list expected))
(io:format "Answer with compose: ~p~n" (list compose-result))))
Параллельность [ править ]
Передача сообщений с помощью легких «процессов» Эрланга:
(defmodule messenger-back
(export (print-result 0) (send-message 2)))
(defun print-result ()
(receive
((tuple pid msg)
(io:format "Received message: '~s'~n" (list msg))
(io:format "Sending message to process ~p ...~n" (list pid))
(! pid (tuple msg))
(print-result))))
(defun send-message (calling-pid msg)
(let ((spawned-pid (spawn 'messenger-back 'print-result ())))
(! spawned-pid (tuple calling-pid msg))))
Несколько одновременных HTTP-запросов:
(defun parse-args (flag)
"Given one or more command-line arguments, extract the passed values.
For example, if the following was passed via the command line:
$ erl -my-flag my-value-1 -my-flag my-value-2
One could then extract it in an LFE program by calling this function:
(let ((args (parse-args 'my-flag)))
...
)
In this example, the value assigned to the arg variable would be a list
containing the values my-value-1 and my-value-2."
(let ((`#(ok ,data) (init:get_argument flag)))
(lists:merge data)))
(defun get-pages ()
"With no argument, assume 'url parameter was passed via command line."
(let ((urls (parse-args 'url)))
(get-pages urls)))
(defun get-pages (urls)
"Start inets and make (potentially many) HTTP requests."
(inets:start)
(plists:map
(lambda (x)
(get-page x)) urls))
(defun get-page (url)
"Make a single HTTP request."
(let* ((method 'get)
(headers '())
(request-data `#(,url ,headers))
(http-options ())
(request-options '(#(sync false))))
(httpc:request method request-data http-options request-options)
(receive
(`#(http #(,request-id #(error ,reason)))
(io:format "Error: ~p~n" `(,reason)))
(`#(http #(,request-id ,result))
(io:format "Result: ~p~n" `(,result))))))
Ссылки [ править ]
- ^ Видинг, Роберт. «Эрланг со вкусом Lisp» (PDF) . Фабрика Эрланг . Проверено 17 января 2014 г.
- ^ Jump up to: Перейти обратно: а б с «История LFE в списке рассылки Erlang со вкусом Lisp» . Проверено 28 мая 2014 г.
- ^ «Объявление LFE в списке рассылки вопросов по Erlang» . Проверено 17 января 2014 г.
- ^ Jump up to: Перейти обратно: а б Армстронг, Джо; Видинг, Роберт (30 декабря 2013 г.). «Аппаратное обеспечение, использованное при разработке Erlang и LFE» (обмен электронной почтой). Беседовал Дункан МакГрегор . Проверено 17 января 2014 г.
- ^ «Продолжение объявления LFE в списке рассылки вопросов по Erlang» . Проверено 17 января 2014 г.