Fennel wiki: lume

The Lume library is a very handy tool that can be thought of as "Lua's missing standard library". It contains a bunch of common general-purpose functions that larger languages often feature built-in, including common table manipulation functions like map and reduce.

Most of Lume deals with sequence-type functions that operate on either sequential or key/value tables, but there are a few oddballs that don't.

You can install Lume via luarocks, or else you can just download the lume.lua file from its repository and drop that into your project directory.

(local lume (require :lume))

(local kv {:abc 123 :def 456 :xyz 789})
(local seq [123 456 789])

(fn even? [x] (= (% x 2) 0))

;; map a function over a table. note that the table is the first arg.
(lume.map seq (fn [x] (* 3 x))) ; -> [369 1368 2367]

;; keep or drop elements from a table based on a predicate function.
(lume.filter seq even?) ; -> [456]
(lume.reject seq even?) ; -> [123 789]

;; the classic reduce, aka foldl; run a function over everything in
;; the table with an accumulator value.
(lume.reduce seq (fn [acc x] (+ acc x))) ; -> 1368

;; return a new table with all the keys and values from any number of tables.
;; right-most arguments take precedence.
(lume.merge seq kv {:abc 963})
;; -> { :abc 963 :def 456 :xyz 789 1 123 2 456 3 789 }

;; unlike most of the other functions here, the extend function
;; modifies its first argument rather than returning a fresh table:
(local newtable {:qrs 147 :tuv 258})
(lume.extend newtable {:jkl 999})
newtable ; -> { :jkl 999 :qrs 147 :tuv 258 }

;; return all the keys in a table:
(lume.keys kv) ; -> ["xyz" "def" "abc"]

;; return the key under which a given value is first found in a table:
(lume.find seq 456) ; -> 2
(lume.find kv 789) ; "xyz"

;; similar to find, except use a predicate function instead of a value.
;; returns both the value matched and its index:
(lume.match seq even?) ; -> 456 2

;; select a subset of keys from a table:
(lume.pick kv :abc :xyz) ; -> { :abc 123 :xyz 789 }

;; finally we have a handful of miscellaneous non-table-related functions.

;; oddly Lua does not ship with a string splitting function; use this instead:
(lume.split "diode,capacitor,switch" ",") ; -> ["diode" "capacitor" "switch"]

;; generate a QUID and return a string representation:
(lume.uuid) ; -> "d6cce35c-487a-458f-aab2-9032c2621f38"

;; the hotswap function may be the most important thing in all of lume. it
;; facilitates seamless reloading of modules and works equally well with 
;; modules whether they are written in Fennel or Lua:

(local mymod (require :mymod))
mymod ; -> {:firstfunction #<function: 0x564>, :second #<function: 0x860>}
;; [ ... make some edits to mymod.fnl to add a third function ...]
;; not only will the hotswap function return the updated module...
(lume.hotswap :mymod) ; -> { :firstfunction ... :second ... :third ...}
;; but all existing references to the mymod module which have been loaded
;; using require will be updated to contain its latest contents!
mymod.third ; -> #<function: 0x9d6>

There's more in Lume that we haven't covered here; see the readme for a complete listing.