From 85db8b8549d9d45e39c1a5118d91d3fd3a88818f Mon Sep 17 00:00:00 2001 From: Andrey Listopadov Date: Sat, 29 Oct 2022 15:49:30 +0300 Subject: remove the :relative require, update installation guide, update docstrings --- .fenneldoc | 10 +--- Makefile | 13 ++++- README.md | 26 ++++++---- doc/core.md | 20 ++++---- doc/macros.md | 120 +++++++++++++++++++++++++++++++++++-------- init-macros.fnl | 155 ++++++++++++++++++++++++++++++++++++++++++++------------ init.fnl | 21 ++++---- 7 files changed, 271 insertions(+), 94 deletions(-) diff --git a/.fenneldoc b/.fenneldoc index 3cdf8b6..ab82b39 100644 --- a/.fenneldoc +++ b/.fenneldoc @@ -15,6 +15,7 @@ "keys" "tbl" "_" + "%+" "cs" "sep" "coll" @@ -27,12 +28,6 @@ :insert-copyright true :insert-license true :insert-version true - :keys {:copyright "_COPYRIGHT" - :description "_DESCRIPTION" - :doc-order "_DOC_ORDER" - :license "_LICENSE" - :module-name "_MODULE_NAME" - :version "_VERSION"} :mode "checkdoc" :modules-info {:init-macros.fnl {:description "Macros for fennel-cljlib." :name "macros"} @@ -159,9 +154,8 @@ non-ASCII strings." :order "alphabetic" :out-dir "./doc" :project-copyright "Copyright (C) 2020-2021 Andrey Listopadov" - :project-doc-order {} :project-license "[MIT](https://gitlab.com/andreyorst/fennel-cljlib/-/raw/master/LICENSE)" - :project-version "v1.0.0" + :project-version "v1.1.0" :sandbox false :test-requirements {:init-macros.fnl "(require-macros :init-macros) (import-macros {: assert-eq} :fennel-test) diff --git a/Makefile b/Makefile index d828d66..c7a4d79 100644 --- a/Makefile +++ b/Makefile @@ -10,11 +10,19 @@ LUASOURCES = $(FNLSOURCES:.fnl=.lua) LUAEXECUTABLES ?= lua luajit FENNELDOC := $(shell command -v fenneldoc) LUACOV_COBERTURA := $(shell command -v luacov-cobertura) -COMPILEFLAGS += --metadata +COMPILEFLAGS += --metadata --require-as-include .PHONY: build clean distclean test luacov luacov-console doc help $(LUAEXECUTABLES) build: $(LUASOURCES) + @echo "--[[ This is a self-contained version of the fennel-cljlib library" > cljlib.lua + @echo " meant to be used directly from Lua, or embedded into other" >> cljlib.lua + @echo " applications. It doesn't include macros, given that Lua doesn't" >> cljlib.lua + @echo " support Fennel's macro system, but all other features, like" >> cljlib.lua + @echo " laziness, and immutability are available in the same way as if" >> cljlib.lua + @echo " this library was used from Fennel. ]]" >> cljlib.lua + @cat init.lua >> cljlib.lua + @rm init.lua ${LUASOURCES}: $(FNLSOURCES) @@ -22,11 +30,12 @@ ${LUASOURCES}: $(FNLSOURCES) $(FENNEL) --lua $(LUA) $(COMPILEFLAGS) --compile $< > $@ clean: - rm -f $(LUASOURCES) $(LUATESTS) + rm -f $(LUASOURCES) $(LUATESTS) cljlib.lua distclean: clean rm -rf luacov* coverage +test: COMPILEFLAGS = --metadata test: $(FNLTESTS) @echo "Testing on" $$($(LUA) -v) >&2 @$(foreach test,$?,LUA_PATH="./?/init.lua;$LUA_PATH" $(FENNEL) $(COMPILEFLAGS) --lua $(LUA) $(test) || exit;) diff --git a/README.md b/README.md index 5de8568..f52b316 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,35 @@ # Fennel Cljlib -Experimental library for [Fennel](https://fennel-lang.org/) language, that adds many functions from [Clojure](https://clojure.org/)'s standard library. -This is not a one to one port of Clojure `core`, because many Clojure functions require certain guarantees, like immutability and laziness, which are hard to efficiently implement on top of Lua. +Experimental library for the [Fennel](https://fennel-lang.org/) language, that adds many functions from [Clojure](https://clojure.org/)'s standard library. +This is not a one-to-one port of Clojure `core`, because many Clojure features require certain facilities from the runtime. +This library implements lazy sequences, transducers, immutable tables, sets and vectors, transients, and a lot of functions from the `core` namespace. Some semantics like concurrency, or dynamic scope is not supported by Lua runtime at all. -Therefore certain functions were altered to better suit the domain. +Therefore, certain functions were altered to better suit the domain. ## Installation Clone library into your project or put it as a git submodule: - $ git clone --recursive https://gitlab.com/andreyorst/fennel-cljlib cljlib + $ git clone --recursive https://gitlab.com/andreyorst/fennel-cljlib club Now you can require `:cljlib` from Fennel: -``` clojure +``` fennel (local clj (require :cljlib)) (import-macros cljm :cljlib) ``` -Optionally precompile the library to make it load slightly faster: +Make sure to set up the `FENNEL_PATH` and `LUA_PATH` to include the installation directory: - $ cd cljlib; COMPILEFLAGS="--require-as-include" make + FENNEL_PATH="cljlib/?/init.fnl;$FENNEL_PATH" + LUA_PATH="cljlib/?/init.lua;#LUA_PATH" -This will compile `init.fnl` into `init.lua`, with all dependencies included, so `require` should honor Lua files over Fennel files. -It is also possible to use this library from Lua this way. +Alternatively, precompile the library to make it load slightly faster: + + $ cd cljlib; make + +This will compile `init.fnl` into the `cljlib.lua` file, with all dependencies included. +It is also possible to use this library directly from Lua this way. ## Documentation @@ -34,5 +40,5 @@ Documentation is auto-generated with [Fenneldoc](https://gitlab.com/andreyorst/f Please make sure you've read [contribution guidelines](https://gitlab.com/andreyorst/fennel-cljlib/-/tree/master/CONTRIBUTING.md). diff --git a/doc/core.md b/doc/core.md index 7f13e9b..cc8fab6 100644 --- a/doc/core.md +++ b/doc/core.md @@ -1,4 +1,4 @@ -# Core (v1.0.0) +# Core (v1.1.0) Fennel-cljlib - functions from Clojure's core.clj implemented on top of Fennel. @@ -1175,7 +1175,7 @@ Function signature: ``` A transducer which concatenates the contents of each input, which must be a - collection, into the reduction. + collection, into the reduction. Accepts the reducing function `rf`. ## `class` Function signature: @@ -1464,8 +1464,8 @@ Function signature: (into ({}) ([to]) ([to from]) ([to xform from])) ``` -Returns a new coll consisting of to-coll with all of the items of - from-coll conjoined. A transducer may be supplied. +Returns a new coll consisting of `to` with all of the items of + `from` conjoined. A transducer `xform` may be supplied. ### Examples @@ -1751,7 +1751,7 @@ Function signature: (random-sample ([prob]) ([prob coll])) ``` -Returns items from coll with random probability of prob (0.0 - +Returns items from `coll` with random probability of `prob` (0.0 - 1.0). Returns a transducer when no collection is provided. ## `realized?` @@ -1872,10 +1872,10 @@ Function signature: Coerces coll to a (possibly empty) sequence, if it is not already one. Will not force a lazy seq. `(sequence nil)` yields an empty list, -When a transducer is supplied, returns a lazy sequence of applications -of the transform to the items in `coll`, i.e. to the set of first -items of each `coll`, followed by the set of second items in each -`coll`, until any one of the `colls` is exhausted. Any remaining +When a transducer `xform` is supplied, returns a lazy sequence of +applications of the transform to the items in `coll`, i.e. to the set +of first items of each `coll`, followed by the set of second items in +each `coll`, until any one of the `colls` is exhausted. Any remaining items in other `colls` are ignored. The transform should accept number-of-colls arguments @@ -2011,7 +2011,7 @@ Function signature: (unreduced [x]) ``` -**Undocumented** +If `x` is `reduced?`, returns `(deref x)`, else returns `x`. ## `update` Function signature: diff --git a/doc/macros.md b/doc/macros.md index 6e93a10..90dcc15 100644 --- a/doc/macros.md +++ b/doc/macros.md @@ -1,4 +1,4 @@ -# Macros (v1.0.0) +# Macros (v1.1.0) Macros for fennel-cljlib. **Table of contents** @@ -29,7 +29,10 @@ Function signature: (cond ...) ``` -**Undocumented** +Takes a set of test expression pairs. It evaluates each test one at a +time. If a test returns logical true, `cond` evaluates and returns +the value of the corresponding expression and doesn't evaluate any of +the other tests or exprs. `(cond)` returns nil. ## `def` Function signature: @@ -40,7 +43,10 @@ Function signature: Name binding macro similar to `local` but acts in terms of current namespace set with the `ns` macro, unless `:private` was passed before -the binding name. +the binding name. Accepts the `name` to be bound and the `initializer` +expression. `meta` can be either an associative table where keys are +strings, or a string representing a key from the table. If a sole +string is given, it's value is set to `true` in the meta table. ## `defmethod` Function signature: @@ -164,7 +170,11 @@ Function signature: Same as (def name (fn* name docstring? [params*] pre-post? exprs*)) or (def name (fn* name docstring? ([params*] pre-post? exprs*)+)) with -any doc-string or attrs added to the function metadata. +any doc-string or attrs added to the function metadata. Accepts +`name` wich will be used to refer to a function in the current +namespace, and optional `doc-string?`, a vector of function's +`params*`, `pre-post?` conditions, and the `body` of the function. +The body is wrapped in an implicit do. See `fn*` for more info. ## `defn-` Function signature: @@ -176,7 +186,10 @@ Function signature: Same as (def :private name (fn* name docstring? [params*] pre-post? exprs*)) or (def :private name (fn* name docstring? ([params*] pre-post? exprs*)+)) with any doc-string or attrs added to the -function metadata. +function metadata. Accepts `name` wich will be used to refer to a +function, and optional `doc-string?`, a vector of function's `params*`, +`pre-post?` conditions, and the `body` of the function. The body is +wrapped in an implicit do. See `fn*` for more info. ## `fn*` Function signature: @@ -186,14 +199,18 @@ Function signature: ``` Clojure-inspired `fn` macro for defining functions. -Supports multi-arity dispatching via the following syntax: +Accepts an optional `name` and `docstring?`, followed by the binding +list containing function's `params*`. The `body` is wrapped in an +implicit `do`. The `doc-string?` argument specifies an optional +documentation for the function. Supports multi-arity dispatching via +the following syntax: (fn* optional-name optional-docstring ([arity1] body1) ([other arity2] body2)) -Accepts pre and post conditions in a form of a table after argument +Accepts `pre-post?` conditions in a form of a table after argument list: (fn* optional-name @@ -211,19 +228,21 @@ The same syntax applies to multi-arity version. Function signature: ``` -(if-let [name test] if-branch else-branch ...) +(if-let [name test] if-branch else-branch) ``` -**Undocumented** +When `test` is logical `true`, evaluates the `if-branch` with `name` +bound to the value of `test`. Otherwise evaluates the `else-branch` ## `if-some` Function signature: ``` -(if-some [name test] if-branch else-branch ...) +(if-some [name test] if-branch else-branch) ``` -**Undocumented** +When `test` is not `nil`, evaluates the `if-branch` with `name` +bound to the value of `test`. Otherwise evaluates the `else-branch` ## `in-ns` Function signature: @@ -232,25 +251,50 @@ Function signature: (in-ns name) ``` -**Undocumented** +Sets the compile time variable `current-ns` to the given `name`. +Affects such macros as `def`, `defn`, which will bind names to the +specified namespace. + +### Examples + +```fennel +(ns a) +(defn f [] "f from a") +(ns b) +(defn f [] "f from b") +(in-ns a) +(defn g [] "g from a") +(in-ns b) +(defn g [] "g from b") + +(assert-eq (a.f) "f from a") +(assert-eq (b.f) "f from b") +(assert-eq (a.g) "g from a") +(assert-eq (b.g) "g from b") +``` ## `lazy-cat` Function signature: ``` -(lazy-cat ...) +(lazy-cat & colls) ``` -**Undocumented** +Expands to code which yields a lazy sequence of the concatenation of +`colls` - expressions returning collections. Each expression is not +evaluated until it is needed. ## `lazy-seq` Function signature: ``` -(lazy-seq ...) +(lazy-seq & body) ``` -**Undocumented** +Takes a `body` of expressions that returns an sequence, table or nil, +and yields a lazy sequence that will invoke the body only the first +time `seq` is called, and will cache the result and return it on all +subsequent `seq` calls. See also - `realized?` ## `loop` Function signature: @@ -297,6 +341,38 @@ Function signature: ``` Namespace declaration macro. +Accepts the `name` of the generated namespace, and creates a local +variable with this name holding a table. Optionally accepts +`commentary` describing what namespace is about and a `requirements` +spec, specifying what libraries should be required. + +The `requirements` spec is a list that consists of vectors, specifying +library name and a possible alias or a vector of names to refer to +without a prefix: + +``` +(ns some-namespace + "Description of the some-namespace." + (:require [some.lib] + [some.other.lib :as lib2] + [another.lib :refer [foo bar baz]])) + +(defn inc [x] (+ x 1)) +``` + +Which is equivalent to: + +``` +(local some-namespace {}) +(local lib (require :some.lib)) +(local lib2 (require :some.other.lib)) +(local {:bar bar :baz baz :foo foo} (require :another.lib)) +(comment "Description of the some-namespace.") +``` + +Note that when no `:as` alias is given, the library will be named +after the innermost part of the require path, i.e. `some.lib` is +transformed to `lib`. ## `time` Function signature: @@ -305,7 +381,7 @@ Function signature: (time expr) ``` -Measure expression execution time in ms. +Measure the CPU time spent executing `expr`. ## `try` Function signature: @@ -381,19 +457,21 @@ Always run some side effect action: Function signature: ``` -(when-let [name test] ...) +(when-let [name test] & body) ``` -**Undocumented** +When `test` is logical `true`, evaluates the `body` with `name` bound +to the value of `test`. ## `when-some` Function signature: ``` -(when-some [name test] ...) +(when-some [name test] & body) ``` -**Undocumented** +When `test` is not `nil`, evaluates the `body` with `name` bound to +the value of `test`. --- diff --git a/init-macros.fnl b/init-macros.fnl index 569bee7..7ee918b 100644 --- a/init-macros.fnl +++ b/init-macros.fnl @@ -40,18 +40,40 @@ SOFTWARE.") (set has (= sym elt))) has) -(fn make-require [module relative?] - (let [module (tostring module)] - (if relative? - `(if (: (or ... "") :match "(.+%.)[^.]+") - (require (.. (: (or ... "") :match "(.+%.)[^.]+") ,module)) - (= ... "init") - (require ,module) - (require (.. ... "." ,module))) - `(require ,module)))) - (fn ns [name commentary requirements] - "Namespace declaration macro." + "Namespace declaration macro. +Accepts the `name` of the generated namespace, and creates a local +variable with this name holding a table. Optionally accepts +`commentary` describing what namespace is about and a `requirements` +spec, specifying what libraries should be required. + +The `requirements` spec is a list that consists of vectors, specifying +library name and a possible alias or a vector of names to refer to +without a prefix: + +``` +(ns some-namespace + \"Description of the some-namespace.\" + (:require [some.lib] + [some.other.lib :as lib2] + [another.lib :refer [foo bar baz]])) + +(defn inc [x] (+ x 1)) +``` + +Which is equivalent to: + +``` +(local some-namespace {}) +(local lib (require :some.lib)) +(local lib2 (require :some.other.lib)) +(local {:bar bar :baz baz :foo foo} (require :another.lib)) +(comment \"Description of the some-namespace.\") +``` + +Note that when no `:as` alias is given, the library will be named +after the innermost part of the require path, i.e. `some.lib` is +transformed to `lib`." (set current-ns name) (let [bind-table [name] require-table [{}] @@ -61,21 +83,26 @@ SOFTWARE.") (match requirements [:require & requires] (each [_ spec (ipairs requires)] - (let [relative? (has? spec :relative)] - (match spec - (where (or [module :as alias :refer names] - [module :refer names :as alias])) - (do (table.insert bind-table (collect [_ name (ipairs names) :into {'&as alias}] - (values (tostring name) name))) - (table.insert require-table (make-require module relative?))) - [module :as alias] - (do (table.insert bind-table alias) - (table.insert require-table (make-require module relative?))) - [module :refer names] - (do (table.insert bind-table (collect [_ name (ipairs names)] - (values (tostring name) name))) - (table.insert require-table (make-require module relative?))) - _ (assert-compile false "wrong require syntax" name)))) + (match spec + (where (or [module :as alias :refer names] + [module :refer names :as alias])) + (do (table.insert bind-table (collect [_ name (ipairs names) :into {'&as alias}] + (values (tostring name) name))) + (table.insert require-table `(require ,(tostring module)))) + [module :as alias] + (do (table.insert bind-table alias) + (table.insert require-table `(require ,(tostring module)))) + [module :refer names] + (do (table.insert bind-table (collect [_ name (ipairs names)] + (values (tostring name) name))) + (table.insert require-table `(require ,(tostring module)))) + [module] + (do (->> (string.gsub (tostring module) ".+%.(.-)$" "%1") + (pick-values 1) + sym + (table.insert bind-table)) + (table.insert require-table `(require ,(tostring module)))) + _ (assert-compile false "wrong require syntax" name))) nil nil _ (assert-compile false "wrong require syntax" name)) (if (string? commentary) @@ -84,6 +111,27 @@ SOFTWARE.") `(local ,bind-table ,require-table)))) (fn in-ns [name] + "Sets the compile time variable `current-ns` to the given `name`. +Affects such macros as `def`, `defn`, which will bind names to the +specified namespace. + +# Examples + +```fennel +(ns a) +(defn f [] \"f from a\") +(ns b) +(defn f [] \"f from b\") +(in-ns a) +(defn g [] \"g from a\") +(in-ns b) +(defn g [] \"g from b\") + +(assert-eq (a.f) \"f from a\") +(assert-eq (b.f) \"f from b\") +(assert-eq (a.g) \"g from a\") +(assert-eq (b.g) \"g from b\") +```" (set current-ns name)) ;;; def @@ -91,7 +139,10 @@ SOFTWARE.") (fn def [...] {:fnl/docstring "Name binding macro similar to `local` but acts in terms of current namespace set with the `ns` macro, unless `:private` was passed before -the binding name." +the binding name. Accepts the `name` to be bound and the `initializer` +expression. `meta` can be either an associative table where keys are +strings, or a string representing a key from the table. If a sole +string is given, it's value is set to `true` in the meta table." :fnl/arglist [([name initializer]) ([meta name initializer])]} (match [...] (where (or [:private name val] @@ -229,14 +280,18 @@ Because inital arglist didn't specify arities of 0 and 2." (fn fn* [...] {:fnl/docstring "Clojure-inspired `fn' macro for defining functions. -Supports multi-arity dispatching via the following syntax: +Accepts an optional `name` and `docstring?`, followed by the binding +list containing function's `params*`. The `body` is wrapped in an +implicit `do`. The `doc-string?` argument specifies an optional +documentation for the function. Supports multi-arity dispatching via +the following syntax: (fn* optional-name optional-docstring ([arity1] body1) ([other arity2] body2)) -Accepts pre and post conditions in a form of a table after argument +Accepts `pre-post?` conditions in a form of a table after argument list: (fn* optional-name @@ -366,7 +421,11 @@ The same syntax applies to multi-arity version. {:fnl/docstring "Same as (def name (fn* name docstring? [params*] pre-post? exprs*)) or (def name (fn* name docstring? ([params*] pre-post? exprs*)+)) with -any doc-string or attrs added to the function metadata." +any doc-string or attrs added to the function metadata. Accepts +`name` wich will be used to refer to a function in the current +namespace, and optional `doc-string?`, a vector of function's +`params*`, `pre-post?` conditions, and the `body` of the function. +The body is wrapped in an implicit do. See `fn*` for more info." :fnl/arglist [([name doc-string? [params*] pre-post? body]) ([name doc-string? ([params*] pre-post? body)+])]} (assert-compile (sym? name) "expected a function name, use `fn*` for anonymous functions" name) @@ -377,7 +436,10 @@ any doc-string or attrs added to the function metadata." "Same as (def :private name (fn* name docstring? [params*] pre-post? exprs*)) or (def :private name (fn* name docstring? ([params*] pre-post? exprs*)+)) with any doc-string or attrs added to the -function metadata." +function metadata. Accepts `name` wich will be used to refer to a +function, and optional `doc-string?`, a vector of function's `params*`, +`pre-post?` conditions, and the `body` of the function. The body is +wrapped in an implicit do. See `fn*` for more info." :fnl/arglist [([name doc-string? [params*] pre-post? body]) ([name doc-string? ([params*] pre-post? body)+])]} (assert-compile (sym? name) "expected a function name, use `fn*` for anonymous functions" name) @@ -386,7 +448,7 @@ function metadata." ;;; Time (fn time [expr] - "Measure expression execution time in ms." + "Measure the CPU time spent executing `expr`." `(let [c# os.clock pack# #(doto [$...] (tset :n (select "#" $...))) s# (c#) @@ -398,12 +460,18 @@ function metadata." ;;; let variants (fn when-let [[name test] ...] + {:fnl/docstring "When `test` is logical `true`, evaluates the `body` with `name` bound +to the value of `test`." + :fnl/arglist [[name test] & body]} `(let [val# ,test] (if val# (let [,name val#] ,...)))) (fn if-let [[name test] if-branch else-branch ...] + {:fnl/docstring "When `test` is logical `true`, evaluates the `if-branch` with `name` +bound to the value of `test`. Otherwise evaluates the `else-branch`" + :fnl/arglist [[name test] if-branch else-branch]} (assert-compile (= 0 (select "#" ...)) "too many arguments to if-let" ...) `(let [val# ,test] (if val# @@ -412,12 +480,18 @@ function metadata." ,else-branch))) (fn when-some [[name test] ...] + {:fnl/docstring "When `test` is not `nil`, evaluates the `body` with `name` bound to +the value of `test`." + :fnl/arglist [[name test] & body]} `(let [val# ,test] (if (not= nil val#) (let [,name val#] ,...)))) (fn if-some [[name test] if-branch else-branch ...] + {:fnl/docstring "When `test` is not `nil`, evaluates the `if-branch` with `name` +bound to the value of `test`. Otherwise evaluates the `else-branch`" + :fnl/arglist [[name test] if-branch else-branch]} (assert-compile (= 0 (select "#" ...)) "too many arguments to if-some" ...) `(let [val# ,test] (if (not= nil val#) @@ -863,10 +937,16 @@ Always run some side effect action: ;;; Misc (fn cond [...] + "Takes a set of test expression pairs. It evaluates each test one at a +time. If a test returns logical true, `cond` evaluates and returns +the value of the corresponding expression and doesn't evaluate any of +the other tests or exprs. `(cond)` returns nil." (assert-compile (= 0 (% (select "#" ...) 2)) "cond requires an even number of forms" ...) - `(if ,...)) + (if (= 0 (select "#" ...)) + `nil + `(if ,...))) ;;; Lazy seq @@ -877,6 +957,11 @@ Always run some side effect action: "lazy-seq.init-macros"))) (fn lazy-seq [...] + {:fnl/docstring "Takes a `body` of expressions that returns an sequence, table or nil, +and yields a lazy sequence that will invoke the body only the first +time `seq` is called, and will cache the result and return it on all +subsequent `seq` calls. See also - `realized?`" + :fnl/arglist [& body]} `(let [core# (require ,core) res# ,(lazy-seq* ...)] (match (getmetatable res#) @@ -888,6 +973,10 @@ Always run some side effect action: res#)) (fn lazy-cat [...] + {:fnl/docstring "Expands to code which yields a lazy sequence of the concatenation of +`colls` - expressions returning collections. Each expression is not +evaluated until it is needed." + :fnl/arglist [& colls]} `(let [core# (require ,core) res# ,(lazy-cat* ...)] (match (getmetatable res#) diff --git a/init.fnl b/init.fnl index ccb705f..f0898b5 100644 --- a/init.fnl +++ b/init.fnl @@ -31,8 +31,8 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM‚ DAMAGES OR OTHER LIABILITY‚ WHETHER IN AN ACTION OF CONTRACT‚ TORT OR OTHERWISE‚ ARISING FROM‚ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." - (:require [lazy-seq :as lazy :relative] - [itable :as itable :relative])) + (:require [lazy-seq :as lazy] + [itable :as itable])) ;;; Utility functions @@ -1206,7 +1206,7 @@ Returns a transducer when no collection is provided." ([coll] (core.sequence (dedupe) coll))) (defn random-sample - "Returns items from coll with random probability of prob (0.0 - + "Returns items from `coll` with random probability of `prob` (0.0 - 1.0). Returns a transducer when no collection is provided." ([prob] (filter (fn [] (< (math.random) prob)))) @@ -1492,6 +1492,7 @@ called. Early termination is supported via `reduced`. (lazy.reduced? x)) (defn unreduced + "If `x` is `reduced?`, returns `(deref x)`, else returns `x`." [x] (if (reduced? x) (deref x) x)) @@ -1511,7 +1512,7 @@ called. Early termination is supported via `reduced`. (defn cat "A transducer which concatenates the contents of each input, which must be a - collection, into the reduction." + collection, into the reduction. Accepts the reducing function `rf`." [rf] (let [rrf (preserving-reduced rf)] (fn* @@ -1591,10 +1592,10 @@ that certain transforms may inject or skip items." (defn sequence "Coerces coll to a (possibly empty) sequence, if it is not already one. Will not force a lazy seq. `(sequence nil)` yields an empty list, -When a transducer is supplied, returns a lazy sequence of applications -of the transform to the items in `coll`, i.e. to the set of first -items of each `coll`, followed by the set of second items in each -`coll`, until any one of the `colls` is exhausted. Any remaining +When a transducer `xform` is supplied, returns a lazy sequence of +applications of the transform to the items in `coll`, i.e. to the set +of first items of each `coll`, followed by the set of second items in +each `coll`, until any one of the `colls` is exhausted. Any remaining items in other `colls` are ignored. The transform should accept number-of-colls arguments" ([coll] @@ -2046,8 +2047,8 @@ raise an error." ;;; Into (defn into - "Returns a new coll consisting of to-coll with all of the items of - from-coll conjoined. A transducer may be supplied. + "Returns a new coll consisting of `to` with all of the items of + `from` conjoined. A transducer `xform` may be supplied. # Examples -- cgit v1.2.3