Janet bindings for immer, a library of immutable data structures.
(use jimmy)
(def good-numbers (set/new 1 2 3 4 5))
(print good-numbers)
#| {2 3 5 1 4}
# actually, five kinda sucks
(print (set/remove good-numbers 5))
#| {2 3 1 4}
# but it was persistent all along!!
(print good-numbers)
#| {2 3 5 1 4}
# sets support union/intersect/difference, and
# operators are standing by
(print (- good-numbers (set/new 1 2)))
#| {3 5 4}
You can (use jimmy)
to bring all types into scope as set/new
, map/new
, etc., or you can (import jimmy/set)
to only bring a specific submodule into scope.
Note: the jimmy/map
module is extremely incomplete.
(set/add set & xs)
Returns a new set containing all of the elements from the original set and all of the subsequent arguments.
(set/count set pred)
Returns the number of elements in the set that match the given predicate. pred
can be any callable value, not just a function.
Note that the arguments are in a different order than Janet's count
function.
(set/difference set & sets)
Returns a set that is the first set minus all of the latter sets.
(set/filter set pred)
Returns a set containing only the elements for which the predicate returns a truthy value. pred
can be any callable value, not just a function.
Note that the arguments are in the opposite order of Janet's filter
function.
(set/filter-map set f)
Like set/map
, but excludes nil
. f
can be any callable value, not just a function.
(set/intersection & sets)
Returns a set that is the intersection of all of its arguments. Naively folds when given more than two arguments.
(set/map set f)
Returns a new set derived from the given transformation function. f
can be any callable value, not just a function.
Note that the arguments are in the opposite order of Janet's map
function.
(set/new & xs)
Returns a persistent immutable set containing only the listed elements.
(set/of iterable)
Returns a set of all the values in an iterable data structure.
(set/of-keys iterable)
Returns a set of all the keys in an iterable data structure.
(set/reduce set init f)
Returns a reduction of the elements in the set, which will be traversed in arbitrary order. f
can be any callable value, not just a function.
Note that the arguments are in a different order than Janet's reduce
function.
(set/remove set & xs)
Returns a new set containing all of the elements from the original set except any of the subsequent arguments.
(set/strict-subset? a b)
Returns true if a
is a strict subset of b
.
(set/strict-superset? a b)
Returns true if a
is a strict superset of b
.
(set/subset? a b)
Returns true if a
is a subset of b
.
(set/superset? a b)
Returns true if a
is a superset of b
.
(set/to-array set)
Returns an array of all of the elements in the set, in no particular order.
(set/to-tuple set)
Returns a tuple of all of the elements in the set, in no particular order.
(set/union & sets)
Returns a set that is the union of all of its arguments.
:+
is an alias forset/union
:*
is an alias forset/intersection
:-
is an alias forset/difference
set/empty
is the empty set
(map/keys map)
Returns an iterator over the keys in the map.
(map/new & kvs)
Returns a persistent immutable map containing the listed entries.
(map/pairs map)
Returns an iterator over the key-value pairs in the map.
(map/values map)
Returns an iterator over the values in the map.
map/empty
is the empty map
(vec/count vec pred)
Returns the number of elements in the vector that match the given predicate. pred
can be any callable value, not just a function.
Note that the arguments are in a different order than Janet's count
function.
(vec/filter vec pred)
Returns a vector containing only the elements for which the predicate returns a truthy value. pred
can be any callable value, not just a function.
Note that the arguments are in the opposite order of Janet's filter
function.
(vec/filter-map vec f)
Like vec/map
, but excludes nil
. f
can be any callable value, not just a function.
(vec/first vec)
Returns the first element of the vector.
(vec/last vec)
Returns the last element of the vector.
(vec/map vec f)
Returns a new vector derived from the given transformation function. f
can be any callable value, not just a function.
Note that the arguments are in the opposite order of Janet's map
function.
(vec/new & xs)
Returns a persistent immutable vector containing only the listed elements.
(vec/of iterable)
Returns a vector of all the values in an iterable data structure.
(vec/pop vec)
Returns a new vector with the last element removed.
(vec/popn vec)
Returns a new vector with the last n elements removed.
(vec/push vec & xs)
Returns a new vector containing all of the elements from the original and all of the subsequent arguments.
(vec/put vec n val)
Returns a new vector with nth element set to val.
(vec/reduce vec init f)
Returns a reduction of the elements in the vector. f
can be any callable value, not just a function.
Note that the arguments are in a different order than Janet's reduce
function.
(vec/take vec n)
Returns a new vector containing the first n elements of vec, or all of vec if n >= (length vec).
(vec/to-array vec)
Returns an array of all of the elements in the vector.
(vec/to-tuple vec)
Returns a tuple of all of the elements in the vector.
vec/empty
is the empty vector
Janet's iteration protocol is not flexible enough for Jimmy to support eachk
or eachp
or the :keys
and :pairs
directive in loop
-family macros.
Unlike Janet's tables and structs, Jimmy data structures can contain nil
:
repl:1:> (use jimmy)
repl:2:> (set/new 1 2 3 nil)
<jimmy/set {3 1 nil 2}>
repl:3:> (map/new nil :value :key nil)
<jimmy/map {nil :value :key nil}>
Iterating over a map with each
will iterate over key-value pairs, not just values. To iterate over values, use:
(each value (map/values map)
(print value))
You should not use eachk
or eachp
with Jimmy maps, because next
returns an iterator, not a key. To iterate over the keys in a map, use:
(each value (map/keys map)
(print value))
In order to support iteratation with Janet's next
protocol for unordered containers, Jimmy boxes the corresponding C++ iterator into an abstract type to use as the key. This means that a simple (each el set (print el))
will allocate memory for the abstract type containing the iterator. It's not a lot of memory, but it's short-lived garbage and Janet's GC currently does nothing to optimize for short-lived garbage. This probably won't cause performance problems, just something to bear in mind.
Also, I don't know C++, which is sort of a flaw when trying to write bindings for a C++ library, so I would caution you to read the code with a very critical eye. Code review welcome!
- add bindings for
immer::map
- 1.0 release