summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Orst <andreyorst@gmail.com>2020-10-22 23:03:42 +0300
committerAndrey Orst <andreyorst@gmail.com>2020-10-22 23:03:42 +0300
commite16763df4de9e198adf48d746407d43fa5538221 (patch)
tree3015c6d25357f88fd0e4493de2e6d597136d96ad
parent54a83a9f0506804a597875f3eaf4de874bf6762f (diff)
changes
fix eq? for empty tables rewrite parts of the readme simplify functions rest and check-bindings
-rw-r--r--README.org35
-rw-r--r--core.fnl14
-rw-r--r--macros/core.fnl6
3 files changed, 31 insertions, 24 deletions
diff --git a/README.org b/README.org
index c17a02e..0937797 100644
--- a/README.org
+++ b/README.org
@@ -1,10 +1,9 @@
-
* Fennel Cljlib
-Library for [[https://fennel-lang.org/][Fennel]] language that adds a lot of functions from [[https://clojure.org/][Clojure]] standard library.
-This is not a one to one port of Clojure =core=, because many Clojure functions require certain guarantees, like immutability of the underlying data structures.
+Experimental library for [[https://fennel-lang.org/][Fennel]] language, that adds many functions from [[https://clojure.org/][Clojure]]'s standard library.
+This is not a one to one port of Clojure =core=, because many Clojure functions require certain guarantees, like immutability of the underlying data structures, or laziness.
Therefore some names were changed, but they should be still recognizable.
-Goals of this project are:
+Even though it is project is experimental, the goals of this project are:
- Have a self contained library, with no dependencies, that provides a set of useful functions from Clojure =core=,
- Be close to the platform, e.g. implement functions in a way that is efficient to use in Lua VM,
@@ -155,20 +154,17 @@ It also calls =seq= on it's argument.
#+end_src
*** =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.
-Both functions return the resulting table, so it is possible to nest these, or build a classic =map=:
+
+=cons= accepts value as its first argument and table as second, and puts value to the front of the table:
#+begin_src fennel
- (fn map [f col]
- (if-some [val (first col)]
- (cons (f val) (map f (rest col)))
- []))
+ (cons 1 [2 3])
+ ;; [1 2 3]
#+end_src
-=cons= accepts value as its first argument and table as second and puts value to the front of the table.
-=col= is not modified by the =map= function described above, but the =[]= table in the =else= branch of =is-some= is.
-
=conj= accepts table as it's first argument and any amount of values afterwards.
It puts values in order given into the table:
@@ -177,6 +173,19 @@ It puts values in order given into the table:
; [1 2 3]
#+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= and =mapkv=
Mapping functions.
In Clojure we have a =seq= abstraction, that allows us to use single =mapv= on both vectors, and hash tables.
@@ -228,4 +237,4 @@ Then it maps function over the associative map, by passing initial value as a fi
;; 20
#+end_src
-# LocalWords: Luajit VM
+# LocalWords: Luajit VM arity runtime multi Cljlib fn
diff --git a/core.fnl b/core.fnl
index 4890554..eba11d6 100644
--- a/core.fnl
+++ b/core.fnl
@@ -3,10 +3,11 @@
(import-macros {: fn*} :macros.fn)
(fn seq [tbl]
- "Return sequential table.
+ "Create sequential table.
Transforms original table to sequential table of key value pairs
-stored as sequential tables in linear time. If original table is
-sequential table, leaves it unchanged."
+stored as sequential tables in linear time. If `tbl' is an
+associative table, returns `[[key1 value1] ... [keyN valueN]]' table.
+If `tbl' is sequential table, leaves it unchanged."
(var assoc? false)
(let [res []]
(each [k v (pairs tbl)]
@@ -23,8 +24,7 @@ sequential table, leaves it unchanged."
(fn rest [itbl]
"Returns table of all elements of indexed table but the first one."
- (let [[_ & xs] (seq itbl)]
- xs))
+ [(_unpack itbl 2)])
(fn* conj
@@ -175,8 +175,8 @@ sorting tables first."
([x] true)
([x y]
(if (and (= (type x) "table") (= (type y) "table"))
- (and (reduce #(and $1 $2) (mapv (fn [[k v]] (eq? (. y k) v)) (kvseq x)))
- (reduce #(and $1 $2) (mapv (fn [[k v]] (eq? (. x k) v)) (kvseq y))))
+ (and (reduce #(and $1 $2) true (mapv (fn [[k v]] (eq? (. y k) v)) (kvseq x)))
+ (reduce #(and $1 $2) true (mapv (fn [[k v]] (eq? (. x k) v)) (kvseq y))))
(= x y)))
([x y & xs]
(reduce #(and $1 $2) (eq? x y) (mapv #(eq? x $) xs))))
diff --git a/macros/core.fnl b/macros/core.fnl
index 7c8af40..deb363a 100644
--- a/macros/core.fnl
+++ b/macros/core.fnl
@@ -3,10 +3,8 @@
(local insert table.insert)
(fn check-bindings [bindings]
- (assert-compile (sequence? bindings) "expected binding table
-
-* Try placing a table here in square brackets containing identifiers to bind." bindings)
- (assert-compile (= (length bindings) 2) "expected exactly two forms in binding vector." bindings))
+ (and (assert-compile (sequence? bindings) "expected binding table" [])
+ (assert-compile (= (length bindings) 2) "expected exactly two forms in binding vector." bindings)))
(fn* if-let
([bindings then]