Jump to content

LFE (programming language)

From Wikipedia, the free encyclopedia

This is an old revision of this page, as edited by Oubiwann (talk | contribs) at 20:09, 17 January 2014 (Created page for LFE). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

(diff) ← Previous revision | Latest revision (diff) | Newer revision → (diff)
LFE
Paradigmmulti-paradigm: concurrent, functional
Designed byRobert Virding
DeveloperRobert Virding
First appeared2008
Stable release
v0.7a / 10 August 2011 (2011-08-10)
Typing disciplinedynamic, strong
LicenseApache License 2.0
Filename extensions.lfe .hrl
Websitelfe.github.io
Major implementations
Erlang
Influenced by
Erlang, Common Lisp, Scheme
Influenced
Elixir, Joxa, Concurrent Schemer

LFE (Lisp Flavored Erlang) is a functional, concurrent, general-purpose programming language built on top of Core Erlang and the Erlang Virtual Machine (BEAM). LFE builds on top of Erlang in order to provide a Lisp syntax for writing distributed, fault-tolerant, soft real-time, non-stop applications. LFE also extends Erlang to support meta-programming with macros and polymorphism via protocols.[1]

History

Robert Virding announced the release of LFE on the "Erlang Questions" mail list in March of 2008.[2] Virding developed LFE on version R12B-0 of Erlang,[3] on a Dell XPS laptop.[4]

Features


Syntax and Semantics

Symbolic expressions (S-expressions)

Like Lisp, LFE is an expression-oriented language. Unlike non-homoiconic programming languages, Lisps make no or little syntactic distinction between "expressions" and "statements": 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, (list 1 2 'foo) is a list whose elements are the integers 1 and 2, and the atom [[foo|foo]]. These values are implicitly typed: they are respectively two integers and a Lisp-specific data type called a "symbolic atom", and do not have to be declared as such.

As seen in the example above, LFE expressions are written as lists, using prefix notation. The first element in the list is the name of a form, i.e., a function, operator, macro, or operator. 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 (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 capabilities in anonymous function calls.

Examples

Erlang Interop

Calls to Erlang functions take the form (: <module> <function> <arg1> ... <argn>):

(: io format '"Hello, World!")

Functional Paradigm

Using recursion to define the Ackermann function:

(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 "threads":

(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 (((tuple '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 (tuple url headers))
         (http-options ())
         (request-options (list (tuple 'sync 'false))))
    (: httpc request method request-data http-options request-options)
    (receive
      ((tuple 'http (tuple request-id (tuple 'error reason)))
       (: io format '"Error: ~p~n" (list reason)))
      ((tuple 'http (tuple request-id result))
       (: io format '"Result: ~p~n" (list result))))))

References

  1. ^ "Lisp Flavored Erlang" (PDF). Robert Virding. Retrieved 2014-01-17.
  2. ^ "LFE announcement on Erlang Questions mail list". Retrieved 2014-01-17.
  3. ^ "Follow-upt to LFE announcement on Erlang Questions mail list". Retrieved 2014-01-17.
  4. ^ Armstrong, Joe; Virding, Robert (2013-12-30). "Hardware used in the development of Erlang and LFE" (Interview). Interviewed by Duncan McGreggor. {{cite interview}}: |access-date= requires |url= (help); |format= requires |url= (help); External link in |subjectlink1= and |subjectlink2= (help); Unknown parameter |subjectlink1= ignored (|subject-link1= suggested) (help); Unknown parameter |subjectlink2= ignored (|subject-link2= suggested) (help)