summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Listopadov <andreyorst@gmail.com>2022-08-25 23:20:45 +0300
committerAndrey Listopadov <andreyorst@gmail.com>2022-08-25 23:23:17 +0300
commitf98e3fa8712a6fb5f4d49233123318104eab7bc3 (patch)
tree4e1489365734f6067a0d35a1155f3750222e9575
parent3f738c3368ddaadbaa4372443cece90651d1ccd2 (diff)
make vector support nils, implement pop on vectors and sequences
-rw-r--r--CHANGELOG.md12
-rw-r--r--init.fnl45
2 files changed, 44 insertions, 13 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 382dd41..39c8a08 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,16 @@
+## Cljlib dev (???)
+
+- Vectors can store `nil` values
+- Add `pop` operation for vectors and sequences
+
## Cljlib v1.0.0 (2022-08-21)
+
Full rewrite of the library.
This library now requires the minimum Fennel version 1.2.0.
(Fennel v1.2.0 isn't yet released at the moment of cljlib v1.0.0 release, use the build from the `main` branch).
### New features
+
- added [lazy-seq](https://gitlab.com/andreyorst/lazy-seq) as a dependency, and made all sequence functions use it
- added [itable](https://gitlab.com/andreyorst/itable) as a dependency, and made all tables immutable by default
- implemented transducers
@@ -11,19 +18,22 @@ This library now requires the minimum Fennel version 1.2.0.
- added `ns` macro
### Changes
+
- `fn*` no longer splits multisyms and doesn't bind both local and namespaced versions
- `fn*` is for anonymous functions, it doesn't create a local binding
- `def` now binds in terms of the namespace, specified by `ns`
- `def` no longer support documentation metadata
### Removed features
+
- removed `ordered-set` and `ordered-map`
- `into` is no longer a macro
- `empty` is no longer a macro
- removed metadata-related macros
### Fixes
-- #1 has been fixed, and `fn*` now generates multi-value destructuring when possible.
+
+- [#1](https://gitlab.com/andreyorst/fennel-cljlib/-/issues/1) has been fixed, and `fn*` now generates multi-value destructuring when possible.
## Cljlib v0.5.4 (2021-07-22)
diff --git a/init.fnl b/init.fnl
index 361208b..321bd12 100644
--- a/init.fnl
+++ b/init.fnl
@@ -546,21 +546,31 @@ Empty tables created with `vector` will pass the test:
(immutable (itable v))))}
(setmetatable {}))))
-(fn vec* [v]
+(fn vec* [v len]
(match (getmetatable v)
mt (doto mt
+ (tset :__len (constantly (or len (length* v))))
(tset :cljlib/type :vector)
(tset :cljlib/editable true)
(tset :cljlib/conj
- (fn [t v] (vec* (itable.insert t v))))
+ (fn [t v]
+ (let [len (length* t)]
+ (vec* (itable.assoc t (+ len 1) v) (+ len 1)))))
+ (tset :cljlib/pop
+ (fn [t]
+ (let [len (- (length* t) 1)
+ coll []]
+ (for [i 1 len]
+ (tset coll i (. t i)))
+ (vec* (itable coll) len))))
(tset :cljlib/empty
(fn [] (vec* (itable []))))
(tset :cljlib/transient (vec->transient vec*))
(tset :__fennelview (fn [coll view inspector indent]
(if (empty? coll)
"[]"
- (let [lines (icollect [_ v (ipairs coll)]
- (.. " " (view v inspector indent)))]
+ (let [lines (fcollect [i 1 (length* coll)]
+ (.. " " (view (. coll i) inspector indent)))]
(tset lines 1 (.. "[" (string.gsub (or (. lines 1) "") "^%s+" "")))
(tset lines (length lines) (.. (. lines (length lines)) "]"))
lines)))))
@@ -570,14 +580,14 @@ Empty tables created with `vector` will pass the test:
(defn vec
"Coerce collection `coll` to a vector."
[coll]
- (cond (empty? coll) (vec* (itable []))
- (vector? coll) (vec* (itable coll))
- :else (-> coll
- core.seq
- lazy.pack
- (doto (tset :n nil))
- itable
- vec*)))
+ (cond (empty? coll) (vec* (itable []) 0)
+ (vector? coll) (vec* (itable coll) (length* coll))
+ :else (let [packed (-> coll core.seq lazy.pack)
+ len packed.n]
+ (-> packed
+ (doto (tset :n nil))
+ (itable {:fast-index? true})
+ (vec* len)))))
(defn vector
"Constructs sequential table out of it's arguments.
@@ -1950,6 +1960,17 @@ specified `key` or `keys`."
{:cljlib/type :hash-set :cljlib/disj f} (apply f Set key keys)
_ (error (.. "disj is not supported on " (class Set)) 2))))
+(defn pop
+ "For a list or queue, returns a new list/queue without the first
+item, for a vector, returns a new vector without the last item. If
+the collection is empty, throws an exception. Note - not the same
+as next/butlast."
+ [coll]
+ (match (getmetatable coll)
+ {:cljlib/type :seq} (drop 1 coll)
+ {:cljlib/pop f} (f coll)
+ _ (error (.. "pop is not supported on " (class coll)) 2)))
+
;;; Transients
(defn transient