LFE comes with a powerful REPL, supporting interactive development (including writing macros!) as well as running scripts or even evaluating arbitrary LFE code via the command line.
lfe> (== 42 #b101010)
true
lfe> (integer_to_list 42 2)
"101010"
lfe> #\a
97
lfe> "regular string"
"regular string"
lfe> #"binary string"
#"binary string"
Note that in LFE and Erlang a string is really just a list of integers;
there is no "string" type. There is, however, an "atom" type in LFE; this would be analogous to the Lisp symbol. For example, 'my-atom
, or if the atom has spaces in it, '|my atom|
.
;; Lists
lfe> '(a b c 1 2 5)
(a b c 1 2 5)
;; Tuples
lfe> #("element 1" 2 elem-3)
#("element 1" 2 elem-3)
;; Maps
lfe> #m(key1 "value 1"
"key 2" value-2)
#M("key 2" value-2 key1 "value 1")
In LFE lists are like they are in a Lisp (except they also include strings). Additionally, LFE has tuples (Lisp vectors) and maps (Lisp has tables). LFE has property lists, dicts, and ordered dicts from Erlang, supported via additional libraries.
;; Defining a record automatically generates a set of
;; useful functions for that particular record.
lfe> (defrecord person
name
address
age)
set-person-age
;; Use the generated record constructor:
lfe> (make-person name "Ford Prefect"
address "Betelgeuse Seven"
age 234))
#(person "Ford Prefect" "Betelgeuse Seven" 234)
Like all data in LFE, records can be pattern-matched. Pattern matching on record field names and data in function arguments is an extremely powerful capability provided to developers.
;; A recursive function with pattern matching:
lfe> (defun ackermann
((0 n) (+ n 1))
((m 0) (ackermann (- m 1) 1))
((m n) (ackermann (- m 1)
(ackermann m (- n 1)))))
;; Call the function
lfe> (ackermann 3 4)
125
;; Apply the function
lfe> (funcall #'ackermann/2 3 4))
125
As well as supporting the standard Lisp syntax for defun
,
LFE functions support pattern matching in arguments, allowing you to create
concise, expressive, and elegant code.
;; LFE and Erlang do not support n-arity functions, but
;; you can write a Lisp macro to get around that :-)
lfe> (defmacro mean args
`(/ (lists:sum ,args)
,(length args)))
;; Use the macro with different numbers of arguments:
lfe> (mean 1)
1.0
lfe> (mean 1 2)
1.5
lfe> (mean 1 2 3 4 5 6 42 108)
21.375
LFE macros are unhygenic, but with scoped variables. There is no gensym
in
LFE due to this being unsafe in long-lived, distributed code (LFE supports
sharing code with remote nodes). With the exception of running in the REPL,
macros are only compile-time.
lfe> (lists:reverse
(erlang:integer_to_list
(lists:foldl #'*/2 1 '(1 2 3 4))))
"42"
lfe> (supervisor:which_children 'kernel_sup)
(#(logger_sup #Pid<0.70.0> supervisor (logger_sup))
#(kernel_safe_sup #Pid<0.69.0> supervisor (kernel))
#(kernel_refc #Pid<0.68.0> worker (kernel_refc))
#(kernel_config #Pid<0.67.0> worker (kernel_config))
#(user #Pid<0.63.0> supervisor (user_sup))
#(standard_error #Pid<0.61.0> supervisor (standard_error))
#(erl_signal_server #Pid<0.60.0> worker dynamic)
...)
Here we have two examples of directly calling Erlang functions from LFE. First, we're "folding" (a.k.a "reducing") over a list of items, multiplying them by the accumulated value, and then further transforming using other Erlang functions. Then we are calling an Erlang function to get information about a particular supervision tree.
(defmodule server
(behaviour gen_server)
(export
(start_link 0)
(stop 0)
...))
(defun handle_call
(('amount _caller state-data)
`#(reply ,state-data ,state-data))
(('stop _caller state-data)
`#(stop shutdown ok state-data))
((message _caller state-data)
`#(reply ,(unknown-command) ,state-data)))
OTP is what you use when you need to create industrial grade applications and services; there's nothing quite like it in the programming world. As such, it has inspired countless imitations in a great many other programming languages. In LFE, you get to use the real deal.
LFE Features
Alien Technology
It is an established fact that John McCarthy shared alien tech with the world in 1958 when he introduced us to Lisp. We continue that great tradition.
- Functions and variables with separate namespaces (LFE is a Lisp-2)
- Low-hygiene Macros
- Homoiconicity
- In-REPL Function and macro definitions
Core Erlang Foundation
All the benefits of Erlang with none of the Prolog.
- No global data
- No mutable data
- Pattern matching and guards
- Compiler and interpreter
- Hot upgrading of deployed code
- The Banarama of languages
The ability to generate distributed applications and full releases in mere minutes.
- Fault-tolerant
- Massively scalable
- Extreme Concurrency
- Soft real-time
- Open. Telecom. Platform.
Language Lab
The mad-scientist powers of a Lisp combined with the efficiency of the Actor Model and Erlang's light-weight processes.
- Experiment with creating distributed systems in new ways.
- Create DSLs on-demand.
- Take advantage of 1000s of cores without having to change your code.
- Easily write your own compilers.
Build It with LFE
Stand-alone Libraries
Building libraries for use by LFE applications (and even Erlang or other BEAM language applications!) is the bread and butter of LFE hackers. The Erlang/BEAM ecosystem is fully accessible to LFE applications, but you also have the freedom to do more in LFE.
OTP Releases
When your LFE prototype is ready for the big-time, you can run it with all the sophisticated machinery of an OTP release. In fact, you don't have to wait: start your prototype as a release, with zero pain and all of the benefit.
Books
LFE Chinenual
A work in progress, this book aims to eventually be the complete manual for LFE
Videos