lfe_clj(3)
๐ lfe_clj(3) โ the clj LFE Clojure interface library ๐
โจ NAME โจ
clj โ LFE Clojure interface library. Itโs literally the Clojure-flavored bestie for your LFE code. ๐ซถ
โจ SYNOPSIS โจ
This module provides Clojure-inspired functions and macros for use in LFE. Thatโs the whole vibe: Clojure energy, LFE address. ๐
โจ EXPORTS โจ
N.B. You do not have to make fully-qualified calls to the macros exported from clj โ you can (include-lib "lfe/include/clj.lfe") and then call them directly, like this:
(include-lib "lfe/include/clj.lfe")
(-> 2 (+ 2) (=:= 4)) ; 'true
๐ ๏ธ Function Macros ๐ ๏ธ
(defn name [arg ...] {{doc-string}} ...)and(defn {{doc-string}} ([argpat ...] ...))โ define and automatically export a function. Yes, it exports it for you, no extra steps, slay. โจ(defn- name [arg ...] {{doc-string}} ...)and(defn- {{doc-string}} ([argpat ...] ...))โ equivalent todefun.(fn (arg ...) ...)โ equivalent tolambda.
๐งต Threading Macros ๐งต
Note: the original versions were copied from Tim Dysingerโs lfesl repo here:
https://github.com/lfex/lfesl/blob/master/include/thread.lfe
They have since been modified to be safely exportable. Iconic glow-up behavior, honestly. ๐
(-> ...)โ thread first.
Example usage, demonstrating ordering (and yes, the order is the whole point, bestie):
> (set o '(#(a 1) #(b 2) #(c 3)))
(#(a 1) #(b 2) #(c 3))
> (clj:-> o
> (++ '(#(d 4)))
> (++ '(#(e 5)))
> (++ '(#(f 6))))
(#(a 1) #(b 2) #(c 3) #(d 4) #(e 5) #(f 6))
Note that the use of -> in this example results in each successive value being appended to the input list.
Another example showing how this works:
> (lists:sublist
> (lists:reverse
> (lists:sort
> (lists:merge
> (string:tokens
> (string:to_upper "a b c d e")
> " ")
> '("X" "F" "L"))))
> 2 3)
("L" "F" "E")
Can be rewritten as this:
> (clj:-> "a b c d e"
> (string:to_upper)
> (string:tokens " ")
> (lists:merge '("X" "F" "L"))
> (lists:sort)
> (lists:reverse)
> (lists:sublist 2 3))
("L" "F" "E")
(->> ...)โ thread last.
Example usage, demonstrating ordering:
> (set o '(#(a 1) #(b 2) #(c 3)))
(#(a 1) #(b 2) #(c 3))
> (clj:->> o
> (++ '(#(d 4)))
> (++ '(#(e 5)))
> (++ '(#(f 6))))
(#(f 6) #(e 5) #(d 4) #(a 1) #(b 2) #(c 3))
Note that the use of ->> in this example results in each successive value being prepended to the input list. Different direction, different drama. ๐
Another example showing how this:
> (lists:foldl #'+/2 0
> (clj:take 10
> (lists:filter
> (clj:comp #'clj:even?/1 #'clj:round/1)
> (lists:map
> (lambda (x)
> (math:pow x 2))
> (clj:seq 42)))))
1540.0
Can be rewritten as this:
> (clj:->> (clj:seq 42)
> (lists:map (lambda (x) (math:pow x 2)))
> (lists:filter (clj:comp #'clj:even?/1 #'clj:round/1))
> (clj:take 10)
> (lists:foldl #'+/2 0))
1540.0
(as-> expr name . sexps)โ bindnametoexpr, evaluate the firstsexpin the lexical context of that binding, then bindnameto that result, repeating for each successivesexpinsexps, and return the result of the lastsexp. Itโs giving โpass the aux, but make it lexical.โ ๐(cond-> expr . clauses)โ given an expression and a set of test/sexppairs, threadx(via->) through eachsexpfor which the corresponding test expression is truthy, i.e. neither'falsenor'undefined. Note that, unlikecondbranching,cond->threading does not short circuit after the first truthy test expression. It keeps going, main character energy. ๐(cond->> expr . clauses)โ given an expression and a set of test/sexppairs, threadx(via->>) through eachsexpfor which the corresponding test expression is truthy, i.e. neither'falsenor'undefined. Note that, unlikecondbranching,cond->>threading does not short circuit after the first truthy test expression. Same no-short-circuit vibe, different thread. ๐(some-> x . sexps)โ whenxis not'undefined, thread it into the firstsexp(via->), and when that result is not'undefined, through the next, etc. Lowkey the โonly if it existsโ pipeline. ๐ฆ(some->> x . sexps)โ whenxis not'undefined, thread it into the firstsexp(via->>), and when that result is not'undefined, through the next, etc. Samesome->energy, but last-threaded. โจ
๐ Conditional Macros ๐
(if-let ((patt test)) then {{else}})โ iftestevaluates to anything other than'falseor'undefined, evaluatethenwithpattbound to the value oftest; otherwise evaluateelse, if supplied, else'undefined.(iff-let ((patt test)) . body)โ whentestevaluates to anything other than'falseor'undefined, evaluatebodywithpattbound to the value oftest; otherwise return'undefined.(condp pred expr . clauses)โ given a binary predicate, an expression, and a set of clauses of the form:
test-expr result-expr
test-expr >> result-fn
where result-fn is a unary function, if (pred test-expr expr) returns anything other than 'undefined or 'false, the clause is a match.
If a binary clause matches, return result-expr. If a ternary clause matches, call result-fn with the result of the predicate and return the result.
If no clause matches and a single default expression is given after the clauses, return it. If no default expression is given and no clause matches, throw a no-matching-clause error. No cap, it will absolutely throw. ๐ญ
(if-not test then)and(if-not test then else)โ iftestevaluates to'falseor'undefined, evaluate and returnthen; otherwiseelse, if supplied, else'undefined.(iff test . body)โ like Clojureโswhen. Iftestevaluates to anything other than'falseor'undefined, evaluatebodyin an implicitprogn.(when-not test . body)โ iftestevaluates to'falseor'undefined, evaluatebodyin an implicitprogn. Otherwise return'undefined.(not= x),(not= x y), and(not= x y . more)โ same as(not (== ...)).
๐ธ Predicate Macros ๐ธ
Allowed in guards, unless otherwise stated. Guard-friendly little icons, we love to see it. ๐ซถ
(tuple? x)โ return'trueifxis a tuple.(atom? x)โ return'trueifxis an atom.(binary? x)โ return'trueifxis a binary.(bitstring? x)โ return'trueifxis a bitstring.(boolean? x)and(bool? x)โ return'trueifxis a boolean.(float? x)โ return'trueifxis a float.(function? f)and(func? f)โ return'trueifxis a function.(function? f n)and(func? f n)โ return'trueiffis ann-ary function.(integer? x)and(int? x)โ return'trueifxis an integer.(number? x)โ return'trueifxis a number.(record? x record-tag)and(record? x record-tag size)โ return'trueifxis a tuple and its first element isrecord-tag. Ifsizeis given, check thatxis arecord-tagrecord of sizesize.
N.B.record?/2may yield unexpected results, due to difference between the Erlang and LFE compilers. As such, whenever possible, preferrecord?/3.
(reference? x)โ return'trueifxis a reference.(map? x)โ return'trueifxis a map. Return'falseon versions of Erlang without maps. Respect the old Erlang era, bestie. ๐ฐ๏ธ(undefined? x)and(undef? x)โ return'trueifxis the atom'undefined.(nil? x)โ return'trueifxis the atom'nilor the empty list.(true? x)โ return'trueifxis the atom'true.(false? x)โ return'trueifxis the atom'false.(falsy? x)โ return'trueifxis one of the atoms'falseand'undefined.(odd? x)โ return'trueifxis odd.(even? x)โ return'trueifxis even.(zero? x)โ return'trueifxis zero.(pos? x)โ return'trueifxis greater than zero.(neg? x)โ return'trueifxis less than zero.(identical? x)โ return'trueifxis exactly equal toy.
๐ฆ Other Macros ๐ฆ
(str x1, x2 ... xn)โ given an arbitrary number of arguments, return a string consisting of each of their string representations.
N.B. Because Erlang characters are represented as integers, this will not work for chars, e.g.#\a, which will be presented in the return value as its integer value, i.e."97".
> (clj:str #\a "bc")
"97bc"
> (clj:str "a" "bc")
"abc"
(lazy-seq)and(lazy-seq seq)โ return a (possibly infinite) lazy sequence from a given lazy sequenceseq, or a finite lazy sequence from given listseq. A lazy sequence is treated as finite if at any iteration it produces the empty list, instead of a cons cell with data as the head and a nullary function for the next iteration as the tail. Itโs giving โinfinite until it says itโs done.โ โจ(conj coll . xs)โconj[oin]a value onto an existing collection. Prepend to a list, append to a tuple, and merge maps. Collection glow-up, no cap. ๐
๐ Clojure-inspired if Macro ๐
(if test then)and(if test then else)โ iftestevaluates to anything other than'falseor'undefined, returnthen; otherwiseelse, if given, else'undefined.
๐ง Function Composition ๐ง
(comp f g)โ right to left function composition.(comp fs x)โ compose a list of functionsfs, right to left, and apply the resulting function tox.(comp f g x)โ equivalent to(funcall (comp f g) x).(comp fs)โ compose a list of functionsfsfrom right to left.(comp)โ equivalent to#'identity/1.
๐ Usage ๐
The following examples assume #'1+/1 is defined:
> (defun 1+ (x) (+ x 1))
1+
> (funcall (clj:comp #'math:sin/1 #'math:asin/1) 0.5)
0.49999999999999994
> (funcall (clj:comp (list #'1+/1 #'math:sin/1 #'math:asin/1) 0.5))
1.5
Or used in another function call:
> (lists:filter (clj:comp #'not/1 #'zero?/1)
'(0 1 0 2 0 3 0 4))
(1 2 3 4)
The usage above is best when comp will be called by higher-order functions like lists:foldl/3 or lists:filter/2, etc. However, one may also call comp in the following manner, best suited for direct usage:
> (clj:comp #'math:sin/1 #'math:asin/1 0.5)
0.49999999999999994
> (clj:comp (list #'1+/1 #'math:sin/1 #'math:asin/1) 0.5)
1.5
๐ Partial Application ๐
(partial f args)and(partial f arg-1)โ partially applyfto a given argumentarg-1or list ofargs. Pre-fill the vibe, call it later. ๐
โจ Usage โจ
Okay bestie, letโs see this cutie in action. ๐ These examples are literally the whole vibe:
> (set f (clj:partial #'+/2 1))
#Fun<clj.3.121115395>
> (funcall f 2)
3
> (set f (clj:partial #'+/3 1))
#Fun<clj.3.121115395>
> (funcall f '(2 3))
6
> (set f (clj:partial #'+/3 '(2 3)))
#Fun<clj.3.121115395>
> (funcall f 4)
9
> (set f (clj:partial #'+/4 '(2 3)))
#Fun<clj.3.121115395>
> (funcall f '(4 5))
14
Lowkey important: to partially apply a function that expects a list, you have to wrap that list into a (singleton) list. No cap. ๐ซถ
> (set double (clj:partial #'*/2 2))
#Fun<clj.5.16146786>
> (set f (clj:partial #'lists:map/2 double))
#Fun<clj.5.16146786>
> (funcall f '((1 2 3)))
(2 4 6)
๐ฆ Predicate Functions ๐ฆ
N.B. These functions may not be used in guards. ๐จ
(string? data)โ Return'trueifdatais a flat list of printable characters. ๐(unicode? data)โ Return'trueifdatais a flat list of printable Unicode characters. ๐(list? data)โ Return'trueifdatais a list and not a string. ๐(set? data)โ Return'trueifdataappears to be a (possibly ordered) set. โจ(dict? data)โ Return'trueifdatais a dictionary. ๐(proplist? lst)โ Return'trueiflstis a list whereproplist-kv?/1returns'truefor all elements inlst. ๐ง(proplist-kv? data)โ Return'trueifdatais a key/value tuple or an atom. ๐(queue? x)โ Return'trueifxis a queue. ๐ถ(empty? x)โ Return'trueifxis the empty list, tuple, map, dictionary, queue, or general balanced tree. ๐ซง(every? pred lst)โ Return'trueif(pred x)returns'truefor everyxinlst. ๐ฏ(all? pred lst)โ Return'trueif(pred x)returns'truefor everyxinlst. ๐(any? pred lst)โ Return'trueif(pred x)returns'truefor anyxinlst. ๐ฅ(not-any? pred lst)โ Return'falseif(pred x)returns'truefor anyxinlst. ๐(element? elem data)โ Return'trueifelemis an element ofdata, wheredatais a list, set or ordset. ๐ฏ
๐ธ Sequence Functions ๐ธ
(seq end)โ Equivalent to(seq 1 end). โจ(seq start end)โ Equivalent to(seq start end 1). ๐ซ(seq start end step)โ Return a sequence of integers, starting withstart, containing the successive results of addingstepto the previous element, untilendhas been reached orpassword. In the latter case,endis not an element of the sequence. ๐ซถ(next func)โ Equivalent to(next func 1 1). ๐(next func start)โ Equivalent to(next func start 1). ๐ฆ(next func start step)โ Return a nullary function that returns a cons cell withstartas the head and a nullary function,(next func (funcall func start step) step), as the tail. The result can be treated as a (possibly infinite) lazy list, which only computes subsequent values as needed. ๐(lazy-seq seq)โ Return a lazy sequence (possibly infinite) from given lazy sequenceseqor finite lazy sequence from given listseq. Lazy sequence is treated as finite if at any iteration it produces empty list instead of data as its head and nullary function for next iteration as its tail. ๐ง(cycle lst)โ Return a lazy infinite sequence with all elements from a given listlstor another lazy sequence cycled. Seenext/3for details on the structure. ๐(range)โ Equivalent to(range 1 1). ๐(range start)โ Equivalent to(range start 1). โญ(range start step)โ Return a lazy list of integers, starting withstartand increasing bystep. Equivalent to(next #'+/2 start step). See also:next/3. ๐(drop n lst)โ Return a list of all but the firstnelements inlst. Ifnis the atomall, return the empty list. ๐ซณ(drop โall lst)โ Return a list of all but the firstnelements inlst. Ifnis the atomall, return the empty list. ๐จ(take n lst)โ Given a (possibly lazy) listlst, return a list of the firstnelements oflst, or all elements if there are fewer thann. Ifnis the atomallandlstis a โnormalโ list, returnlst. ๐ซด(take โall lst)โ Given a (possibly lazy) listlst, return a list of the firstnelements oflst, or all elements if there are fewer thann. Ifnis the atomallandlstis a โnormalโ list, returnlst. ๐(split-at n lst)โ Return a tuple of#(,(take n lst) ,(drop n lst)). โ๏ธ(partition n lst)โ Equivalent to(partition n n lst). ๐งฉ(partition n step lst)โ Equivalent to(partition n step () lst). ๐ช(partition n step pad lst)โ Return a list of lists ofnitems each, at offsetsstepapart. Use the elements ofpadas necessary to complete the last partition up tonelements. In case there are not enough padding elements, return a partition with less thannitems. ๐จ(partition-all n lst)โ Equivalent to(partition-all n n lst). ๐งต(partition-all n step lst)โ Return a list of lists likepartition/3, possibly including partitions with fewer thannelements at the end. ๐ท(interleave list-1 list-2)โ Return a list of the first element of each list, then the second, etc. ๐ค(get-in data keys)โ Equivalent to(get-in data keys 'undefined). ๐(get-in data keys not-found)โ Return the value in a nested associative structure, wherekeysis a list of keys or list indices. Return the atomnot-foundif the key is not present or index is out of bounds, or thenot-foundvalue. ๐๏ธ(reduce func (cons head tail))โ Equivalent to(reduce func head tail). ๐(reduce func acc lst)โ Equivalent to(lists:foldl func acc lst). ๐งฎ(repeat x)โ Return a lazy infinite sequence ofxs. Seenext/3for details on the structure. ๐(repeat n f)โ Given a nullary functionf, return a list ofnapplications off. ๐ฌ(repeat n x)โ Given a termx, return a list ofncopies ofx. ๐ฏ
๐ Other Functions ๐
(identity x)โ Identity function. ๐ช(constantly x)โ Return a unary function that returnsx. N.B. This is like Haskellโsconstrather than Clojureโsconstantly. ๐งธ(inc x)โ Incrementxby 1. โ(dec x)โ Decrementxby 1. โ
๐ AUTHORS ๐
Huge shoutout to Tim Dysinger, Duncan McGreggor, and Eric Bailey โ icons only. ๐ โจ
Final cute sign-off: the source/version and date footer says 2015-2016, lfe_clj(3) โ and thatโs the whole page, bestie. ๐๐๐
๐ฆ where this page comes from
- alpine 3.24: lfe-doc 2.2.0-r2 ยท Apache-2.0
- nixos 26.05: erlang27.3.4.19-lfe 2.2.0
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms