diff options
Diffstat (limited to 'doc')
| -rw-r--r-- | doc/cljlib.md | 77 | ||||
| -rw-r--r-- | doc/macros.md | 207 | ||||
| -rw-r--r-- | doc/tests/test.md | 41 |
3 files changed, 174 insertions, 151 deletions
diff --git a/doc/cljlib.md b/doc/cljlib.md index e54bcae..4634fb9 100644 --- a/doc/cljlib.md +++ b/doc/cljlib.md @@ -138,15 +138,12 @@ arguments to `args`, and `f` must support variadic amount of arguments. ### Examples -Applying `print` to different arguments: +Applying [`add`](#add) to different amount of arguments: ``` fennel -(apply print [1 2 3 4]) -;; prints 1 2 3 4 -(apply print 1 [2 3 4]) -;; => 1 2 3 4 -(apply print 1 2 3 4 5 6 [7 8 9]) -;; => 1 2 3 4 5 6 7 8 9 +(assert-eq (apply add [1 2 3 4]) 10) +(assert-eq (apply add 1 [2 3 4]) 10) +(assert-eq (apply add 1 2 3 4 5 6 [7 8 9]) 45) ``` ## `add` @@ -228,7 +225,7 @@ Function signature: (inc ([x])) ``` -Increase number by one +Increase number `x` by one ## `dec` Function signature: @@ -237,7 +234,7 @@ Function signature: (dec ([x])) ``` -Decrease number by one +Decrease number `x` by one ## `eq` Function signature: @@ -270,24 +267,24 @@ metadata attached for this test to work. Non empty tables: ``` fennel -(assert (map? {:a 1 :b 2})) +(assert-is (map? {:a 1 :b 2})) (local some-table {:key :value}) -(assert (map? some-table)) +(assert-is (map? some-table)) ``` Empty tables: ``` fennel (local some-table {}) -(assert (not (map? some-table))) +(assert-not (map? some-table)) ``` Empty tables created with [`hash-map`](#hash-map) will pass the test: ``` fennel (local some-table (hash-map)) -(assert (map? some-table)) +(assert-is (map? some-table)) ``` ## `vector?` @@ -312,24 +309,24 @@ metadata attached for this test to work. Non empty vector: ``` fennel -(assert (vector? [1 2 3 4])) +(assert-is (vector? [1 2 3 4])) (local some-table [1 2 3]) -(assert (vector? some-table)) +(assert-is (vector? some-table)) ``` Empty tables: ``` fennel (local some-table []) -(assert (not (vector? some-table))) +(assert-not (vector? some-table)) ``` Empty tables created with [`vector`](#vector) will pass the test: ``` fennel (local some-table (vector)) -(assert (vector? some-table)) +(assert-is (vector? some-table)) ``` ## `multifn?` @@ -360,7 +357,7 @@ Function signature: (nil? ([]) ([x])) ``` -Test if value is nil. +Test if `x` is nil. ## `zero?` Function signature: @@ -369,7 +366,7 @@ Function signature: (zero? ([x])) ``` -Test if value is equal to zero. +Test if `x` is equal to zero. ## `pos?` Function signature: @@ -396,7 +393,7 @@ Function signature: (even? ([x])) ``` -Test if value is even. +Test if `x` is even. ## `odd?` Function signature: @@ -405,7 +402,7 @@ Function signature: (odd? ([x])) ``` -Test if value is odd. +Test if `x` is odd. ## `string?` Function signature: @@ -514,7 +511,7 @@ Sets additional metadata for function [`vector?`](#vector?) to work. ``` fennel (local v (vector 1 2 3 4)) -(assert (eq v [1 2 3 4])) +(assert-eq v [1 2 3 4]) ``` ## `seq` @@ -564,7 +561,7 @@ Function signature: (kvseq ([col])) ``` -Transforms any table to key-value sequence. +Transforms any table `col` to key-value sequence. ## `first` Function signature: @@ -953,7 +950,8 @@ Function signature: (hash-map ([]) ([& kvs])) ``` -Create associative table from keys and values +Create associative table from `kvs` represented as sequence of keys +and values ## `get` Function signature: @@ -1002,7 +1000,7 @@ Function signature: (find ([tbl key])) ``` -Returns the map entry for `key`, or `nil` if key not present. +Returns the map entry for `key`, or `nil` if key not present in `tbl`. ## `dissoc` Function signature: @@ -1011,44 +1009,45 @@ Function signature: (dissoc ([tbl]) ([tbl key]) ([tbl key & keys])) ``` -Remove `key` from table `tbl`. +Remove `key` from table `tbl`. Optionally takes more `keys`. ## `remove-method` Function signature: ``` -(remove-method ([multifn dispatch-val])) +(remove-method ([multimethod dispatch-value])) ``` -Remove method from `multifn` for given `dispatch-val`. +Remove method from `multimethod` for given `dispatch-value`. ## `remove-all-methods` Function signature: ``` -(remove-all-methods ([multifn])) +(remove-all-methods ([multimethod])) ``` -Removes all of the methods of multimethod +Removes all of the methods of `multimethod` ## `methods` Function signature: ``` -(methods ([multifn])) +(methods ([multimethod])) ``` -Given a multimethod, returns a map of dispatch values -> dispatch fns +Given a `multimethod`, returns a map of dispatch values -> dispatch fns ## `get-method` Function signature: ``` -(get-method ([multifn dispatch-val])) +(get-method ([multimethod dispatch-value])) ``` -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. +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. ## `ordered-set` Function signature: @@ -1133,9 +1132,9 @@ and are compared for having the same keys without particular order and same size: ``` fennel -(assert (= (ordered-set :a :b) (ordered-set :b :a))) -(assert (not= (ordered-set :a :b) (ordered-set :b :a :c))) -(assert (= (ordered-set :a :b) (hash-set :a :b))) +(assert-eq (ordered-set :a :b) (ordered-set :b :a)) +(assert-ne (ordered-set :a :b) (ordered-set :b :a :c)) +(assert-eq (ordered-set :a :b) (hash-set :a :b)) ``` ## `hash-set` @@ -1168,5 +1167,5 @@ Copyright (C) 2020 Andrey Orst License: [MIT](https://gitlab.com/andreyorst/fennel-cljlib/-/raw/master/LICENSE) -<!-- Generated with Fenneldoc 0.0.7 +<!-- Generated with Fenneldoc 0.1.0 https://gitlab.com/andreyorst/fenneldoc --> diff --git a/doc/macros.md b/doc/macros.md index 1841b14..f1efa48 100644 --- a/doc/macros.md +++ b/doc/macros.md @@ -1,4 +1,4 @@ -# Macros.fnl (0.3.0) +# Macros.fnl (0.4.0) Macros for Cljlib that implement various facilities from Clojure. **Table of contents** @@ -27,7 +27,10 @@ Function signature: ``` Create (anonymous) function of fixed arity. -Supports multiple arities by defining bodies as lists. +Accepts optional `name` and `docstring?` as first two arguments, +followed by single or multiple arity bodies defined as lists. Each +list starts with `arglist*` vector, which supports destructuring, and +is followed by `body*` wrapped in implicit `do`. ### Examples Named function of fixed arity 2: @@ -136,12 +139,12 @@ namespace tables: ([t1 t2 & tables] (join (join t1 t2) ((or table.unpack _G.unpack) tables)))) ;; call to `join` resolves to ns.tables.join -(ns.strings.join "a" "b" "c") -;; => abc -(join ["a"] ["b"] ["c"] ["d" "e"]) -;; => ["a" "b" "c" "d" "e"] -(join "a" "b" "c") -;; {} +(assert-eq (ns.strings.join "a" "b" "c") "abc") + +(assert-eq (join ["a"] ["b"] ["c"] ["d" "e"]) + ["a" "b" "c" "d" "e"]) +(assert-eq (join "a" "b" "c") + []) ``` Note that this creates a collision and local `join` overrides `join` @@ -159,10 +162,12 @@ General purpose try/catch/finally macro. Wraps its body in `pcall` and checks the return value with `match` macro. -Catch clause is written either as (catch symbol body*), thus acting as -catch-all, or (catch value body*) for catching specific errors. It is -possible to have several `catch` clauses. If no `catch` clauses -specified, an implicit catch-all clause is created. +Catch clause is written either as `(catch symbol body*)`, thus acting +as catch-all, or `(catch value body*)` for catching specific errors. +It is possible to have several `catch` clauses. If no `catch` clauses +specified, an implicit catch-all clause is created. `body*`, and +inner expressions of `catch-clause*`, and `finally-clause?` are +wrapped in implicit `do`. Finally clause is optional, and written as (finally body*). If present, it must be the last clause in the `try` form, and the only @@ -184,36 +189,36 @@ Catch all errors, ignore those and return fallback value: (+ x y) (catch _ 0))) -(add nil 1) ;; => 0 +(assert-eq (add nil 1) 0) ``` Catch error and do cleanup: ``` fennel -(let [tbl []] - (try - (table.insert tbl "a") - (table.insert tbl "b" "c") - (catch _ - (each [k _ (pairs tbl)] - (tset tbl k nil)))) - tbl) -;; => {} +(local tbl []) + +(try + (table.insert tbl "a") + (table.insert tbl "b" "c") + (catch _ + (each [k _ (pairs tbl)] + (tset tbl k nil)))) + +(assert-eq (length tbl) 0) + ``` Always run some side effect action: ``` fennel -(local res (try 10 (finally (print "side-effect!")))) -;; => side-effect! -;; => nil -res -;; => 10 -(local res (try (error 10) (catch 10 nil) (finally (print "side-effect!")))) -;; => side-effect! -;; => nil -res -;; => nil +(local t []) +(local res (try 10 (finally (table.insert t :finally)))) +(assert-eq (. t 1) :finally) +(assert-eq res 10) + +(local res (try (error 10) (catch 10 nil) (finally (table.insert t :again)))) +(assert-eq (. t 2) :again) +(assert-eq res nil) ``` @@ -224,15 +229,22 @@ Function signature: (def attr-map? name expr) ``` -Wrapper around `local` which can -declare variables inside namespace, and as local at the same time -similarly to [`fn*`](#fn*): +Wrapper around `local` which can declare variables inside namespace, +and as local `name` at the same time similarly to +[`fn*`](#fn*). Accepts optional `attr-map?` which can contain a +docstring, and whether variable should be mutable or not. Sets +variable to the result of `expr`. ``` fennel (def ns {}) (def a 10) ;; binds `a` to `10` +(assert-eq a 10) + (def ns.b 20) ;; binds `ns.b` and `b` to `20` + +(assert-eq b 20) +(assert-eq ns.b 20) ``` `a` is a `local`, and both `ns.b` and `b` refer to the same value. @@ -263,42 +275,48 @@ Function signature: ``` Works the same as [`def`](#def), but ensures that later `defonce` -calls will not override existing bindings: +calls will not override existing bindings. Accepts same `attr-map?` as +`def`, and sets `name` to the result of `expr`: ``` fennel (defonce a 10) (defonce a 20) -(print a) ;; => prints 10 +(assert-eq a 10) ``` ## `defmulti` Function signature: ``` -(defmulti name docstring? dispatch-fn attr-map?) +(defmulti name docstring? dispatch-fn options*) ``` -Create multifunction with -runtime dispatching based on results from `dispatch-fn`. Returns an -empty table with `__call` metamethod, that calls `dispatch-fn` on its -arguments. Amount of arguments passed, should be the same as accepted -by `dispatch-fn`. Looks for multimethod based on result from -`dispatch-fn`. +Create multifunction `name` with runtime dispatching based on results +from `dispatch-fn`. Returns a proxy table with `__call` metamethod, +that calls `dispatch-fn` on its arguments. Amount of arguments +passed, should be the same as accepted by `dispatch-fn`. Looks for +multimethod based on result from `dispatch-fn`. + +Accepts optional `docstring?`, and `options*` arguments, where +`options*` is a sequence of key value pairs representing additional +attributes. Supported options: + +`:default` - the default dispatch value, defaults to `:default`. By default, multifunction has no multimethods, see -[`multimethod`](#multimethod) on how to add one. +[`defmethod`](#defmethod) on how to add one. ## `defmethod` Function signature: ``` -(defmethod multifn dispatch-val fnspec) +(defmethod multi-fn dispatch-value fnspec) ``` -Attach new method to multi-function dispatch value. accepts the `multi-fn` -as its first argument, the dispatch value as second, and function tail -starting from argument list, followed by function body as in -[`fn*`](#fn). +Attach new method to multi-function dispatch value. accepts the +`multi-fn` as its first argument, the `dispatch-value` as second, and +`fnspec` - a function tail starting from argument list, followed by +function body as in [`fn*`](#fn). ### Examples Here are some examples how multimethods can be used. @@ -315,7 +333,7 @@ to another multimethod: (defmethod fac 0 [_] 1) (defmethod fac :default [x] (* x (fac (- x 1)))) -(fac 4) ;; => 24 +(assert-eq (fac 4) 24) ``` `:default` is a special method which gets called when no other methods @@ -348,22 +366,30 @@ tables to Lua's one: (defmulti to-lua-str (fn [x] (type x))) (defmethod to-lua-str :number [x] (tostring x)) -(defmethod to-lua-str :table [x] (let [res []] - (each [k v (pairs x)] - (table.insert res (.. "[" (to-lua-str k) "] = " (to-lua-str v)))) - (.. "{" (table.concat res ", ") "}"))) +(defmethod to-lua-str :table [x] + (let [res []] + (each [k v (pairs x)] + (table.insert res (.. "[" (to-lua-str k) "] = " (to-lua-str v)))) + (.. "{" (table.concat res ", ") "}"))) (defmethod to-lua-str :string [x] (.. "\"" x "\"")) (defmethod to-lua-str :default [x] (tostring x)) -(print (to-lua-str {:a {:b 10}})) -;; => {["a"] = {["b"] = 10}} +(assert-eq (to-lua-str {:a {:b 10}}) "{[\"a\"] = {[\"b\"] = 10}}") -(print (to-lua-str [:a :b :c [:d {:e :f}]])) -;; => {[1] = "a", [2] = "b", [3] = "c", [4] = {[1] = "d", [2] = {["e"] = "f"}}} +(assert-eq (to-lua-str [:a :b :c [:d {:e :f}]]) + "{[1] = \"a\", [2] = \"b\", [3] = \"c\", [4] = {[1] = \"d\", [2] = {[\"e\"] = \"f\"}}}") ``` And if we call it on some table, we'll get a valid Lua table, which we -can then reformat as we want and use in Lua if we want. +can then reformat as we want and use in Lua. + +All of this can be done with functions, and single entry point +function, that uses if statement and branches on the type, however one +of the additional features of multimethods, is that separate libraries +can extend such multimethod by adding additional claues to it without +needing to patch the source of the function. For example later on +support for userdata or coroutines can be added to `to-lua-str` +function as a separate multimethods for respective types. ## `into` Function signature: @@ -372,7 +398,7 @@ Function signature: (into to from) ``` -Transform one table into another. Mutates first table. +Transform table `from` into another table `to`. Mutates first table. Transformation happens in runtime, but type deduction happens in compile time if possible. This means, that if literal values passed @@ -380,15 +406,15 @@ to `into` this will have different effects for associative tables and vectors: ``` fennel -(into [1 2 3] [4 5 6]) ;; => [1 2 3 4 5 6] -(into {:a 1 :c 2} {:a 0 :b 1}) ;; => {:a 0 :b 1 :c 2} +(assert-eq (into [1 2 3] [4 5 6]) [1 2 3 4 5 6]) +(assert-eq (into {:a 1 :c 2} {:a 0 :b 1}) {:a 0 :b 1 :c 2}) ``` Conversion between different table types is also supported: ``` fennel -(into [] {:a 1 :b 2 :c 3}) ;; => [[:a 1] [:b 2] [:c 3]] -(into {} [[:a 1] [:b 2]]) ;; => {:a 1 :b 2} +(assert-eq (into [] {:a 1}) [[:a 1]]) +(assert-eq (into {} [[:a 1] [:b 2]]) {:a 1 :b 2}) ``` Same rules apply to runtime detection of table type, except that this @@ -396,7 +422,7 @@ will not work for empty tables: ``` fennel (local empty-table {}) -(into empty-table {:a 1 :b 2}) ;; => [[:a 1] [:b 2]] +(assert-eq (into empty-table {:a 1}) [[:a 1]]) ``` fennel If table is empty, `into` defaults to sequential table, because it @@ -408,8 +434,8 @@ runtime, and this works as expected: ``` fennel (local t1 [1 2 3]) (local t2 {:a 10 :c 3}) -(into t1 {:a 1 :b 2}) ;; => [1 2 3 [:a 1] [:b 2]] -(into t2 {:a 1 :b 2}) ;; => {:a 1 :b 2 :c 3} +(assert-eq (into t1 {:a 1}) [1 2 3 [:a 1]]) +(assert-eq (into t2 {:a 1}) {:a 1 :c 3}) ``` `cljlib.fnl` module provides two additional functions `vector` and @@ -417,8 +443,8 @@ runtime, and this works as expected: at runtime: ``` fennel -(into (vector) {:a 1 :b 2}) ;; => [[:a 1] [:b 2]] -(into (hash-map) [[:a 1 :b 2]]) ;; => {:a 1 :b 2} +(assert-eq (into (vector) {:a 1}) [[:a 1]]) +(assert-eq (into (hash-map) [[:a 1] [:b 2]]) {:a 1 :b 2}) ``` ## `empty` @@ -442,10 +468,10 @@ and return result of the same type: (table.insert res (f v))) (into (empty tbl) res))) -(map (fn [[k v]] [(string.upper k) v]) {:a 1 :b 2 :c 3}) -;; => {:A 1 :B 2 :C 3} -(map #(* $ $) [1 2 3 4]) -;; [1 4 9 16] +(assert-eq (map (fn [[k v]] [(string.upper k) v]) {:a 1 :b 2 :c 3}) + {:A 1 :B 2 :C 3}) +(assert-eq (map #(* $ $) [1 2 3 4]) + [1 4 9 16]) ``` See [`into`](#into) for more info on how conversion is done. @@ -456,11 +482,11 @@ Function signature: (when-meta [& body]) ``` -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` without `--metadata` -switch. +Wrapper that compiles away if metadata support was not enabled. +What this effectively means, is that everything that is wrapped with +this macro and its `body` will disappear from the resulting Lua code +if metadata is not enabled when compiling with `fennel --compile` +without `--metadata` switch. ## `with-meta` Function signature: @@ -469,7 +495,7 @@ Function signature: (with-meta value meta) ``` -Attach metadata to a value. When metadata feature is not enabled, +Attach `meta` to a `value`. When metadata feature is not enabled, returns the value without additional metadata. ``` fennel @@ -526,9 +552,9 @@ Function signature: (if-let [binding test] then-branch else-branch) ``` -If test is logical true, -evaluates `then-branch` with binding-form bound to the value of test, -if not, yields `else-branch`. +If `binding` is set by `test` to logical true, evaluates `then-branch` +with binding-form bound to the value of test, if not, yields +`else-branch`. ## `when-let` Function signature: @@ -537,8 +563,8 @@ Function signature: (when-let [binding test] & body) ``` -If test is logical true, -evaluates `body` in implicit `do`. +If `binding` was bound by `test` to logical true, evaluates `body` in +implicit `do`. ## `if-some` Function signature: @@ -547,9 +573,8 @@ Function signature: (if-some [binding test] then-branch else-branch) ``` -If test is non-`nil`, evaluates -`then-branch` with binding-form bound to the value of test, if not, -yields `else-branch`. +If `test` is non-`nil`, evaluates `then-branch` with `binding`-form bound +to the value of test, if not, yields `else-branch`. ## `when-some` Function signature: @@ -558,8 +583,8 @@ Function signature: (when-some [binding test] & body) ``` -If test is non-`nil`, -evaluates `body` in implicit `do`. +If `test` sets `binding` to non-`nil`, evaluates `body` in implicit +`do`. --- @@ -569,5 +594,5 @@ Copyright (C) 2020 Andrey Orst License: [MIT](https://gitlab.com/andreyorst/fennel-cljlib/-/raw/master/LICENSE) -<!-- Generated with Fenneldoc 0.0.7 +<!-- Generated with Fenneldoc 0.1.0 https://gitlab.com/andreyorst/fenneldoc --> diff --git a/doc/tests/test.md b/doc/tests/test.md index 8a6c7e5..f9d8ae9 100644 --- a/doc/tests/test.md +++ b/doc/tests/test.md @@ -16,7 +16,7 @@ Function signature: (deftest name ...) ``` -Simple way of grouping tests. +Simple way of grouping tests with `name`. ## `testing` Function signature: @@ -25,7 +25,7 @@ Function signature: (testing description ...) ``` -Print test description and run it. +Print test `description` and run it. ## `assert-eq` Function signature: @@ -34,30 +34,26 @@ Function signature: (assert-eq expr1 expr2 msg) ``` -Like `assert`, except compares results of two expressions on equality. +Like `assert`, except compares results of `expr1` and `expr2` for equality. Generates formatted message if `msg` is not set to other message. ### Example Compare two expressions: ``` fennel ->> (assert-eq 1 (+1 1)) -runtime error: equality assertion failed - Left: 1 - Right: 3 +;; (assert-eq 1 (+1 1)) +;; => runtime error: equality assertion failed +;; => Left: 1 +;; => Right: 3 ``` Deep compare values: ``` fennel ->> (assert-eq [1 {[2 3] [4 5 6]}] [1 {[2 3] [4 5]}]) -runtime error: equality assertion failed - Left: [1 { - [2 3] [4 5 6] - }] - Right: [1 { - [2 3] [4 5] - }] +;; (assert-eq [1 {[2 3] [4 5 6]}] [1 {[2 3] [4 5]}]) +;; => runtime error: equality assertion failed +;; => Left: [1 {[2 3] [4 5 6]}] +;; => Right: [1 {[2 3] [4 5]}] ``` ## `assert-ne` @@ -67,7 +63,9 @@ Function signature: (assert-ne expr1 expr2 msg) ``` -Assert for unequality. Same as [`assert-eq`](#assert-eq). +Assert for unequality. Like `assert`, except compares results of +`expr1` and `expr2` for equality. Generates formatted message if +`msg` is not set to other message. Same as [`assert-eq`](#assert-eq). ## `assert-is` Function signature: @@ -76,12 +74,12 @@ Function signature: (assert-is expr msg) ``` -Assert for truth. Same as inbuilt `assert`, except generates more +Assert `expr` for truth. Same as inbuilt `assert`, except generates more verbose message if `msg` is not set. ``` fennel ->> (assert-is (= 1 2 3)) -runtime error: assertion failed for (= 1 2 3) +;; (assert-is (= 1 2 3)) +;; => runtime error: assertion failed for (= 1 2 3) ``` ## `assert-not` @@ -91,8 +89,9 @@ Function signature: (assert-not expr msg) ``` -Assert for not truth. Works the same as [`assert-is`](#assert-is). +Assert `expr` for not truth. Generates more verbose message if + `msg` is not set. Works the same as [`assert-is`](#assert-is). -<!-- Generated with Fenneldoc 0.0.7 +<!-- Generated with Fenneldoc 0.1.0 https://gitlab.com/andreyorst/fenneldoc --> |