Fennel wiki: cljlib

Cljlib is an experimental library that brings a lot of stuff from Clojure's core library into Fennel. The source code can be found at https://gitlab.com/andreyorst/fennel-cljlib.

fn* create single and multi-arity functions

(import-macros {: fn*} :cljlib)

fn* can be used to create functions of fixed arities, with runtime check for argument count:

(fn* foo
  "function that accepts fixed amount of arguments"
  [a b c]
  (+ a b c))

(foo 1 2 3) ;; => 6
(foo 1 2) ;; => error, wrong arg amount for single-arity-foo

fn* also can be used to create multi-arity functions, that evaluate different bodies based on argument count:

(fn* bar
  "function that still accepts fixed amount of arguments,
   but knows how to deal with different arities"
  ([a] a)
  ([a b] (+ a b))
  ([a b & c]
   (bar (+ a b) (unpack c))))

(bar 1) ;; => 1
(bar 1 2) ;; => 3
(bar 1 2 3) ;; => 6
(bar 1 2 3 4) ;; => 10

Most functions in this library are implemented with this macro.

into transform sequential tables into associative, and back

(import-macros {: into} :cljlib)

into implemented as a macro, that understands different types of tables and knows how to deal with those:

(into [] {:a 1 :b 2}) ;; => [["b" 2] ["a" 1]]
(into {:a 10 :c 20} {:a 1 :b 2}) ;; => {:a 1 :b 2 :c 20}
(into {} [[:a 1] [:b 2]]) => {:a 1 :b 2}

Runtime checking is also possible:

(local a [1 2 3])
(into a [4 5 6]) ;; => [1 2 3 4 5 6]

(local b {:host "localhost"})
(into b [[:port 1234]]) ;; => {:host "localhost" :port 1234}

This is done by runtime deduction of table type, and therefore doesn't work for empty tables:

(local a [])
(into a {:a 1}) ;; => [["a" 1]]

(local b {})
(into b {:a 1}) ;; => [["a" 1]]
(into {} {:a 1}) ;; => {:a 1}

Empty tables can be distinguished only when used in literal forms.

mapv map function over one or more tables

(local {: mapv} (require :cljlib))

mapv works exactly like in Clojure, though doesn't yield a transducer (yet?)

(fn inc [x] (+ x 1))
(mapv inc [1 2 3 4]) ;; => [2 3 4 5]

Associative tables also supported:

(mapv (fn [[k v]] (print (.. "key: " k ", val: " v))) {:a 1 :b 2})
;; prints:
;; key b, val 2
;; key a, val 1
;; returns
;; {}

Several tables can also be passed:

(mapv (fn [v1 v2] (+ v1 v2))
      [1 2 3 4]
      [-1 5 0])
;; => [0 7 3]

There's also reduce, reduce-kv, seq, range, eq, and other functions available, and complete list of functions and macros, with descriptions can be viewed at project's documentation.