summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--lfe.html.markdown459
1 files changed, 459 insertions, 0 deletions
diff --git a/lfe.html.markdown b/lfe.html.markdown
new file mode 100644
index 00000000..bdf1eff8
--- /dev/null
+++ b/lfe.html.markdown
@@ -0,0 +1,459 @@
+---
+
+language: "Lisp Flavoured Erlang(LFE)"
+filename: lispflavourederlang.lfe
+contributors:
+ - ["Pratik Karki", "https://github.com/prertik"]
+---
+
+Lisp Flavoured Erlang(LFE) is a functional, concurrent, general-purpose programming
+language and Lisp dialect(Lisp-2) built on top of Core Erlang and the Erlang Virtual Machine(BEAM).
+
+LFE can be obtained from [LFE](https://github.com/rvirding/lfe)
+
+The classic starting point is [LFE DOCS.](http://docs.lfe.io)
+
+Another new site is being built to replace it.[LFE DEV.](http://docs.lfe.io/dev)
+
+
+
+```lfe
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; 0. Syntax
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; General form.
+
+;; Lisp comprises of two syntax called: the ATOM and the S-expression.
+;; `forms` are known as grouped S-expressions.
+
+8 ; an atom; it evaluates to itself
+
+:ERLANG ;Atom; evaluates to the symbol :ERLANG.
+
+t ; another atom which denotes true.
+
+(* 2 21) ; an S- expression
+
+'(8 :foo t) ;another one
+
+
+;;; Comments
+
+;; Single line comments start with a semicolon; use two for normal
+;; comments, three for section comments, and four fo file-level
+;; comments.
+
+;; Block Comment
+
+ #| comment text |#
+
+;;; Environment
+
+;; LFE is the de-facto standard.
+
+;; Libraries can be used directly from the Erlang ecosystem. Rebar3 is the build tool.
+
+;; LFE is usually developed with a text editor(preferably Emacs) and a REPL
+;; (Read Evaluate Print Loop) running at the same time. The REPL
+;; allows for interactive exploration of the program as it is "live"
+;; in the system.
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; 1. Literals and Special Syntactic Rules
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Integers
+
+1234 -123 ; Regular decimal notation
+#b0 #b10101 ; Binary notation
+#0 #10101 ; Binary notation (alternative form)
+#o377 #o-111 ; Octal notation
+#d123456789 #d+123 ; Explicitly decimal notation
+#xc0ffe 0x-01 ; Hexadecimal notation
+#2r1010 #8r377 ;Notation with explicit base (up to 36)
+#\a #$ #\ä #\🐭 ;Character notation (the value is the Unicode code point of the character)
+#\x1f42d; ;Character notation with the value in hexadecimal
+
+;;; Floating point numbers
+1.0 +2.0 -1.5 1.0e10 1.111e-10
+
+;;; Strings
+
+"any text between double quotes where \" and other special characters like \n can be escaped".
+; List String
+"Cat: \x1f639;" ; writing unicode in string for regular font ending with semicolon.
+
+#"This is a binary string \n with some \"escaped\" and quoted (\x1f639;) characters"
+; Binary strings are just strings but function different in the VM.
+; Other ways of writing it are: #B("a"), #"a", and #B(97).
+
+
+;;; Character escaping
+
+\b ; => Backspace
+\t ; => Tab
+\n ; => Newline
+\v ; => Vertical tab
+\f ; => Form Feed
+\r ; => Carriage Return
+\e ; => Escape
+\s ; => Space
+\d ; => Delete
+
+;;; Binaries
+;; It is used to create binaries with any contents.
+#B((#"a" binary) (#"b" binary)) ; #"ab" (Evaluated form)
+
+;;; Lists are: () or (foo bar baz)
+
+;;; Tuples are written in: #(value1 value2 ...). Empty tuple #() is also valid.
+
+;;; Maps are written as: #M(key1 value1 key2 value2 ...). Empty map #M() is also valid.
+
+;;; Symbols: Things that cannot be parsed. Eg: foo, Foo, foo-bar, :foo
+| foo | ; explicit construction of symbol by wrapping vertical bars.
+
+;;; Evaluation
+
+;; #.(... some expression ...). E.g. '#.(+ 1 1) will evaluate the (+ 1 1) while it ;; reads the expression and then be effectively '2.
+
+;; List comprehension in LFE REPL
+
+lfe> (list-comp
+ ((<- x '(0 1 2 3)))
+ (trunc (math:pow 3 x)))
+ (1 3 9 27)
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 2. Core forms
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; These forms are same as those found at Common Lisp and Scheme.
+
+(quote e)
+(cons head tail)
+(car e)
+(cdr e)
+(list e ... )
+(tuple e ... )
+(binary seg ... )
+(map key val ...), (map-get m k), (map-set m k v ...), (map-update m k v ...)
+
+(lambda (arg ...) ...)
+ (match-lambda
+ ((arg ... ) {{(when e ...)}} ...) ; Matches clauses
+ ... )
+(let ((pat {{(when e ...)}} e)
+ ...)
+ ... )
+(let-function ((name lambda|match-lambda) ; Only define local
+ ... ) ; functions
+ ... )
+(letrec-function ((name lambda|match-lambda) ; Only define local
+ ... ) ; functions
+ ... )
+(let-macro ((name lambda-match-lambda) ; Only define local
+ ...) ; macros
+ ...)
+(progn ... )
+(if test true-expr {{false-expr}})
+(case e
+ (pat {{(when e ...)}} ...)
+ ... ))
+(receive
+ (pat {{(when e ...)}} ... )
+ ...
+ (after timeout ... ))
+(catch ... )
+(try
+ e
+ {{(case ((pat {{(when e ...)}} ... )
+ ... ))}}
+ {{(catch
+ ; Next must be tuple of length 3!
+ (((tuple type value ignore) {{(when e ...)}}
+ ... )
+ ... )}}
+ {{(after ... )}})
+
+(funcall func arg ... )
+(call mod func arg ... ) - Call to Erlang Mod:Func(Arg, ... )
+(define-module name declaration ... )
+(extend-module declaration ... ) - Define/extend module and declarations.
+(define-function name lambda|match-lambda)
+(define-macro name lambda|match-lambda) - Define functions/macros at top-level.
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 3. Macros
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Macros are part of the language to allow you to create abstractions
+;; on top of the core language and standard library that move you closer
+;; toward being able to directly express the things you want to express.
+
+;; Top-level function
+
+(defun name (arg ...) ...)
+
+;; Adding comments in functions
+
+(defun name
+ "Toplevel function with pattern-matching arguments"
+ ((argpat ...) ...)
+ ...)
+
+;; Top-level macro
+
+(defmacro name (arg ...) ...)
+(defmacro name arg ...)
+
+;; Top-level macro with pattern matching arguments
+
+(defmacro name
+ ((argpat ...) ...)
+ ...)
+
+;; Top-level macro using Scheme inspired syntax-rules format
+
+(defsyntax name
+ (pat exp)
+ ...)
+
+;;; Local macros in macro or syntax-rule format
+
+(macrolet ((name (arg ... ) ... )
+ ... )
+ ... )
+
+(syntaxlet ((name (pat exp) ...)
+ ...)
+ ...)
+
+;; Like CLISP
+
+(prog1 ...)
+(prog2 ...)
+
+;; Erlang LFE module
+
+(defmodule name ...)
+
+;; Erlang LFE record
+
+(defrecord name ...)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 4. Patterns and Guards
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Using patterns in LFE compared to that of Erlang
+
+;; Erlang ;; LFE
+;; {ok, X} (tuple 'ok x)
+;; error 'error
+;; {yes, [X|Xs]} (tuple 'yes (cons x xs))
+;; <<34,F/float>> (binary 34 (f float))
+;; [P|Ps]=All (= (cons p ps) all)
+
+ _ ; => is don't care while pattern matching
+
+ (= pattern1 pattern2) ; => easier, better version of pattern matching
+
+;; Guards
+
+;; Whenever pattern occurs(let, case, receive, lc, etc) it can be followed by an optional
+;; guard which has the form (when test ...).
+
+(progn gtest ...) ;; => Sequence of guard tests
+(if gexpr gexpr gexpr)
+(type-test e)
+(guard-bif ...) ;; => Guard BIFs, arithmetic, boolean and comparison operators
+
+;;; REPL
+
+lfe>(set (tuple len status msg) #(8 ok "Trillian"))
+ #(8 ok "Trillian")
+lfe>msg
+ "Trillian"
+
+;;; Program illustrating use of Guards
+
+(defun right-number?
+ ((x) (when (orelse (== x 42) (== x 276709)))
+ 'true)
+ ((_) 'false))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 5. Functions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; A simple function using if.
+
+(defun max (x y)
+ "The max function."
+ (if (>= x y) x y))
+
+;; Same function using more clause
+
+(defun max
+ "The max function."
+ ((x y) (when (>= x y)) x)
+ ((x y) y))
+
+;; Same function using similar style but using local functions defined by flet or fletrec
+
+(defun foo (x y)
+ "The max function."
+ (flet ((m (a b) "Local comment."
+ (if (>= a b) a b)))
+ (m x y)))
+
+;; LFE being Lisp-2 has separate namespaces for variables and functions
+;; Both variables and function/macros are lexically scoped.
+;; Variables are bound by lambda, match-lambda and let.
+;; Functions are bound by top-level defun, flet and fletrec.
+;; Macros are bound by top-level defmacro/defsyntax and by macrolet/syntaxlet.
+
+;; (funcall func arg ...) like CL to call lambdas/match-lambdas
+;; (funs) bound to variables are used.
+
+;; separate bindings and special for apply.
+apply _F (...),
+apply _F/3 ( a1, a2, a3 )
+
+;; Cons'ing in function heads
+(defun sum (l) (sum l 0))
+ (defun sum
+ (('() total) total)
+ (((cons h t) total) (sum t (+ h total))))
+
+;; ``cons`` literal instead of constructor form
+ (defun sum (l) (sum l 0))
+ (defun sum
+ (('() total) total)
+ ((`(,h . ,t) total) (sum t (+ h total))))
+
+;; Matching records in function heads
+
+(defun handle_info
+ (('ping (= (match-state remote-pid 'undefined) state))
+ (gen_server:cast (self) 'ping)
+ `#(noreply ,state))
+ (('ping state)
+ `#(noreply ,state)))
+
+;; Receiving Messages
+ (defun universal-server ()
+ (receive
+ ((tuple 'become func)
+ (funcall func))))
+
+;; another way for receiving messages
+
+ (defun universal-server ()
+ (receive
+ (`#(become ,func)
+ (funcall func))))
+
+;; Composing a complete function for specific tasks
+
+(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))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 6. Concurrency
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Message passing as done by 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))))))
+
+
+;; Check out Erlang's documentation for more concurrency and OTP docs.
+```
+
+## Further Reading
+
+* [LFE DOCS](http://docs.lfe.io)
+* [LFE GitBook](https://lfe.gitbooks.io/reference-guide/index.html)
+* [LFE Wiki](https://en.wikipedia.org/wiki/LFE_(programming_language))
+
+## Extra Info
+* [LFE PDF](http://www.erlang-factory.com/upload/presentations/61/Robertvirding-LispFlavouredErlang.pdf)
+* [LFE mail](https://groups.google.com/d/msg/lisp-flavoured-erlang/XA5HeLbQQDk/TUHabZCHXB0J)
+
+## Credits
+
+Lots of thanks to Robert Virding for creating LFE, Duncan McGreggor for documenting it and other LFE contributors who made LFE awesome.
+