summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Orst <andreyorst@gmail.com>2020-11-14 16:51:51 +0300
committerAndrey Orst <andreyorst@gmail.com>2020-11-14 16:55:11 +0300
commit4ea70bf39971eeb742a5de689a9ad8ba63559ecb (patch)
tree0c8268316eff16ca5b066063b29ea410c0405336
parent612d8185384ca77347ed89d02c45b91cd9dcd57a (diff)
Feature(doc): upload autogenerated documentation.
-rw-r--r--README.org517
-rw-r--r--cljlib-macros.fnl24
-rw-r--r--cljlib.fnl157
-rw-r--r--doc/0.1.0/cljlib-macros.md288
-rw-r--r--doc/0.1.0/cljlib.md674
-rw-r--r--tests/fn.fnl14
6 files changed, 1064 insertions, 610 deletions
diff --git a/README.org b/README.org
index 6204a59..e30d62c 100644
--- a/README.org
+++ b/README.org
@@ -11,519 +11,4 @@ Even though it is project is experimental, the goals of this project are:
- Be close to the platform, e.g. implement functions in a way that is efficient to use in Lua VM,
- Be well documented library, with good test coverage.
-
-* Macros
-List of macros provided by the library.
-
-** Metadata macros
-Metadata in Fennel is a pretty tough subject, as there's no such thing as metadata in Lua.
-Therefore, the metadata usage in Fennel is more limited compared to Clojure.
-This library provides some facilities for metadata management, which are experimental and should be used with care.
-
-There are several important gotchas about using metadata.
-
-First, note that this works only when used with Fennel, and only when =(require fennel)= works.
-For compiled Lua library this feature is turned off.
-
-Second, try to avoid using metadata with anything else than tables and functions.
-When storing function or table as a key into metatable, its address is used, while when storing string of number, the value is used.
-This, for example, may cause documentation collision, when you've set some variable holding a number value to have certain docstring, and later you've defined another variable with the same value, but different docstring.
-While this isn't a major breakage, it may confuse if someone will explore your code in the REPL with =doc=.
-
-Lastly, note that prior to Fennel 0.7.1 =import-macros= wasn't respecting =--metadata= switch.
-So if you're using Fennel < 0.7.1 this stuff will only work if you use =require-macros= instead of =import-macros=.
-
-*** =when-meta=
-This macros is a wrapper that compiles away if metadata support was not enabled.
-What this effectively means, is that everything that is wrapped with this macro will disappear from the resulting Lua code if metadata is not enabled when compiling with =fennel --compile=.
-
-*** =with-meta=
-Attach metadata to a value.
-
-#+begin_src fennel
- >> (local foo (with-meta (fn [...] (let [[x y z] [...]] (+ x y z)))
- {:fnl/arglist [:x :y :z :...]
- :fnl/docstring "sum first three values"}))
- >> (doc foo)
- (foo x y z ...)
- sum first three values
-#+end_src
-
-When metadata feature is not enabled, returns the value without additional metadata.
-
-*** =meta=
-Get metadata table from object:
-
-#+begin_src fennel
- >> (meta (with-meta {} {:meta "data"}))
- {
- :meta "data"
- }
-#+end_src
-
-** =def= and =defonce=
-=def= is wrappers around =local= which can declare variables inside namespace, and as local at the same time:
-
-#+begin_src fennel
- >> (def ns {})
- >> (def a 10)
- >> a
- 10
- >> (def ns.a 20)
- >> a
- 20
- >> ns.a
- 20
-#+end_src
-
-Both =ns.a= and =a= refer to the same value.
-
-=defonce= ensures that the binding isn't overridden by another =defonce=:
-
-#+begin_src fennel
- >> (defonce ns {})
- >> (defonce ns.a 42)
- >> (defonce ns 10)
- >> ns
- {:a 42}
- >> a
- 42
-#+end_src
-
-Both =def= and =defonce= support literal metadata table as first argument, or a :dynamic keyword, that uses Fennel =var= instead of =local=:
-
-#+begin_src fennel
- >> (def {:dynamic true} a 10)
- >> (set a 20)
- >> a
- 20
- >> (defonce :dynamic b 40)
- >> (set b 42)
- >> b
- 42
-#+end_src
-
-Documentation string can be attached to value via =:doc= keyword.
-However it is not recommended to attach metadata to everything except tables and functions:
-
-#+begin_src fennel
- ;; Bad, may overlap with existing documentation for 299792458, if any
- >> (def {:doc "The speed of light in m/s"} c 299792458)
- >> (doc c)
- c
- The speed of light in m/s
-
- ;; OK
- >> (def {:doc "default connection options"}
- defaults {:port 1234
- :host localhost})
-#+end_src
-
-** =fn*=
-Clojure's =fn= equivalent.
-Returns a function of fixed amount of arguments by doing runtime dispatch based on argument count.
-Capable of producing multi-arity functions:
-
-#+begin_src fennel
- (fn* square "square number" [x] (^ x 2))
-
- (square 9) ;; => 81.0
- (square 1 2) ;; => error
-
- (fn* range
- "Returns increasing sequence of numbers from `lower' to `upper'.
- If `lower' is not provided, sequence starts from zero.
- Accepts optional `step'"
- ([upper] (range 0 upper 1))
- ([lower upper] (range lower upper 1))
- ([lower upper step]
- (let [res []]
- (for [i lower (- upper step) step]
- (table.insert res i))
- res)))
-
- (range 10) ;; => [0 1 2 3 4 5 6 7 8 9]
- (range -10 0) ;; => [-10 -9 -8 -7 -6 -5 -4 -3 -2 -1]
- (range 0 1 0.2) ;; => [0.0 0.2 0.4 0.6 0.8]
-#+end_src
-
-Both variants support up to one arity with =& more=:
-
-#+begin_src fennel
- (fn* vec [& xs] xs)
-
- (vec 1 2 3) ;; => [1 2 3]
-
- (fn* add
- "sum two or more values"
- ([] 0)
- ([a] a)
- ([a b] (+ a b))
- ([a b & more] (add (+ a b) (unpack more))))
-
- (add) ;; => 0
- (add 1) ;; => 1
- (add 1 2) ;; => 3
- (add 1 2 3 4) ;; => 10
-#+end_src
-
-One extra capability of =fn*= supports the same semantic as =def= regarding namespaces:
-
-#+begin_src fennel
- (local ns {})
-
- (fn* ns.plus
- ([] 0)
- ([x] x)
- ([x y] (+ x y))
- ([x y & zs] (apply plus (+ x y) zs)))
-
- ns
-#+end_src
-
-Note, that =plus= is used without =ns= part, e.g. not =ns.plus=.
-If we =require= this code from file in the REPL, we will see that our =ns= has single function =plus=:
-
-#+begin_src fennel
- >> (local ns (require :module))
- >> ns
- {add #<function 0xbada55code>}
-#+end_src
-
-This is possible because =fn*= separates the namespace part from the function name, and creates a =local= variable with the same name as function, then defines the function within lexical scope of =do=, sets =namespace.foo= to it and returns the function object to the outer scope.
-
-#+begin_src fennel
- (local plus
- (do (fn plus [...]
- ;; plus body
- )
- (set ns.plus plus)
- plus))
-#+end_src
-
-See =core.fnl= for more examples.
-
-** =fn+=
-Works similarly to Fennel's =fn=, by creating ordinary function without arity semantics, except does the namespace automation like =fn*=, and has the same order of arguments as the latter:
-
-#+begin_src fennel
- (local ns {})
-
- ;; module & file-local functions
- (fn+ ns.double
- "double the number"
- [x]
- (* x 2))
-
- (fn+ ns.triple
- [x]
- (* x 3))
-
- ;; no namespace, file-local function
- (fn+ quadruple
- [x]
- (* x 4))
-
- ;; anonymous file-local function
- (fn+ [x] (* x 5))
-
- ns
-#+end_src
-
-See =core.fnl= for more examples.
-
-** =if-let= and =when-let=
-When test expression is not =nil= or =false=, evaluates the first body form with the =name= bound to the result of the expressions.
-
-#+begin_src fennel
- (if-let [val (test)]
- (print val)
- :fail)
-#+end_src
-
-Expanded form:
-
-#+begin_src fennel
- (let [tmp (test)]
- (if tmp
- (let [val tmp]
- (print val))
- :fail))
-#+end_src
-
-=when-let= is mostly the same, except doesn't have false branch and accepts any amount of forms:
-
-#+begin_src fennel
- (when-let [val (test)]
- (print val)
- val)
-#+end_src
-
-Expanded form:
-
-#+begin_src fennel
- (let [tmp (test)]
- (if tmp
- (let [val tmp]
- (print val)
- val)))
-#+end_src
-
-** =if-some= and =when-some=
-Much like =if-let= and =when-let=, except tests expression for not being =nil=.
-
-#+begin_src fennel
- (when-some [val (foo)]
- (print (.. "val is not nil: " val))
- val)
-#+end_src
-
-** =into=
-Clojure's =into= function is implemented as macro, because Fennel has no runtime distinction between =[]= and ={}= tables, since Lua also doesn't feature this feature.
-However we can do this at compile time.
-
-#+begin_src fennel
- (into [1 2 3] [4 5 6]) ;; => [1 2 3 4 5 6]
- (into [] {:a 1 :b 2 :c 3 :d 4}) ;; => [["d" 4] ["a" 1] ["b" 2] ["c" 3]]
- (into {} [[:d 4] [:a 1] [:b 2] [:c 3]]) ;; => {:a 1 :b 2 :c 3 :d 4}
- (into {:a 0 :e 5} {:a 1 :b 2 :c 3 :d 4}) ;; => {:a 1 :b 2 :c 3 :d 4 :e 5}
-#+end_src
-
-Because the type check at compile time it will only respect the type when literal representation is used.
-If a variable holding the table, its type is checked at runtime.
-Empty tables default to sequential ones:
-
-#+begin_src fennel
- (local a [])
- (into a {:a 1 :b 2}) ;; => [["b" 2] ["a" 1]]
-
- (local b {})
- (into b {:a 1 :b 2}) ;; => [["b" 2] ["a" 1]]
-#+end_src
-
-However, if target table is not empty, its type can be deduced:
-
-#+begin_src fennel
- (local a {:c 3})
- (into a {:a 1 :b 2}) ;; => {:a 1 :b 2 :c 3}
-
- (local b [1])
- (into b {:a 1 :b 2}) ;; => [1 ["b" 2] ["a" 1]]
-#+end_src
-
-Note that when converting associative table into sequential table order is determined by the =pairs= function.
-Also note that if variable stores the table has both integer key 1, and other associative keys, the type will be the same as of sequential table.
-
-** =defmulti= and =defmethod=
-A bit more simple implementations of Clojure's =defmulti= and =defmethod=.
-=defmulti= macros returns an empty table with =__call= metamethod, that calls dispatching function on its arguments.
-Methods are defined inside =multimethods= table, which is also stored in the metatable.
-
-=defmethod= adds a new method to the metatable of given =multifn=.
-It accepts the multi-fn table as its first argument, the dispatch value as second, and Fennel's arglist followed by the body:
-
-#+begin_src fennel
- (defmulti fac (fn [x] x))
-
- (defmethod fac 0 [_] 1)
- (defmethod fac :default [x] (* x (fac (- x 1))))
-
- (fac 4) ;; => 24
-#+end_src
-
-=:default= is a special method which gets called when no other methods were found for given dispatch value.
-
-
-* Functions
-Here are some important functions from the library.
-Full set can be examined by requiring the module.
-
-** =seq=
-=seq= produces a sequential table from any kind of table in linear time.
-Works mostly like in Clojure, but, since Fennel doesn't have list object, it returns sequential table or =nil=:
-
-#+begin_src fennel
- (seq [1 2 3 4 5]) ;; => [1 2 3 4 5]
- (seq {:a 1 :b 2 :c 3 :d 4})
- ;; => [["d" 4] ["a" 1] ["b" 2] ["c" 3]]
- (seq []) ;; => nil
- (seq {}) ;; => nil
-#+end_src
-
-See =into= on how to transform such sequence back into associative table.
-
-** =first=, =last=, =butlast=, and =rest=
-=first= returns first value of a table.
-It call =seq= on it, so this takes linear time for any kind of table.
-As a consequence, associative tables are supported:
-
-#+begin_src fennel
- (first [1 2 3]) ;; => 1
- (first {:host "localhost" :port 2344 :options {}})
- ;; => ["host" "localhost"]
-#+end_src
-
-=last= returns the last argument from table:
-
-#+begin_src fennel
- (last [1 2 3]) ;; => 3
- (last {:a 1 :b 2}) ;; => [:b 2]
-#+end_src
-
-=butlast= returns everything from the table, except the last item:
-
-#+begin_src fennel
- (butlast [1 2 3]) ;; => [1 2]
-#+end_src
-
-=rest= works the same way, but returns everything except first item of a table.
-
-#+begin_src fennel
- (rest [1 2 3]) ;; => [2 3]
- (rest {:host "localhost" :port 2344 :options {}})
- ;; => [["port" 2344] ["options" {}]]
-#+end_src
-
-All these functions call =seq= on its argument, therefore expect everything to happen in linear time.
-Because of that these functions are expensive, therefore should be avoided when table type is known beforehand, and the table can be manipulated with =.= or =get=.
-
-** =conj= and =cons=
-Append and prepend item to the table.
-Unlike Clojure, =conj=, and =cons= modify table passed to these functions.
-This is done both to avoid copying of whole thing, and because Fennel doesn't have immutability guarantees.
-
-=cons= accepts value as its first argument and table as second, and puts value to the front of the table:
-
-#+begin_src fennel
- (cons 1 [2 3]) ;; => [1 2 3]
-#+end_src
-
-=conj= accepts table as its first argument and any amount of values afterwards.
-It puts values in order given into the table:
-
-#+begin_src fennel
- (conj [] 1 2 3) ;; => [1 2 3]
-#+end_src
-
-It is also possible to add items to associative table:
-
-#+begin_src fennel
- (conj {:a 1} [:b 2]) ;; => {:a 1 :b 2}
- (conj {:a 1} [:b 2] [:a 0]) ;; => {:a 0 :b 2}
-#+end_src
-
-Both functions return the resulting table, so it is possible to nest calls to both of these.
-As an example, here's a classic map function:
-
-#+begin_src fennel
- (fn map [f col]
- (if-some [val (first col)]
- (cons (f val) (map f (rest col)))
- []))
-#+end_src
-
-=col= is not modified by the =map= function described above, but the =[]= table in the =else= branch of =is-some= is eventually modified by the stack of calls to =cons=.
-However this library provides more efficient versions of map, that support arbitrary amount of tables.
-
-** =mapv=
-Mapping function over table.
-In Clojure we have a =seq= abstraction, that allows us to use single =mapv= on both vectors, and hash tables.
-In this library the =seq= function is implemented in a similar way, so you can expect =mapv= to behave similarly to Clojure:
-
-#+begin_src fennel
- (fn cube [x] (* x x x))
- (mapv cube [1 2 3]) ;; => [1 8 27]
-
- (mapv #(* $1 $2) [1 2 3] [1 -1 0]) ;; => [1 -2 0]
-
- (mapv (fn [f-name s-name company position]
- (.. f-name " " s-name " works as " position " at " company))
- ["Bob" "Alice"]
- ["Smith" "Watson"]
- ["Happy Days co." "Coffee With You"]
- ["secretary" "chief officer"])
- ;; => ["Bob Smith works as secretary at Happy Days co."
- ;; "Alice Watson works as chief officer at Coffee With You"]
-
- (mapv (fn [[k v]] [(string.upper k) v]) {:host "localhost" :port 1344})
- ;; => [["HOST" "localhost"] ["PORT" 1344]]
-#+end_src
-
-** =reduce= and =reduce-kv=
-Ordinary reducing functions.
-Work the same as in Clojure, except doesn't yield transducer when only function was passed.
-
-#+begin_src fennel
- (fn add [a b] (+ a b))
- (reduce add [1 2 3 4 5]) ;; => 15
- (reduce add 10 [1 2 3 4 5]) ;; => 25
-#+end_src
-
-=reduce-kv= expects function that accepts 3 arguments and initial value.
-Then it maps function over the associative map, by passing initial value as a first argument, key as second argument, and value as third argument.
-
-#+begin_src fennel
- (reduce-kv (fn [acc key val]
- (if (or (= key :a) (= key :c))
- (+ acc val) acc))
- 0
- {:a 10 :b -20 :c 10})
- ;; => 20
-#+end_src
-
-** Predicate functions
-Set of functions, that are small but useful with =mapv= or =reduce=.
-These are commonly used so it makes sense to have that, without defining via anonymous function or =#= shorthand every time.
-
-- =map?= - check if table is an associative table.
- Returns =false= for empty table.
-- =seq?= - check if table is a sequential table
- Returns =false= for empty table.
-
-Other predicates are self-explanatory:
-
-- =assoc?=
-- =boolean?=
-- =double?=
-- =empty?=
-- =even?=
-- =false?=
-- =int?=
-- =neg?=
-- =nil?=
-- =odd?=
-- =pos?=
-- =string?=
-- =true?=
-- =zero?=
-
-** =eq=
-Deep compare values.
-If given two tables, recursively calls =eq= on each field until one of the tables exhausted.
-Other values are compared with default equality operator.
-
-** =comp=
-Compose functions into one function.
-
-#+begin_src fennel
- (fn square [x] (^ x 2))
- (fn inc [x] (+ x 1))
-
- ((comp square inc) 5) ;; => 36
-#+end_src
-
-# LocalWords: Luajit VM arity runtime multi Cljlib fn mapv kv REPL
-# LocalWords: namespaced namespace eq metatable Lua defonce arglist
-# LocalWords: namespaces defmulti defmethod metamethod butlast
-# LocalWords: prepend LocalWords docstring
-
-** =every?= and =not-any?=
-=every?= checks if predicate is true for every item in the table.
-=not-any?= checks if predicate is false foe every item in the table.
-
-#+begin_src fennel
- >> (every? pos-int? [1 2 3 4])
- true
- >> (not-any? pos-int? [-1 -2 -3 4.2])
- true
-#+end_src
+Documentation is autogenerated with [[https://gitlab.com/andreyorst/fenneldoc][Fenneldoc]] and can be found [[https://gitlab.com/andreyorst/fennel-cljlib/-/tree/master/doc][here]].
diff --git a/cljlib-macros.fnl b/cljlib-macros.fnl
index e49713f..e62c185 100644
--- a/cljlib-macros.fnl
+++ b/cljlib-macros.fnl
@@ -74,18 +74,26 @@ Strings are transformed into a sequence of letters."
(fn gen-arglist-doc [args]
(if (list? (. args 1))
(let [arglist []
- open (if (> (length args) 1) "\n [" "")
- close (if (= open "") "" "]")]
+ newline? (if (> (length args) 1) "\n (" "(")]
(each [i v (ipairs args)]
- (table.insert
- arglist
- (.. open (table.concat (gen-arglist-doc v) " ") close)))
+ (let [arglist-doc (gen-arglist-doc v)]
+ (when (next arglist-doc)
+ (table.insert
+ arglist
+ (.. newline? (table.concat arglist-doc " ") ")")))))
arglist)
(sequence? (. args 1))
- (let [arglist []]
- (each [_ v (ipairs (. args 1))]
- (table.insert arglist (tostring v)))
+ (let [arglist []
+ args (. args 1)
+ len (length args)]
+ (each [i v (ipairs args)]
+ (table.insert arglist
+ (match i
+ (1 ? (= len 1)) (.. "[" (tostring v) "]")
+ 1 (.. "[" (tostring v))
+ len (.. (tostring v) "]")
+ _ (tostring v))))
arglist)))
(fn multisym->sym [s]
diff --git a/cljlib.fnl b/cljlib.fnl
index 24936f1..f25e321 100644
--- a/cljlib.fnl
+++ b/cljlib.fnl
@@ -1,4 +1,7 @@
-(local core {})
+(local core {:_DESCRIPTION "Fennel-cljlib - functions from Clojure's core.clj implemented on top of Fennel."
+ :_VERSION "0.1.0"
+ :_COPYRIGHT "Copyright (C) 2020 Andrey Orst"})
+
(local insert table.insert)
(local unpack (or table.unpack _G.unpack))
@@ -144,9 +147,9 @@ arguments to `args`."
(fn* core.seq
"Create sequential table.
Transforms original table to sequential table of key value pairs
-stored as sequential tables in linear time. If `tbl` is an
+stored as sequential tables in linear time. If `col` is an
associative table, returns `[[key1 value1] ... [keyN valueN]]` table.
-If `tbl` is sequential table, returns its shallow copy."
+If `col` is sequential table, returns its shallow copy."
[col]
(let [res (empty [])]
(match (type col)
@@ -169,25 +172,25 @@ If `tbl` is sequential table, returns its shallow copy."
(fn* core.first
"Return first element of a table. Calls `seq` on its argument."
- [tbl]
- (when-some [tbl (seq tbl)]
- (. tbl 1)))
+ [col]
+ (when-some [col (seq col)]
+ (. col 1)))
(fn* core.rest
"Returns table of all elements of a table but the first one. Calls
`seq` on its argument."
- [tbl]
- (if-some [tbl (seq tbl)]
- (vector (unpack tbl 2))
+ [col]
+ (if-some [col (seq col)]
+ (vector (unpack col 2))
(empty [])))
(fn* core.last
"Returns the last element of a table. Calls `seq` on its argument."
- [tbl]
- (when-some [tbl (seq tbl)]
- (var (i v) (next tbl))
+ [col]
+ (when-some [col (seq col)]
+ (var (i v) (next col))
(while i
- (local (_i _v) (next tbl i))
+ (local (_i _v) (next col i))
(if _i (set v _v))
(set i _i))
v))
@@ -195,12 +198,11 @@ If `tbl` is sequential table, returns its shallow copy."
(fn* core.butlast
"Returns everything but the last element of a table as a new
table. Calls `seq` on its argument."
- [tbl]
- (when-some [tbl (seq tbl)]
- (table.remove tbl (length tbl))
- (when (not (empty? tbl))
- tbl)))
-
+ [col]
+ (when-some [col (seq col)]
+ (table.remove col (length col))
+ (when (not (empty? col))
+ col)))
(fn* core.conj
"Insert `x` as a last element of indexed table `tbl`. Modifies `tbl`"
@@ -243,10 +245,7 @@ If `tbl` is sequential table, returns its shallow copy."
(apply concat (concat x y) xs)))
(fn* core.reduce
- "Reduce indexed table using function `f` and optional initial value `val`.
-
-([f table])
-([f val table])
+ "Reduce collection `col` using function `f` and optional initial value `val`.
`f` should be a function of 2 arguments. If val is not supplied,
returns the result of applying f to the first 2 items in coll, then
@@ -256,18 +255,18 @@ result of calling f with no arguments. If coll has only 1 item, it is
returned and f is not called. If val is supplied, returns the result
of applying f to val and the first item in coll, then applying f to
that result and the 2nd item, etc. If coll contains no items, returns
-val and f is not called."
- ([f tbl]
- (let [tbl (or (seq tbl) (empty []))]
- (match (length tbl)
+val and f is not called. Calls `seq` on `col`."
+ ([f col]
+ (let [col (or (seq col) (empty []))]
+ (match (length col)
0 (f)
- 1 (. tbl 1)
- 2 (f (. tbl 1) (. tbl 2))
- _ (let [[a b & rest] tbl]
+ 1 (. col 1)
+ 2 (f (. col 1) (. col 2))
+ _ (let [[a b & rest] col]
(reduce f (f a b) rest)))))
- ([f val tbl]
- (let [tbl (or (seq tbl) (empty []))]
- (let [[x & xs] tbl]
+ ([f val col]
+ (let [col (or (seq col) (empty []))]
+ (let [[x & xs] col]
(if (nil? x)
val
(reduce f (f val x) xs))))))
@@ -275,22 +274,20 @@ val and f is not called."
(fn* core.reduce-kv
"Reduces an associative table using function `f` and initial value `val`.
-([f val table])
-
`f` should be a function of 3 arguments. Returns the result of
-applying `f` to `val`, the first key and the first value in coll, then
-applying `f` to that result and the 2nd key and value, etc. If coll
-contains no entries, returns `val` and `f` is not called. Note that
-reduce-kv is supported on vectors, where the keys will be the
-ordinals."
- [f val tbl]
+applying `f` to `val`, the first key and the first value in `coll`,
+then applying `f` to that result and the 2nd key and value, etc. If
+`coll` contains no entries, returns `val` and `f` is not called. Note
+that reduce-kv is supported on sequential tables and strings, where
+the keys will be the ordinals."
+ [f val col]
(var res val)
- (each [_ [k v] (pairs (or (seq tbl) (empty [])))]
+ (each [_ [k v] (pairs (or (seq col) (empty [])))]
(set res (f res k v)))
res)
(fn* core.mapv
- "Maps function `f` over one or more tables.
+ "Maps function `f` over one or more collections.
Accepts arbitrary amount of tables, calls `seq` on each of it.
Function `f` must take the same amount of parameters as the amount of
@@ -298,76 +295,76 @@ tables passed to `mapv`. Applies `f` over first value of each
table. Then applies `f` to second value of each table. Continues until
any of the tables is exhausted. All remaining values are
ignored. Returns a table of results."
- ([f tbl]
+ ([f col]
(local res (empty []))
- (each [_ v (ipairs (or (seq tbl) (empty [])))]
+ (each [_ v (ipairs (or (seq col) (empty [])))]
(when-some [tmp (f v)]
(insert res tmp)))
res)
- ([f t1 t2]
+ ([f col1 col2]
(let [res (empty [])
- t1 (or (seq t1) (empty []))
- t2 (or (seq t2) (empty []))]
- (var (i1 v1) (next t1))
- (var (i2 v2) (next t2))
+ col1 (or (seq col1) (empty []))
+ col2 (or (seq col2) (empty []))]
+ (var (i1 v1) (next col1))
+ (var (i2 v2) (next col2))
(while (and i1 i2)
(when-some [tmp (f v1 v2)]
(insert res tmp))
- (set (i1 v1) (next t1 i1))
- (set (i2 v2) (next t2 i2)))
+ (set (i1 v1) (next col1 i1))
+ (set (i2 v2) (next col2 i2)))
res))
- ([f t1 t2 t3]
+ ([f col1 col2 col3]
(let [res (empty [])
- t1 (or (seq t1) (empty []))
- t2 (or (seq t2) (empty []))
- t3 (or (seq t3) (empty []))]
- (var (i1 v1) (next t1))
- (var (i2 v2) (next t2))
- (var (i3 v3) (next t3))
+ col1 (or (seq col1) (empty []))
+ col2 (or (seq col2) (empty []))
+ col3 (or (seq col3) (empty []))]
+ (var (i1 v1) (next col1))
+ (var (i2 v2) (next col2))
+ (var (i3 v3) (next col3))
(while (and i1 i2 i3)
(when-some [tmp (f v1 v2 v3)]
(insert res tmp))
- (set (i1 v1) (next t1 i1))
- (set (i2 v2) (next t2 i2))
- (set (i3 v3) (next t3 i3)))
+ (set (i1 v1) (next col1 i1))
+ (set (i2 v2) (next col2 i2))
+ (set (i3 v3) (next col3 i3)))
res))
- ([f t1 t2 t3 & tbls]
- (let [step (fn step [tbls]
- (if (->> tbls
+ ([f col1 col2 col3 & cols]
+ (let [step (fn step [cols]
+ (if (->> cols
(mapv #(not= (next $) nil))
(reduce #(and $1 $2)))
- (cons (mapv #(. (or (seq $) (empty [])) 1) tbls) (step (mapv #(do [(unpack $ 2)]) tbls)))
+ (cons (mapv #(. (or (seq $) (empty [])) 1) cols) (step (mapv #(do [(unpack $ 2)]) cols)))
(empty [])))
res (empty [])]
- (each [_ v (ipairs (step (consj tbls t3 t2 t1)))]
+ (each [_ v (ipairs (step (consj cols col3 col2 col1)))]
(when-some [tmp (apply f v)]
(insert res tmp)))
res)))
-(fn* core.filter [pred tbl]
- (if-let [tbl (seq tbl)]
- (let [f (. tbl 1)
- r [(unpack tbl 2)]]
+(fn* core.filter
+ "Returns a sequential table of the items in `col` for which `pred`
+ returns logical true."
+ [pred col]
+ (if-let [col (seq col)]
+ (let [f (. col 1)
+ r [(unpack col 2)]]
(if (pred f)
(cons f (filter pred r))
(filter pred r)))
(empty [])))
-(fn kvseq [tbl]
+(fn* core.kvseq
"Transforms any table kind to key-value sequence."
+ [tbl]
(let [res (empty [])]
(each [k v (pairs tbl)]
(insert res [k v]))
res))
-
-
-(fn* core.identity
- "Returns its argument."
- [x]
- x)
+(fn* core.identity "Returns its argument." [x] x)
(fn* core.comp
+ "Compose functions."
([] identity)
([f] f)
([f g]
@@ -481,6 +478,7 @@ found in the table."
res))
(fn* core.remove-method
+ "Remove method from `multifn` for given `dispatch-val`."
[multifn dispatch-val]
(tset (. (getmetatable multifn) :multimethods) dispatch-val nil)
multifn)
@@ -615,12 +613,13 @@ that would apply to that value, or `nil` if none apply and no default."
([x y & xs]
(reduce #(and $1 $2) (eq x y) (mapv #(eq x $) xs))))
-(fn* core.memoize [f]
+(fn* core.memoize
"Returns a memoized version of a referentially transparent function.
The memoized version of the function keeps a cache of the mapping from
arguments to results and, when calls with the same arguments are
repeated often, has higher performance at the expense of higher memory
use."
+ [f]
(let [memo (setmetatable {} {:__index
(fn [tbl key]
(each [k v (pairs tbl)]
diff --git a/doc/0.1.0/cljlib-macros.md b/doc/0.1.0/cljlib-macros.md
new file mode 100644
index 0000000..d99dad6
--- /dev/null
+++ b/doc/0.1.0/cljlib-macros.md
@@ -0,0 +1,288 @@
+# Cljlib-macros.fnl
+Macro module for Fennel Cljlib.
+
+## Metadata macros
+Metadata in Fennel is a pretty tough subject, as there's no such thing as metadata in Lua.
+Therefore, the metadata usage in Fennel is more limited compared to Clojure.
+This library provides some facilities for metadata management, which are experimental and should be used with care.
+
+There are several important gotchas about using metadata.
+
+First, note that this works only when used with Fennel, and only when `(require fennel)` works.
+For compiled Lua library this feature is turned off.
+
+Second, try to avoid using metadata with anything else than tables and functions.
+When storing function or table as a key into metatable, its address is used, while when storing string of number, the value is used.
+This, for example, may cause documentation collision, when you've set some variable holding a number value to have certain docstring, and later you've defined another variable with the same value, but different docstring.
+While this isn't a major breakage, it may confuse if someone will explore your code in the REPL with `doc`.
+
+Lastly, note that prior to Fennel 0.7.1 `import-macros` wasn't respecting `--metadata` switch.
+So if you're using Fennel < 0.7.1 this stuff will only work if you use `require-macros` instead of `import-macros`.
+
+
+### `when-meta`
+This macros is a wrapper that compiles away if metadata support was not enabled.
+What this effectively means, is that everything that is wrapped with this macro will disappear from the resulting Lua code if metadata is not enabled when compiling with `fennel --compile`.
+
+
+### `with-meta`
+Attach metadata to a value.
+
+ >> (local foo (with-meta (fn [...] (let [[x y z] [...]] (+ x y z)))
+ {:fnl/arglist [:x :y :z :...]
+ :fnl/docstring "sum first three values"}))
+ >> (doc foo)
+ (foo x y z ...)
+ sum first three values
+
+When metadata feature is not enabled, returns the value without additional metadata.
+
+
+### `meta`
+Get metadata table from object:
+
+ >> (meta (with-meta {} {:meta "data"}))
+ {
+ :meta "data"
+ }
+
+
+## `def` and `defonce`
+`def` is wrappers around `local` which can declare variables inside namespace, and as local at the same time:
+
+ >> (def ns {})
+ >> (def a 10)
+ >> a
+ 10
+ >> (def ns.a 20)
+ >> a
+ 20
+ >> ns.a
+ 20
+
+Both `ns.a` and `a` refer to the same value.
+
+`defonce` ensures that the binding isn't overridden by another `defonce`:
+
+ >> (defonce ns {})
+ >> (defonce ns.a 42)
+ >> (defonce ns 10)
+ >> ns
+ {:a 42}
+ >> a
+ 42
+
+Both `def` and `defonce` support literal metadata table as first argument, or a :dynamic keyword, that uses Fennel `var` instead of `local`:
+
+ >> (def {:dynamic true} a 10)
+ >> (set a 20)
+ >> a
+ 20
+ >> (defonce :dynamic b 40)
+ >> (set b 42)
+ >> b
+ 42
+
+Documentation string can be attached to value via `:doc` keyword.
+However it is not recommended to attach metadata to everything except tables and functions:
+
+ ;; Bad, may overlap with existing documentation for 299792458, if any
+ >> (def {:doc "The speed of light in m/s"} c 299792458)
+ >> (doc c)
+ c
+ The speed of light in m/s
+
+ ;; OK
+ >> (def {:doc "default connection options"}
+ defaults {:port 1234
+ :host localhost})
+
+
+## `fn*`
+Clojure's `fn` equivalent.
+Returns a function of fixed amount of arguments by doing runtime dispatch based on argument count.
+Capable of producing multi-arity functions:
+
+ (fn* square "square number" [x] (^ x 2))
+
+ (square 9) ;; => 81.0
+ (square 1 2) ;; => error
+
+ (fn* range
+ "Returns increasing sequence of numbers from `lower' to `upper'.
+ If `lower' is not provided, sequence starts from zero.
+ Accepts optional `step'"
+ ([upper] (range 0 upper 1))
+ ([lower upper] (range lower upper 1))
+ ([lower upper step]
+ (let [res []]
+ (for [i lower (- upper step) step]
+ (table.insert res i))
+ res)))
+
+ (range 10) ;; => [0 1 2 3 4 5 6 7 8 9]
+ (range -10 0) ;; => [-10 -9 -8 -7 -6 -5 -4 -3 -2 -1]
+ (range 0 1 0.2) ;; => [0.0 0.2 0.4 0.6 0.8]
+
+Both variants support up to one arity with `& more`:
+
+ (fn* vec [& xs] xs)
+
+ (vec 1 2 3) ;; => [1 2 3]
+
+ (fn* add
+ "sum two or more values"
+ ([] 0)
+ ([a] a)
+ ([a b] (+ a b))
+ ([a b & more] (add (+ a b) (unpack more))))
+
+ (add) ;; => 0
+ (add 1) ;; => 1
+ (add 1 2) ;; => 3
+ (add 1 2 3 4) ;; => 10
+
+One extra capability of `fn*` supports the same semantic as `def` regarding namespaces:
+
+ (local ns {})
+
+ (fn* ns.plus
+ ([] 0)
+ ([x] x)
+ ([x y] (+ x y))
+ ([x y & zs] (apply plus (+ x y) zs)))
+
+ ns
+
+Note, that `plus` is used without `ns` part, e.g. not `ns.plus`.
+If we `require` this code from file in the REPL, we will see that our `ns` has single function `plus`:
+
+ >> (local ns (require :module))
+ >> ns
+ {add #<function 0xbada55code>}
+
+This is possible because `fn*` separates the namespace part from the function name, and creates a `local` variable with the same name as function, then defines the function within lexical scope of `do`, sets `namespace.foo` to it and returns the function object to the outer scope.
+
+ (local plus
+ (do (fn plus [...]
+ ;; plus body
+ )
+ (set ns.plus plus)
+ plus))
+
+See `core.fnl` for more examples.
+
+
+## `fn+`
+Works similarly to Fennel's `fn`, by creating ordinary function without arity semantics, except does the namespace automation like `fn*`, and has the same order of arguments as the latter:
+
+ (local ns {})
+
+ ;; module & file-local functions
+ (fn+ ns.double
+ "double the number"
+ [x]
+ (* x 2))
+
+ (fn+ ns.triple
+ [x]
+ (* x 3))
+
+ ;; no namespace, file-local function
+ (fn+ quadruple
+ [x]
+ (* x 4))
+
+ ;; anonymous file-local function
+ (fn+ [x] (* x 5))
+
+ ns
+
+See `core.fnl` for more examples.
+
+
+## `if-let` and `when-let`
+When test expression is not `nil` or `false`, evaluates the first body form with the `name` bound to the result of the expressions.
+
+ (if-let [val (test)]
+ (print val)
+ :fail)
+
+Expanded form:
+
+ (let [tmp (test)]
+ (if tmp
+ (let [val tmp]
+ (print val))
+ :fail))
+
+`when-let` is mostly the same, except doesn't have false branch and accepts any amount of forms:
+
+ (when-let [val (test)]
+ (print val)
+ val)
+
+Expanded form:
+
+ (let [tmp (test)]
+ (if tmp
+ (let [val tmp]
+ (print val)
+ val)))
+
+
+## `if-some` and `when-some`
+Much like `if-let` and `when-let`, except tests expression for not being `nil`.
+
+ (when-some [val (foo)]
+ (print (.. "val is not nil: " val))
+ val)
+
+
+## `into`
+Clojure's `into` function is implemented as macro, because Fennel has no runtime distinction between `[]` and `{}` tables, since Lua also doesn't feature this feature.
+However we can do this at compile time.
+
+ (into [1 2 3] [4 5 6]) ;; => [1 2 3 4 5 6]
+ (into [] {:a 1 :b 2 :c 3 :d 4}) ;; => [["d" 4] ["a" 1] ["b" 2] ["c" 3]]
+ (into {} [[:d 4] [:a 1] [:b 2] [:c 3]]) ;; => {:a 1 :b 2 :c 3 :d 4}
+ (into {:a 0 :e 5} {:a 1 :b 2 :c 3 :d 4}) ;; => {:a 1 :b 2 :c 3 :d 4 :e 5}
+
+Because the type check at compile time it will only respect the type when literal representation is used.
+If a variable holding the table, its type is checked at runtime.
+Empty tables default to sequential ones:
+
+ (local a [])
+ (into a {:a 1 :b 2}) ;; => [["b" 2] ["a" 1]]
+
+ (local b {})
+ (into b {:a 1 :b 2}) ;; => [["b" 2] ["a" 1]]
+
+However, if target table is not empty, its type can be deduced:
+
+ (local a {:c 3})
+ (into a {:a 1 :b 2}) ;; => {:a 1 :b 2 :c 3}
+
+ (local b [1])
+ (into b {:a 1 :b 2}) ;; => [1 ["b" 2] ["a" 1]]
+
+Note that when converting associative table into sequential table order is determined by the `pairs` function.
+Also note that if variable stores the table has both integer key 1, and other associative keys, the type will be the same as of sequential table.
+
+
+## `defmulti` and `defmethod`
+A bit more simple implementations of Clojure's `defmulti` and `defmethod`.
+`defmulti` macros returns an empty table with `__call` metamethod, that calls dispatching function on its arguments.
+Methods are defined inside `multimethods` table, which is also stored in the metatable.
+
+`defmethod` adds a new method to the metatable of given `multifn`.
+It accepts the multi-fn table as its first argument, the dispatch value as second, and Fennel's arglist followed by the body:
+
+ (defmulti fac (fn [x] x))
+
+ (defmethod fac 0 [_] 1)
+ (defmethod fac :default [x] (* x (fac (- x 1))))
+
+ (fac 4) ;; => 24
+
+`:default` is a special method which gets called when no other methods were found for given dispatch value.
diff --git a/doc/0.1.0/cljlib.md b/doc/0.1.0/cljlib.md
new file mode 100644
index 0000000..1226591
--- /dev/null
+++ b/doc/0.1.0/cljlib.md
@@ -0,0 +1,674 @@
+# Cljlib.fnl
+Fennel-cljlib - functions from Clojure's core.clj implemented on top of Fennel.
+
+Documentation for version: 0.1.0
+
+## `add`
+Function signature:
+
+```
+(add
+ ([a])
+ ([a b])
+ ([a b c])
+ ([a b c d])
+ ([a b c d & rest]))
+```
+
+Sum arbitrary amount of numbers.
+
+## `apply`
+Function signature:
+
+```
+(apply
+ ([f args])
+ ([f a args])
+ ([f a b args])
+ ([f a b c args])
+ ([f a b c d & args]))
+```
+
+Apply `f` to the argument list formed by prepending intervening
+arguments to `args`.
+
+## `assoc`
+Function signature:
+
+```
+(assoc
+ ([tbl k v])
+ ([tbl k v & kvs]))
+```
+
+Associate key `k` with value `v` in `tbl`.
+
+## `boolean?`
+Function signature:
+
+```
+(boolean? [x])
+```
+
+Test if `x` is a Boolean
+
+## `butlast`
+Function signature:
+
+```
+(butlast [col])
+```
+
+Returns everything but the last element of a table as a new
+ table. Calls `seq` on its argument.
+
+## `comp`
+Function signature:
+
+```
+(comp
+ ([f])
+ ([f g])
+ ([f g & fs]))
+```
+
+Compose functions.
+
+## `complement`
+Function signature:
+
+```
+(complement [f])
+```
+
+Takes a function `f` and returns the function that takes the same
+amount of arguments as `f`, has the same effect, and returns the
+oppisite truth value.
+
+## `concat`
+Function signature:
+
+```
+(concat
+ ([x])
+ ([x y])
+ ([x y & xs]))
+```
+
+Concatenate tables.
+
+## `conj`
+Function signature:
+
+```
+(conj
+ ([tbl])
+ ([tbl x])
+ ([tbl x & xs]))
+```
+
+Insert `x` as a last element of indexed table `tbl`. Modifies `tbl`
+
+## `cons`
+Function signature:
+
+```
+(cons [x tbl])
+```
+
+Insert `x` to `tbl` at the front. Modifies `tbl`.
+
+## `constantly`
+Function signature:
+
+```
+(constantly [x])
+```
+
+Returns a function that takes any number of arguments and returns `x`.
+
+## `dec`
+Function signature:
+
+```
+(dec [x])
+```
+
+Decrease number by one
+
+## `div`
+Function signature:
+
+```
+(div
+ ([a])
+ ([a b])
+ ([a b c])
+ ([a b c d])
+ ([a b c d & rest]))
+```
+
+Divide arbitrary amount of numbers.
+
+## `double?`
+Function signature:
+
+```
+(double? [x])
+```
+
+Test if `x` is a number with floating point data.
+
+## `empty?`
+Function signature:
+
+```
+(empty? [x])
+```
+
+Check if collection is empty.
+
+## `eq`
+Function signature:
+
+```
+(eq
+ ([x])
+ ([x y])
+ ([x y & xs]))
+```
+
+Deep compare values.
+
+## `even?`
+Function signature:
+
+```
+(even? [x])
+```
+
+Test if value is even.
+
+## `every?`
+Function signature:
+
+```
+(every? [pred tbl])
+```
+
+Test if every item in `tbl` satisfies the `pred`.
+
+## `false?`
+Function signature:
+
+```
+(false? [x])
+```
+
+Test if `x` is `false`
+
+## `filter`
+Function signature:
+
+```
+(filter [pred col])
+```
+
+Returns a sequential table of the items in `col` for which `pred`
+ returns logical true.
+
+## `first`
+Function signature:
+
+```
+(first [col])
+```
+
+Return first element of a table. Calls `seq` on its argument.
+
+## `ge`
+Function signature:
+
+```
+(ge
+ ([x])
+ ([x y])
+ ([x y & more]))
+```
+
+Returns true if nums are in monotonically non-increasing order
+
+## `get`
+Function signature:
+
+```
+(get
+ ([tbl key])
+ ([tbl key not-found]))
+```
+
+Get value from the table by accessing it with a `key`.
+Accepts additional `not-found` as a marker to return if value wasn't
+found in the table.
+
+## `get-in`
+Function signature:
+
+```
+(get-in
+ ([tbl keys])
+ ([tbl keys not-found]))
+```
+
+Get value from nested set of tables by providing key sequence.
+Accepts additional `not-found` as a marker to return if value wasn't
+found in the table.
+
+## `get-method`
+Function signature:
+
+```
+(get-method [multifn dispatch-val])
+```
+
+Given a multimethod and a dispatch value, returns the dispatch `fn`
+that would apply to that value, or `nil` if none apply and no default.
+
+## `gt`
+Function signature:
+
+```
+(gt
+ ([x])
+ ([x y])
+ ([x y & more]))
+```
+
+Returns true if nums are in monotonically increasing order
+
+## `hash-map`
+Function signature:
+
+```
+(hash-map
+ ([& kvs]))
+```
+
+Create associative table from keys and values
+
+## `identity`
+Function signature:
+
+```
+(identity [x])
+```
+
+Returns its argument.
+
+## `inc`
+Function signature:
+
+```
+(inc [x])
+```
+
+Increase number by one
+
+## `int?`
+Function signature:
+
+```
+(int? [x])
+```
+
+Test if `x` is a number without floating point data.
+
+## `kvseq`
+Function signature:
+
+```
+(kvseq [tbl])
+```
+
+Transforms any table kind to key-value sequence.
+
+## `last`
+Function signature:
+
+```
+(last [col])
+```
+
+Returns the last element of a table. Calls `seq` on its argument.
+
+## `le`
+Function signature:
+
+```
+(le
+ ([x])
+ ([x y])
+ ([x y & more]))
+```
+
+Returns true if nums are in monotonically non-decreasing order
+
+## `lt`
+Function signature:
+
+```
+(lt
+ ([x])
+ ([x y])
+ ([x y & more]))
+```
+
+Returns true if nums are in monotonically decreasing order
+
+## `map?`
+Function signature:
+
+```
+(map? [tbl])
+```
+
+Check whether `tbl` is an associative table.
+
+## `mapv`
+Function signature:
+
+```
+(mapv
+ ([f col])
+ ([f col1 col2])
+ ([f col1 col2 col3])
+ ([f col1 col2 col3 & cols]))
+```
+
+Maps function `f` over one or more collections.
+
+Accepts arbitrary amount of tables, calls `seq` on each of it.
+Function `f` must take the same amount of parameters as the amount of
+tables passed to `mapv`. Applies `f` over first value of each
+table. Then applies `f` to second value of each table. Continues until
+any of the tables is exhausted. All remaining values are
+ignored. Returns a table of results.
+
+## `memoize`
+Function signature:
+
+```
+(memoize [f])
+```
+
+Returns a memoized version of a referentially transparent function.
+The memoized version of the function keeps a cache of the mapping from
+arguments to results and, when calls with the same arguments are
+repeated often, has higher performance at the expense of higher memory
+use.
+
+## `methods`
+Function signature:
+
+```
+(methods [multifn])
+```
+
+Given a multimethod, returns a map of dispatch values -> dispatch fns
+
+## `mul`
+Function signature:
+
+```
+(mul
+ ([a])
+ ([a b])
+ ([a b c])
+ ([a b c d])
+ ([a b c d & rest]))
+```
+
+Multiply arbitrary amount of numbers.
+
+## `neg-int?`
+Function signature:
+
+```
+(neg-int? [x])
+```
+
+Test if `x` is a negetive integer.
+
+## `neg?`
+Function signature:
+
+```
+(neg? [x])
+```
+
+Test if `x` is less than zero.
+
+## `nil?`
+Function signature:
+
+```
+(nil?
+ ([x]))
+```
+
+Test if value is nil.
+
+## `not-any?`
+Function signature:
+
+```
+(not-any? pred tbl)
+```
+
+Test if no item in `tbl` satisfy the `pred`.
+
+## `not-empty`
+Function signature:
+
+```
+(not-empty [x])
+```
+
+If `x` is empty, returns `nil`, otherwise `x`.
+
+## `odd?`
+Function signature:
+
+```
+(odd? [x])
+```
+
+Test if value is odd.
+
+## `pos-int?`
+Function signature:
+
+```
+(pos-int? [x])
+```
+
+Test if `x` is a positive integer.
+
+## `pos?`
+Function signature:
+
+```
+(pos? [x])
+```
+
+Test if `x` is greater than zero.
+
+## `range`
+Function signature:
+
+```
+(range
+ ([upper])
+ ([lower upper])
+ ([lower upper step]))
+```
+
+return range of of numbers from `lower` to `upper` with optional `step`.
+
+## `reduce`
+Function signature:
+
+```
+(reduce
+ ([f col])
+ ([f val col]))
+```
+
+Reduce collection `col` using function `f` and optional initial value `val`.
+
+`f` should be a function of 2 arguments. If val is not supplied,
+returns the result of applying f to the first 2 items in coll, then
+applying f to that result and the 3rd item, etc. If coll contains no
+items, f must accept no arguments as well, and reduce returns the
+result of calling f with no arguments. If coll has only 1 item, it is
+returned and f is not called. If val is supplied, returns the result
+of applying f to val and the first item in coll, then applying f to
+that result and the 2nd item, etc. If coll contains no items, returns
+val and f is not called. Calls `seq` on `col`.
+
+## `reduce-kv`
+Function signature:
+
+```
+(reduce-kv [f val col])
+```
+
+Reduces an associative table using function `f` and initial value `val`.
+
+`f` should be a function of 3 arguments. Returns the result of
+applying `f` to `val`, the first key and the first value in `coll`,
+then applying `f` to that result and the 2nd key and value, etc. If
+`coll` contains no entries, returns `val` and `f` is not called. Note
+that reduce-kv is supported on sequential tables and strings, where
+the keys will be the ordinals.
+
+## `remove-all-methods`
+Function signature:
+
+```
+(remove-all-methods [multifn])
+```
+
+Removes all of the methods of multimethod
+
+## `remove-method`
+Function signature:
+
+```
+(remove-method [multifn dispatch-val])
+```
+
+Remove method from `multifn` for given `dispatch-val`.
+
+## `rest`
+Function signature:
+
+```
+(rest [seq])
+```
+
+Returns table of all elements of a table but the first one. Calls
+ `seq` on its argument.
+
+## `reverse`
+Function signature:
+
+```
+(reverse [tbl])
+```
+
+Returns table with same items as in `tbl` but in reverse order.
+
+## `seq`
+Function signature:
+
+```
+(seq [col])
+```
+
+Create sequential table.
+Transforms original table to sequential table of key value pairs
+stored as sequential tables in linear time. If `col` is an
+associative table, returns `[[key1 value1] ... [keyN valueN]]` table.
+If `col` is sequential table, returns its shallow copy.
+
+## `seq?`
+Function signature:
+
+```
+(seq? [tbl])
+```
+
+Check whether `tbl` is an sequential table.
+
+## `some`
+Function signature:
+
+```
+(some [pred tbl])
+```
+
+Test if any item in `tbl` satisfies the `pred`.
+
+## `string?`
+Function signature:
+
+```
+(string? [x])
+```
+
+Test if `x` is a string.
+
+## `sub`
+Function signature:
+
+```
+(sub
+ ([a])
+ ([a b])
+ ([a b c])
+ ([a b c d])
+ ([a b c d & rest]))
+```
+
+Subtract arbitrary amount of numbers.
+
+## `true?`
+Function signature:
+
+```
+(true? [x])
+```
+
+Test if `x` is `true`
+
+## `vector`
+Function signature:
+
+```
+(vector [& args])
+```
+
+Constructs sequential table out of it's arguments.
+
+## `zero?`
+Function signature:
+
+```
+(zero? [x])
+```
+
+Test if value is zero.
+
+
+<!-- Generated with Fenneldoc 0.0.1--> \ No newline at end of file
diff --git a/tests/fn.fnl b/tests/fn.fnl
index e0af7cb..aa86b12 100644
--- a/tests/fn.fnl
+++ b/tests/fn.fnl
@@ -7,21 +7,21 @@
"docstring"
[x] x)
(assert-eq (meta f) (when-meta {:fnl/docstring "docstring"
- :fnl/arglist ["x"]}))
+ :fnl/arglist ["[x]"]}))
(fn* f
"docstring"
([x] x))
(assert-eq (meta f) (when-meta {:fnl/docstring "docstring"
- :fnl/arglist ["x"]}))
+ :fnl/arglist ["([x])"]}))
(fn* f
"docstring"
([x] x)
([x y] (+ x y)))
(assert-eq (meta f) (when-meta {:fnl/docstring "docstring"
- :fnl/arglist ["\n [x]"
- "\n [x y]"]}))
+ :fnl/arglist ["\n ([x])"
+ "\n ([x y])"]}))
(fn* f
"docstring"
@@ -29,9 +29,9 @@
([x y] (+ x y))
([x y & z] (+ x y)))
(assert-eq (meta f) (when-meta {:fnl/docstring "docstring"
- :fnl/arglist ["\n [x]"
- "\n [x y]"
- "\n [x y & z]"]}))))
+ :fnl/arglist ["\n ([x])"
+ "\n ([x y])"
+ "\n ([x y & z])"]}))))
(deftest fn+
(testing "fn+ meta"