summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Listopadov <andreyorst@gmail.com>2022-10-31 12:47:23 +0300
committerAndrey Listopadov <andreyorst@gmail.com>2022-10-31 13:17:07 +0300
commit44fa0c9514acade4b7dc80be1b1a1dcd5b3b0326 (patch)
treecf847c0dc1ab710a3093ebcc26f1a897228cb30a
parentaa1c2d9b7c65feefa63d2a84f996161309fb5dcd (diff)
fix namespace switching when using then in require-as-include scenarios
-rw-r--r--.fenneldoc12
-rw-r--r--doc/core.md67
-rw-r--r--doc/macros.md76
-rw-r--r--init-macros.fnl183
-rw-r--r--init.fnl55
5 files changed, 247 insertions, 146 deletions
diff --git a/.fenneldoc b/.fenneldoc
index c905ba1..4a7d003 100644
--- a/.fenneldoc
+++ b/.fenneldoc
@@ -36,7 +36,7 @@ of Fennel.
This library contains a set of functions providing functions that
behave similarly to Clojure's equivalents. Library itself has nothing
-Fennel specific so it should work on Lua, e.g:
+Fennel specific, so it should work on Lua, e.g:
``` lua
Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio
@@ -48,13 +48,13 @@ Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio
This example is mapping an anonymous `function' over a table,
producing new table and concatenating it with `\" \"`.
-However this library also provides Fennel-specific set of
-[macros](./macros.md), that provides additional facilities like
-`defn' or `defmulti' which extend the language allowing writing code
-that looks and works mostly like Clojure.
+However, this library also provides Fennel-specific set of
+[macros](./macros.md), that provides additional facilities like `defn'
+or `defmulti' which extend the language allowing writing code that
+looks and works mostly like Clojure.
Each function in this library is created with `defn', which is a
-special macros for creating multi-arity functions. So when you see
+special macro for creating multi-arity functions. So when you see
function signature like `(foo [x])`, this means that this is function
`foo', that accepts exactly one argument `x'. In contrary, functions
created with `fn' will produce `(foo x)` signature (`x' is not inside
diff --git a/doc/core.md b/doc/core.md
index a247529..74bd2c3 100644
--- a/doc/core.md
+++ b/doc/core.md
@@ -4,7 +4,7 @@ of Fennel.
This library contains a set of functions providing functions that
behave similarly to Clojure's equivalents. Library itself has nothing
-Fennel specific so it should work on Lua, e.g:
+Fennel specific, so it should work on Lua, e.g:
``` lua
Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio
@@ -16,13 +16,13 @@ Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio
This example is mapping an anonymous `function` over a table,
producing new table and concatenating it with `" "`.
-However this library also provides Fennel-specific set of
-[macros](./macros.md), that provides additional facilities like
-`defn` or `defmulti` which extend the language allowing writing code
-that looks and works mostly like Clojure.
+However, this library also provides Fennel-specific set of
+[macros](./macros.md), that provides additional facilities like `defn`
+or `defmulti` which extend the language allowing writing code that
+looks and works mostly like Clojure.
Each function in this library is created with `defn`, which is a
-special macros for creating multi-arity functions. So when you see
+special macro for creating multi-arity functions. So when you see
function signature like `(foo [x])`, this means that this is function
`foo`, that accepts exactly one argument `x`. In contrary, functions
created with `fn` will produce `(foo x)` signature (`x` is not inside
@@ -342,7 +342,7 @@ see `hash-map` for creating tables that have additional metadata
attached for this test to work.
### Examples
-Non empty map:
+Non-empty map:
``` fennel
(assert-is (map? {:a 1 :b 2}))
@@ -367,9 +367,9 @@ Function signature:
(vector? [x])
```
-Check whether `tbl` is an sequential table.
+Check whether `tbl` is a sequential table.
-Non empty sequential tables are tested for two things:
+Non-empty sequential tables are tested for two things:
- `next` returns the key-value pair,
- key, that is returned by the `next` is equal to `1`.
@@ -379,7 +379,7 @@ see `vector` for creating tables that have additional
metadata attached for this test to work.
### Examples
-Non empty vector:
+Non-empty vector:
``` fennel
(assert-is (vector? [1 2 3 4]))
@@ -571,7 +571,7 @@ Function signature:
(vector [& args])
```
-Constructs sequential table out of it's arguments.
+Constructs sequential table out of its arguments.
Sets additional metadata for function `vector?` to work.
@@ -589,10 +589,10 @@ Function signature:
(seq [coll])
```
-Construct a sequnce from the given collection `coll`. If `coll` is an
-associative table, returns sequence of vectors with key and
-value. If `col` is sequential table, returns its shallow copy. If
-`col` is string, return sequential table of its codepoints.
+Construct a sequence from the given collection `coll`. If `coll` is
+an associative table, returns sequence of vectors with key and value.
+If `col` is sequential table, returns its shallow copy. If `col` is
+string, return sequential table of its codepoints.
### Examples
Sequential tables are transformed to sequences:
@@ -602,7 +602,7 @@ Sequential tables are transformed to sequences:
```
Associative tables are transformed to format like this `[[key1 value1]
-... [keyN valueN]]` and order is non deterministic:
+... [keyN valueN]]` and order is non-deterministic:
``` fennel
(seq {:a 1 :b 2 :c 3}) ;; @seq([:b 2] [:a 1] [:c 3])
@@ -800,7 +800,7 @@ Reduces an associative table using function `f` and initial value `val`.
applying `f` to `val`, the first key and the first value in `tbl`,
then applying `f` to that result and the 2nd key and value, etc. If
`tbl` contains no entries, returns `val` and `f` is not called. Note
-that reduce-kv is supported on sequential tables and strings, where
+that `reduce-kv` is supported on sequential tables and strings, where
the keys will be the ordinals.
Early termination is possible with the use of `reduced`
@@ -841,9 +841,9 @@ Function signature:
Returns a vector consisting of the result of applying `f` to the
set of first items of each `coll`, followed by applying `f` to the set
-of second items in each coll, until any one of the `colls` is exhausted.
-Any remaining items in other colls are ignored. Function `f` should
-accept number-of-colls arguments.
+of second items in each coll, until any one of the `colls` is
+exhausted. Any remaining items in other collections are ignored.
+Function `f` should accept number-of-colls arguments.
## `filter`
Function signature:
@@ -890,7 +890,8 @@ Function signature:
(range ([]) ([upper]) ([lower upper]) ([lower upper step]))
```
-Returns lazy sequence of of numbers from `lower` to `upper` with optional `step`.
+Returns lazy sequence of numbers from `lower` to `upper` with optional
+`step`.
## `reverse`
Function signature:
@@ -899,7 +900,7 @@ Function signature:
(reverse [coll])
```
-Returns a lazy sequnce with same items as in `coll` but in reverse order.
+Returns a lazy sequence with same items as in `coll` but in reverse order.
## `take`
Function signature:
@@ -940,7 +941,7 @@ Given a collection `coll`, returns a lazy sequence of lists of `n`
items each, at offsets `step` apart. If `step` is not supplied,
defaults to `n`, i.e. the partitions do not overlap. If a `pad`
collection is supplied, use its elements as necessary to complete last
-partition upto `n` items. In case there are not enough padding
+partition up to `n` items. In case there are not enough padding
elements, return a partition with less than `n` items.
## `identity`
@@ -970,7 +971,7 @@ Function signature:
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.
+opposite truth value.
## `constantly`
Function signature:
@@ -1069,7 +1070,8 @@ Function signature:
(find [coll key])
```
-Returns the map entry for `key`, or `nil` if key not present in `coll`.
+Returns the map entry for `key`, or `nil` if key is not present in
+`coll`.
## `dissoc`
Function signature:
@@ -1096,7 +1098,7 @@ Function signature:
(remove-all-methods [multimethod])
```
-Removes all of the methods of `multimethod`
+Removes all methods of `multimethod`
## `methods`
Function signature:
@@ -1213,7 +1215,8 @@ Function signature:
(contains? [coll elt])
```
-Test if `elt` is in the `coll`. May be a linear search depending on the type of the collection.
+Test if `elt` is in the `coll`. It may be a linear search depending
+on the type of the collection.
## `count`
Function signature:
@@ -1511,7 +1514,7 @@ Function signature:
Returns a lazy sequence of the non-nil results of (f index item) in
the `coll`. Note, this means false return values will be included.
-`f` must be free of side-effects. Returns a transducer when no
+`f` must be free of side effects. Returns a transducer when no
collection is provided.
## `lazy-seq`
@@ -1548,8 +1551,8 @@ truncated before the file is closed:
```fennel
(let [lines (with-open [f (io.open "init.fnl" :r)]
(line-seq f))]
- ;; this errors because only first line was realized, but the file
- ;; was closed before the rest of lines were cached
+ ;; this will error because only first line was realized, but the
+ ;; file was closed before the rest of lines were cached
(assert-not (pcall next lines)))
```
@@ -1634,7 +1637,7 @@ Function signature:
Returns a lazy sequence consisting of the result of applying `f` to 1
and the first item of `coll`, followed by applying `f` to 2 and the
-second item in `coll`, etc, until `coll` is exhausted. Returns a
+second item in `coll`, etc., until `coll` is exhausted. Returns a
transducer when no collection is provided.
## `mapcat`
@@ -1954,7 +1957,7 @@ Function signature:
```
`reduce` with a transformation of `f` (`xform`). If `init` is not
-supplied, `f` will be called to produce it. f should be a reducing
+supplied, `f` will be called to produce it. `f` should be a reducing
step function that accepts both 1 and 2 arguments, if it accepts only
2 you can add the arity-1 with `completing`. Returns the result of
applying (the transformed) `xform` to `init` and the first item in
diff --git a/doc/macros.md b/doc/macros.md
index d757495..8021db9 100644
--- a/doc/macros.md
+++ b/doc/macros.md
@@ -46,7 +46,7 @@ namespace set with the `ns` macro, unless `:private` was passed before
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.
+string is given, its value is set to `true` in the meta table.
## `defmethod`
Function signature:
@@ -55,7 +55,7 @@ Function signature:
(defmethod multi-fn dispatch-value fnspec)
```
-Attach new method to multi-function dispatch value. accepts the
+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).
@@ -91,14 +91,14 @@ Multi-arity function tails are also supported:
(defmulti foo (fn* ([x] [x]) ([x y] [x y])))
-(defmethod foo [10] [_] (print "I've knew I'll get 10"))
-(defmethod foo [10 20] [_ _] (print "I've knew I'll get both 10 and 20"))
+(defmethod foo [10] [_] (print "I knew I'll get 10"))
+(defmethod foo [10 20] [_ _] (print "I knew I'll get both 10 and 20"))
(defmethod foo :default ([x] (print (.. "Umm, got" x)))
([x y] (print (.. "Umm, got both " x " and " y))))
```
-Calling `(foo 10)` will print `"I've knew I'll get 10"`, and calling
-`(foo 10 20)` will print `"I've knew I'll get both 10 and 20"`.
+Calling `(foo 10)` will print `"I knew I'll get 10"`, and calling
+`(foo 10 20)` will print `"I knew I'll get both 10 and 20"`.
However, calling `foo` with any other numbers will default either to
`"Umm, got x"` message, when called with single value, and `"Umm, got
both x and y"` when calling with two values.
@@ -168,10 +168,10 @@ Function signature:
(defn ([name doc-string? [params*] pre-post? body]) ([name doc-string? ([params*] pre-post? body) +]))
```
-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. Accepts
-`name` wich will be used to refer to a function in the current
+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. Accepts
+`name` which 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.
@@ -183,13 +183,13 @@ Function signature:
(defn- ([name doc-string? [params*] pre-post? body]) ([name doc-string? ([params*] pre-post? body) +]))
```
-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. 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.
+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. Accepts `name` which 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:
@@ -222,7 +222,7 @@ list:
The same syntax applies to multi-arity version.
-(pre and post checks are not yet implemented)
+(pre- and post-checks are not yet implemented)
## `if-let`
Function signature:
@@ -232,7 +232,7 @@ Function signature:
```
When `test` is logical `true`, evaluates the `if-branch` with `name`
-bound to the value of `test`. Otherwise evaluates the `else-branch`
+bound to the value of `test`. Otherwise, evaluates the `else-branch`
## `if-some`
Function signature:
@@ -242,7 +242,7 @@ Function signature:
```
When `test` is not `nil`, evaluates the `if-branch` with `name`
-bound to the value of `test`. Otherwise evaluates the `else-branch`
+bound to the value of `test`. Otherwise, evaluates the `else-branch`
## `in-ns`
Function signature:
@@ -251,11 +251,12 @@ Function signature:
(in-ns name)
```
-Sets the compile time variable `current-ns` to the given `name`.
+Sets the compile-time variable `cljlib-namespaces` to the given `name`.
Affects such macros as `def`, `defn`, which will bind names to the
specified namespace.
### Examples
+Creating several namespaces in the file, and defining functions in each:
```fennel
(ns a)
@@ -273,6 +274,33 @@ specified namespace.
(assert-eq (b.g) "g from b")
```
+Note, switching namespaces in the REPL doesn't affect non-namespaced
+local bindings. In other words, when defining a local with `def`, a
+bot a local binding and a namespaced binding are created, and
+switching current namespace won't change the local binding:
+
+```
+>> (ns foo)
+nil
+>> (def x 42)
+nil
+>> (ns bar)
+nil
+>> (def x 1337)
+nil
+>> (in-ns foo)
+#<namespace: foo>
+>> x ; user might have expected to see 42 here
+1337
+>> foo.x
+42
+>> bar.x
+1337
+```
+
+Sadly, Fennel itself has no support for namespace switching in REPL,
+so this feature can be only partially emulated by the cljlib library.
+
## `lazy-cat`
Function signature:
@@ -291,7 +319,7 @@ Function signature:
(lazy-seq & body)
```
-Takes a `body` of expressions that returns an sequence, table or nil,
+Takes a `body` of expressions that returns a 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?`
@@ -374,6 +402,8 @@ 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`.
+See `in-ns` on how to switch namespaces.
+
## `time`
Function signature:
@@ -401,7 +431,7 @@ 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
+The `finally` clause is optional, and written as (finally body*). If
present, it must be the last clause in the [`try`](#try) form, and the only
`finally` clause. Note that `finally` clause is for side effects
only, and runs either after succesful run of [`try`](#try) body, or after any
diff --git a/init-macros.fnl b/init-macros.fnl
index 034b9aa..0e45c77 100644
--- a/init-macros.fnl
+++ b/init-macros.fnl
@@ -29,10 +29,6 @@ SOFTWARE.")
(fn string? [x]
(= :string (type x)))
-;;; ns
-
-(var current-ns nil)
-
(fn has? [tbl sym]
;; searches for the given symbol in a table.
(var has false)
@@ -40,6 +36,97 @@ SOFTWARE.")
(set has (= sym elt)))
has)
+;;; ns
+
+(local cljlib-namespaces
+ {}
+ ;; A map of files and their respective namespaces. Each entry is a
+ ;; filename followed by a table with two keys: `:current` and
+ ;; `:known`. The second one holds all namespaces that were defined
+ ;; for the file via the `ns` macro, and thus are available to switch
+ ;; with the `in-ns` macro. The `:current` key represents currently
+ ;; active namespace that is used for binding via the `def` macro and
+ ;; its derivatives.
+ )
+
+(fn current-file [ast]
+ (. (ast-source ast) :filename))
+
+(fn create-ns [name]
+ (let [file (current-file name)]
+ (when (not (. cljlib-namespaces file))
+ (tset cljlib-namespaces file {:known {}}))
+ (tset cljlib-namespaces file :current name)
+ (tset cljlib-namespaces file :known (tostring name) true))
+ `(setmetatable
+ {}
+ {:__name "namespace"
+ :__fennelview #(do ,(: "#<namespace: %s>" :format (tostring name)))}))
+
+(fn known-ns? [name]
+ (let [file (current-file name)]
+ (?. cljlib-namespaces file :known (tostring name))))
+
+(fn current-ns [ast]
+ (?. cljlib-namespaces (current-file ast) :current))
+
+(fn in-ns [name]
+ "Sets the compile-time variable `cljlib-namespaces` to the given `name`.
+Affects such macros as `def`, `defn`, which will bind names to the
+specified namespace.
+
+# Examples
+Creating several namespaces in the file, and defining functions in each:
+
+```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\")
+```
+
+Note, switching namespaces in the REPL doesn't affect non-namespaced
+local bindings. In other words, when defining a local with `def`, a
+bot a local binding and a namespaced binding are created, and
+switching current namespace won't change the local binding:
+
+```
+>> (ns foo)
+nil
+>> (def x 42)
+nil
+>> (ns bar)
+nil
+>> (def x 1337)
+nil
+>> (in-ns foo)
+#<namespace: foo>
+>> x ; user might have expected to see 42 here
+1337
+>> foo.x
+42
+>> bar.x
+1337
+```
+
+Sadly, Fennel itself has no support for namespace switching in REPL,
+so this feature can be only partially emulated by the cljlib library.
+"
+ (assert-compile (known-ns? name)
+ (: "no such namespace: %s" :format (tostring name))
+ name)
+ (tset cljlib-namespaces (current-file name) :current name)
+ name)
+
(fn ns [name commentary requirements]
"Namespace declaration macro.
Accepts the `name` of the generated namespace, and creates a local
@@ -73,10 +160,11 @@ Which is equivalent to:
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)
+transformed to `lib`.
+
+See `in-ns` on how to switch namespaces."
(let [bind-table [name]
- require-table [{}]
+ require-table [(create-ns name)]
requirements (if (string? commentary)
requirements
commentary)]
@@ -110,30 +198,6 @@ transformed to `lib`."
(values ,require-table (comment ,commentary)))
`(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
(fn def [...]
@@ -142,19 +206,20 @@ namespace set with the `ns` macro, unless `:private` was passed before
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."
+string is given, its value is set to `true` in the meta table."
:fnl/arglist [([name initializer]) ([meta name initializer])]}
(match [...]
(where (or [:private name val]
[{:private true} name val]))
`(local ,name ,val)
[name val]
- (if (in-scope? current-ns)
- `(local ,name
- (let [v# ,val]
- (tset ,current-ns ,(tostring name) v#)
- v#))
- `(local ,name ,val))))
+ (let [namespace (current-ns name)]
+ (if (in-scope? namespace)
+ `(local ,name
+ (let [v# ,val]
+ (tset ,namespace ,(tostring name) v#)
+ v#))
+ `(local ,name ,val)))))
;;; defn
@@ -303,7 +368,7 @@ list:
The same syntax applies to multi-arity version.
-(pre and post checks are not yet implemented)"
+(pre- and post-checks are not yet implemented)"
:fnl/arglist [([name doc-string? [params*] pre-post? body])
([name doc-string? ([params*] pre-post? body)+])]}
(let [{: name? : doc? : args : pre-post? : body : multi-arity?}
@@ -419,10 +484,10 @@ The same syntax applies to multi-arity version.
(fn defn [name ...]
{: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. Accepts
-`name` wich will be used to refer to a function in the current
+ "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. Accepts
+`name` which 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."
@@ -433,13 +498,13 @@ The body is wrapped in an implicit do. See `fn*` for more info."
(fn defn- [name ...]
{:fnl/docstring
- "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. 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."
+ "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. Accepts `name` which 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)
@@ -470,7 +535,7 @@ to the value of `test`."
(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`"
+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]
@@ -490,7 +555,7 @@ the value of `test`."
(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`"
+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]
@@ -561,7 +626,7 @@ By default, multifunction has no multimethods, see
(fn defmethod [multifn dispatch-val ...]
{:fnl/arglist [multi-fn dispatch-value fnspec]
- :fnl/docstring "Attach new method to multi-function dispatch value. accepts the
+ :fnl/docstring "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*'.
@@ -597,14 +662,14 @@ Multi-arity function tails are also supported:
(defmulti foo (fn* ([x] [x]) ([x y] [x y])))
-(defmethod foo [10] [_] (print \"I've knew I'll get 10\"))
-(defmethod foo [10 20] [_ _] (print \"I've knew I'll get both 10 and 20\"))
+(defmethod foo [10] [_] (print \"I knew I'll get 10\"))
+(defmethod foo [10 20] [_ _] (print \"I knew I'll get both 10 and 20\"))
(defmethod foo :default ([x] (print (.. \"Umm, got\" x)))
([x y] (print (.. \"Umm, got both \" x \" and \" y))))
```
-Calling `(foo 10)` will print `\"I've knew I'll get 10\"`, and calling
-`(foo 10 20)` will print `\"I've knew I'll get both 10 and 20\"`.
+Calling `(foo 10)` will print `\"I knew I'll get 10\"`, and calling
+`(foo 10 20)` will print `\"I knew I'll get both 10 and 20\"`.
However, calling `foo' with any other numbers will default either to
`\"Umm, got x\"` message, when called with single value, and `\"Umm, got
both x and y\"` when calling with two values.
@@ -870,7 +935,7 @@ 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
+The `finally` clause is optional, and written as (finally body*). If
present, it must be the last clause in the `try' form, and the only
`finally' clause. Note that `finally' clause is for side effects
only, and runs either after succesful run of `try' body, or after any
@@ -957,7 +1022,7 @@ the other tests or exprs. `(cond)` returns nil."
"lazy-seq.init-macros")))
(fn lazy-seq [...]
- {:fnl/docstring "Takes a `body` of expressions that returns an sequence, table or nil,
+ {:fnl/docstring "Takes a `body` of expressions that returns a 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?`"
diff --git a/init.fnl b/init.fnl
index 71b2e19..67bbde7 100644
--- a/init.fnl
+++ b/init.fnl
@@ -187,7 +187,7 @@ Applying `add` to different amount of arguments:
(defn complement
"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."
+opposite truth value."
[f]
(fn*
([] (not (f)))
@@ -415,7 +415,7 @@ see `hash-map` for creating tables that have additional metadata
attached for this test to work.
# Examples
-Non empty map:
+Non-empty map:
``` fennel
(assert-is (map? {:a 1 :b 2}))
@@ -445,9 +445,9 @@ Empty tables created with `hash-map` will pass the test:
false))
(defn vector?
- "Check whether `tbl` is an sequential table.
+ "Check whether `tbl` is a sequential table.
-Non empty sequential tables are tested for two things:
+Non-empty sequential tables are tested for two things:
- `next` returns the key-value pair,
- key, that is returned by the `next` is equal to `1`.
@@ -457,7 +457,7 @@ see `vector` for creating tables that have additional
metadata attached for this test to work.
# Examples
-Non empty vector:
+Non-empty vector:
``` fennel
(assert-is (vector? [1 2 3 4]))
@@ -592,7 +592,7 @@ Empty tables created with `vector` will pass the test:
(vec* len)))))
(defn vector
- "Constructs sequential table out of it's arguments.
+ "Constructs sequential table out of its arguments.
Sets additional metadata for function `vector?` to work.
@@ -645,10 +645,10 @@ of bounds, `nth` raises an error unless `not-found` is supplied.
x)
(defn seq
- "Construct a sequnce from the given collection `coll`. If `coll` is an
-associative table, returns sequence of vectors with key and
-value. If `col` is sequential table, returns its shallow copy. If
-`col` is string, return sequential table of its codepoints.
+ "Construct a sequence from the given collection `coll`. If `coll` is
+an associative table, returns sequence of vectors with key and value.
+If `col` is sequential table, returns its shallow copy. If `col` is
+string, return sequential table of its codepoints.
# Examples
Sequential tables are transformed to sequences:
@@ -658,7 +658,7 @@ Sequential tables are transformed to sequences:
```
Associative tables are transformed to format like this `[[key1 value1]
-... [keyN valueN]]` and order is non deterministic:
+... [keyN valueN]]` and order is non-deterministic:
``` fennel
(seq {:a 1 :b 2 :c 3}) ;; @seq([:b 2] [:a 1] [:c 3])
@@ -808,9 +808,9 @@ no collection is provided.
(defn mapv
"Returns a vector consisting of the result of applying `f` to the
set of first items of each `coll`, followed by applying `f` to the set
-of second items in each coll, until any one of the `colls` is exhausted.
-Any remaining items in other colls are ignored. Function `f` should
-accept number-of-colls arguments."
+of second items in each coll, until any one of the `colls` is
+exhausted. Any remaining items in other collections are ignored.
+Function `f` should accept number-of-colls arguments."
([f coll]
(->> coll
(core.transduce (map f)
@@ -822,7 +822,7 @@ accept number-of-colls arguments."
(defn map-indexed
"Returns a lazy sequence consisting of the result of applying `f` to 1
and the first item of `coll`, followed by applying `f` to 2 and the
-second item in `coll`, etc, until `coll` is exhausted. Returns a
+second item in `coll`, etc., until `coll` is exhausted. Returns a
transducer when no collection is provided."
([f]
(fn* [rf]
@@ -883,7 +883,8 @@ is provided."
(some #(not (pred $)) coll))
(defn range
- "Returns lazy sequence of of numbers from `lower` to `upper` with optional `step`."
+ "Returns lazy sequence of numbers from `lower` to `upper` with optional
+`step`."
([] (seq* (lazy.range)))
([upper] (seq* (lazy.range upper)))
([lower upper] (seq* (lazy.range lower upper)))
@@ -895,7 +896,7 @@ is provided."
(seq* (apply lazy.concat colls)))
(defn reverse
- "Returns a lazy sequnce with same items as in `coll` but in reverse order."
+ "Returns a lazy sequence with same items as in `coll` but in reverse order."
[coll]
(seq* (lazy.reverse coll)))
@@ -1052,7 +1053,7 @@ provided."
(defn keep-indexed
"Returns a lazy sequence of the non-nil results of (f index item) in
the `coll`. Note, this means false return values will be included.
-`f` must be free of side-effects. Returns a transducer when no
+`f` must be free of side effects. Returns a transducer when no
collection is provided."
([f]
(fn* [rf]
@@ -1074,7 +1075,7 @@ collection is provided."
items each, at offsets `step` apart. If `step` is not supplied,
defaults to `n`, i.e. the partitions do not overlap. If a `pad`
collection is supplied, use its elements as necessary to complete last
-partition upto `n` items. In case there are not enough padding
+partition up to `n` items. In case there are not enough padding
elements, return a partition with less than `n` items."
([n coll] (map seq* (lazy.partition n coll)))
([n step coll] (map seq* (lazy.partition n step coll)))
@@ -1164,7 +1165,8 @@ per reduce) of `coll` by `f`, starting with `init`."
([f init coll] (seq* (lazy.reductions f init coll))))
(defn contains?
- "Test if `elt` is in the `coll`. May be a linear search depending on the type of the collection."
+ "Test if `elt` is in the `coll`. It may be a linear search depending
+on the type of the collection."
[coll elt]
(lazy.contains? coll elt))
@@ -1246,8 +1248,8 @@ truncated before the file is closed:
```fennel
(let [lines (with-open [f (io.open \"init.fnl\" :r)]
(line-seq f))]
- ;; this errors because only first line was realized, but the file
- ;; was closed before the rest of lines were cached
+ ;; this will error because only first line was realized, but the
+ ;; file was closed before the rest of lines were cached
(assert-not (pcall next lines)))
```
@@ -1414,7 +1416,8 @@ unaffected."
(lazy.vals coll)))
(defn find
- "Returns the map entry for `key`, or `nil` if key not present in `coll`."
+ "Returns the map entry for `key`, or `nil` if key is not present in
+`coll`."
[coll key]
(assert (or (map? coll) (empty? coll)) "expected a map")
(match (. coll key)
@@ -1528,7 +1531,7 @@ called. Early termination is supported via `reduced`.
applying `f` to `val`, the first key and the first value in `tbl`,
then applying `f` to that result and the 2nd key and value, etc. If
`tbl` contains no entries, returns `val` and `f` is not called. Note
-that reduce-kv is supported on sequential tables and strings, where
+that `reduce-kv` is supported on sequential tables and strings, where
the keys will be the ordinals.
Early termination is possible with the use of `reduced`
@@ -1577,7 +1580,7 @@ suitable for transduce by adding an arity-1 signature that calls
(defn transduce
"`reduce` with a transformation of `f` (`xform`). If `init` is not
-supplied, `f` will be called to produce it. f should be a reducing
+supplied, `f` will be called to produce it. `f` should be a reducing
step function that accepts both 1 and 2 arguments, if it accepts only
2 you can add the arity-1 with `completing`. Returns the result of
applying (the transformed) `xform` to `init` and the first item in
@@ -2212,7 +2215,7 @@ from `macros.fnl'."
multimethod)
(defn remove-all-methods
- "Removes all of the methods of `multimethod'"
+ "Removes all methods of `multimethod'"
[multimethod]
(if (multifn? multimethod)
(each [k _ (pairs multimethod)]