LFE (programming Language)
   HOME

TheInfoList



OR:

Lisp Flavored Erlang (LFE) is a
functional Functional may refer to: * Movements in architecture: ** Functionalism (architecture) ** Form follows function * Functional group, combination of atoms within molecules * Medical conditions without currently visible organic basis: ** Functional sy ...
,
concurrent Concurrent means happening at the same time. Concurrency, concurrent, or concurrence may refer to: Law * Concurrence, in jurisprudence, the need to prove both ''actus reus'' and ''mens rea'' * Concurring opinion (also called a "concurrence"), a ...
,
garbage collected Garbage, trash, rubbish, or refuse is waste material that is discarded by humans, usually due to a perceived lack of utility. The term generally does not encompass bodily waste products, purely liquid or gaseous wastes, or toxic waste T ...
, general-purpose
programming language A programming language is a system of notation for writing computer programs. Most programming languages are text-based formal languages, but they may also be graphical. They are a kind of computer language. The description of a programming ...
and
Lisp A lisp is a speech impairment in which a person misarticulates sibilants (, , , , , , , ). These misarticulations often result in unclear speech. Types * A frontal lisp occurs when the tongue is placed anterior to the target. Interdental lisping ...
dialect The term dialect (from Latin , , from the Ancient Greek word , 'discourse', from , 'through' and , 'I speak') can refer to either of two distinctly different types of Linguistics, linguistic phenomena: One usage refers to a variety (linguisti ...
built on Core Erlang and the Erlang virtual machine (
BEAM Beam may refer to: Streams of particles or energy *Light beam, or beam of light, a directional projection of light energy **Laser beam *Particle beam, a stream of charged or neutral particles **Charged particle beam, a spatially localized grou ...
). LFE builds on Erlang to provide a Lisp syntax for writing distributed,
fault-tolerant Fault tolerance is the property that enables a system to continue operating properly in the event of the failure of one or more faults within some of its components. If its operating quality decreases at all, the decrease is proportional to the ...
, soft
real-time Real-time or real time describes various operations in computing or other processes that must guarantee response times within a specified time (deadline), usually a relatively short time. A real-time process is generally one that happens in defined ...
, non-stop applications. LFE also extends Erlang to support
metaprogramming Metaprogramming is a programming technique in which computer programs have the ability to treat other programs as their data. It means that a program can be designed to read, generate, analyze or transform other programs, and even modify itself ...
with Lisp macros and an improved developer experience with a feature-rich
read–eval–print loop A read–eval–print loop (REPL), also termed an interactive toplevel or language shell, is a simple interactive computer programming environment that takes single user inputs, executes them, and returns the result to the user; a program written ...
(REPL). LFE is actively supported on all recent releases of Erlang; the oldest version of Erlang supported is R14.


History


Initial release

Initial work on LFE began in 2007, when Robert Virding started creating a prototype of Lisp running on Erlang. This work was focused primarily on parsing and exploring what an implementation might look like. No version control system was being used at the time, so tracking exact initial dates is somewhat problematic. Virding announced the first release of LFE on the ''Erlang Questions'' mail list in March 2008. This release of LFE was very limited: it did not handle recursive letrecs, binarys, receive, or try; it also did not support a Lisp shell. Initial development of LFE was done with version R12B-0 of Erlang on a Dell XPS laptop.


Motives

Robert Virding has stated that there were several reasons why he started the LFE programming language: * He had prior experience programming in Lisp. * Given his prior experience, he was interested in implementing his own Lisp. * In particular, he wanted to implement a Lisp in Erlang: not only was he curious to see how it would run on and integrate with Erlang, he wanted to see what it would ''look'' like. * Since helping to create the Erlang programming language, he had had the goal of making a Lisp which was specifically designed to run on the BEAM and able to fully interact with Erlang/OTP. * He wanted to experiment with
compiling In computing, a compiler is a computer program that translates computer code written in one programming language (the ''source'' language) into another language (the ''target'' language). The name "compiler" is primarily used for programs that ...
another language on Erlang. As such, he saw LFE as a means to explore this by generating Core Erlang and plugging it into the backend of the Erlang compiler.


Features

* A language targeting Erlang virtual machine (BEAM) * Seamless Erlang integration: zero-penalty Erlang function calls (and vice versa) * Metaprogramming via
Lisp macro In computer programming, a macro (short for "macro instruction"; ) is a rule or pattern that specifies how a certain input should be mapped to a replacement output. Applying a macro to an input is known as macro expansion. The input and output ...
s and the
homoiconicity In computer programming, homoiconicity (from the Greek words ''homo-'' meaning "the same" and ''icon'' meaning "representation") is a property of some programming languages. A language is homoiconic if a program written in it can be manipulated as ...
of a Lisp *
Common Lisp Common Lisp (CL) is a dialect of the Lisp programming language, published in ANSI standard document ''ANSI INCITS 226-1994 (S20018)'' (formerly ''X3.226-1994 (R1999)''). The Common Lisp HyperSpec, a hyperlinked HTML version, has been derived fro ...
-style documentation via both source code comments and docstrings *
Shared-nothing architecture A shared-nothing architecture (SN) is a distributed computing architecture in which each update request is satisfied by a single node (processor/memory/storage unit) in a computer cluster. The intent is to eliminate contention among nodes. Nodes do ...
concurrent programming via message passing (
Actor model The actor model in computer science is a mathematical model of concurrent computation that treats ''actor'' as the universal primitive of concurrent computation. In response to a message it receives, an actor can: make local decisions, create more ...
) * Emphasis on
recursion Recursion (adjective: ''recursive'') occurs when a thing is defined in terms of itself or of its type. Recursion is used in a variety of disciplines ranging from linguistics to logic. The most common application of recursion is in mathematics ...
and
higher-order function In mathematics and computer science, a higher-order function (HOF) is a function that does at least one of the following: * takes one or more functions as arguments (i.e. a procedural parameter, which is a parameter of a procedure that is itself ...
s instead of
side-effect In medicine, a side effect is an effect, whether therapeutic or adverse, that is secondary to the one intended; although the term is predominantly employed to describe adverse effects, it can also apply to beneficial, but unintended, consequence ...
-based looping * A full
read–eval–print loop A read–eval–print loop (REPL), also termed an interactive toplevel or language shell, is a simple interactive computer programming environment that takes single user inputs, executes them, and returns the result to the user; a program written ...
(REPL) for interactive development and testing (unlike Erlang's shell, the LFE REPL supports function and macro definitions) *
Pattern matching In computer science, pattern matching is the act of checking a given sequence of tokens for the presence of the constituents of some pattern. In contrast to pattern recognition, the match usually has to be exact: "either it will or will not be ...
* Hot loading of code * A Lisp-2 separation of namespaces for variables and functions *
Java Java (; id, Jawa, ; jv, ꦗꦮ; su, ) is one of the Greater Sunda Islands in Indonesia. It is bordered by the Indian Ocean to the south and the Java Sea to the north. With a population of 151.6 million people, Java is the world's List ...
inter-operation via JInterface and Erjang * Scripting abilities with both lfe and lfescript


Syntax and semantics


Symbolic expressions (S-expressions)

Like Lisp, LFE is an
expression Expression may refer to: Linguistics * Expression (linguistics), a word, phrase, or sentence * Fixed expression, a form of words with a specific meaning * Idiom, a type of fixed expression * Metaphorical expression, a particular word, phrase, o ...
-oriented language. Unlike non-
homoiconic In computer programming, homoiconicity (from the Greek words ''homo-'' meaning "the same" and ''icon'' meaning "representation") is a property of some programming languages. A language is homoiconic if a program written in it can be manipulated as ...
programming languages, Lisps make no or little syntactic distinction between ''expressions'' and ''
statements Statement or statements may refer to: Common uses *Statement (computer science), the smallest standalone element of an imperative programming language *Statement (logic), declarative sentence that is either true or false *Statement, a declarative ...
'': all code and data are written as expressions. LFE brought homoiconicity to the Erlang VM.


Lists

In LFE, the list data type is written with its elements separated by whitespace, and surrounded by parentheses. For example, is a list whose elements are the integers and , and the atom . These values are implicitly typed: they are respectively two integers and a Lisp-specific data type called a ''symbolic atom'', and need not be declared as such. As seen in the example above, LFE expressions are written as lists, using
prefix notation Polish notation (PN), also known as normal Polish notation (NPN), Łukasiewicz notation, Warsaw notation, Polish prefix notation or simply prefix notation, is a mathematical notation in which operators ''precede'' their operands, in contrast t ...
. The first element in the list is the name of a ''form'', i.e., a function, operator, or macro. The remainder of the list are the arguments.


Operators

The LFE-Erlang operators are used in the same way. The expression (* (+ 1 2 3 4 5 6) 2) evaluates to 42. Unlike functions in Erlang and LFE, arithmetic operators in Lisp are
variadic In computer science, an operator or function is variadic if it can take a varying number of arguments; that is, if its arity is not fixed. For specific articles, see: * Variadic function * Variadic macro in the C preprocessor * Variadic template ...
(or ''n-ary''), able to take any number of arguments.


Lambda expressions and function definition

LFE has ''lambda'', just like Common Lisp. It also, however, has ''lambda-match'' to account for Erlang's pattern-matching abilities in anonymous function calls.


Erlang idioms in LFE

This section does not represent a complete comparison between Erlang and LFE, but should give a taste.


Pattern matching

Erlang: 1> = . 2> Msg. "Trillian" LFE: > (set (tuple len status msg) #(8 ok "Trillian")) #(8 ok "Trillian") > msg "Trillian"


List comprehensions

Erlang: 1> , X <- ,1,2,3. [1,3,9,27 LFE: > (list-comp ((<- x '(0 1 2 3))) (trunc (math:pow 3 x))) (1 3 9 27) Or idiomatic functional style: > (lists:map (lambda (x) (trunc (math:pow 3 x))) '(0 1 2 3)) (1 3 9 27)


Guards

Erlang: right_number(X) when X

42; X

276709 -> true; right_number(_) -> false.
LFE: (defun right-number? ((x) (when (orelse (

x 42) (

x 276709))) 'true) ((_) 'false))


cons'ing in function heads

Erlang: sum(L) -> sum(L,0). sum([], Total) -> Total; 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)))) or using a ``cons`` literal instead of the constructor form: (defun sum (l) (sum l 0)) (defun sum (('() total) total) ((`(,h . ,t) total) (sum t (+ h total))))


Matching records in function heads

Erlang: handle_info(ping, #state = State) -> gen_server:cast(self(), ping), ; handle_info(ping, State) -> ; LFE: (defun handle_info (('ping (= (match-state remote-pid 'undefined) state)) (gen_server:cast (self) 'ping) `#(noreply ,state)) (('ping state) `#(noreply ,state)))


Receiving messages

Erlang: universal_server() -> receive -> Func() end. LFE: (defun universal-server () (receive ((tuple 'become func) (funcall func)))) or: (defun universal-server () (receive (`#(become ,func) (funcall func))))


Examples


Erlang interoperability

Calls to Erlang functions take the form ''(: ... )'': (io:format "Hello, World!")


Functional paradigm

Using recursion to define the
Ackermann function In computability theory, the Ackermann function, named after Wilhelm Ackermann, is one of the simplest and earliest-discovered examples of a total computable function that is not primitive recursive. All primitive recursive functions are total ...
: (defun ackermann ((0 n) (+ n 1)) ((m 0) (ackermann (- m 1) 1)) ((m n) (ackermann (- m 1) (ackermann m (- n 1))))) Composing functions: (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))))


Concurrency

Message-passing with Erlang's light-weight "processes": (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)))) Multiple simultaneous HTTP requests: (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))))))


References


External links

* *
LFE Quick Start

LFE User Guide

LFE on Rosetta Code
{{Lisp programming language Programming languages Pattern matching programming languages Lisp programming language family