Janet Notes and Examples

More Working With Data Structures

(def a [1 2 3])
(map some-fn a)

(map + [1 2 3] [4 5 6])        #=> @[5 7 9]
(map tuple [1 2] [3 4] [5 6])  #=> @[(1 3 5) (2 4 6)]
(zipcoll [:a :b :c] [1 2 3])   #=> @{:c 3 :a 1 :b 2}

# Use `;` ("splice") to unpack values:
(def a [1 2 3]) # a tuple
(array ;a)      #=> @[1 2 3]

(filter even? (range 10))                      #=> @[0 2 4 6 8]
(interleave [:a :b :c] [1 2 3] ["x" "y" "z"])  #=> @[:a 1 x :b 2 y :c 3 z]
(interpose 100 (range 5))                      #=> @[0 100 1 100 2 100 3 100 4]

(frequencies [:w :w :x :w :y :y])              #=> @{:w 3 :x 1 :y 2}

(map |($ :type)
     [{:type "cat" :name "Fluffy"}
      {:type "dog" :name "Spot"}])
#=> @["cat" "dog"]

(map string/from-bytes "hello")
#=> @["h" "e" "l" "l" "o"]

(def t {:a 1 :b 2 :c 3})
(kvs t)    #=> @[:c 3 :a 1 :b 2]
(pairs t)  #=> @[(:c 3) (:a 1) (:b 2)]

# Make a new table from a struct:
(table ;(kvs my-struct)) # or
(merge my-struct)

# My own `cycle`.
(def a [44 55 66])

(defn cycle
  [a n]
  (let [ln (length a)]
    (seq [i :range [0 n]]
      (a (% i ln)))))

(pp (cycle a 8)) #=> @[44 55 66 44 55 66 44 55]

# Note, although Janet doesn't support lazy evaluation per se, you could
# return a "thunk" --- function you will possibly call later on for its return
# value. If you never call/realize the thunk, then no work is done.
(def data [3 2 1])
(def sorted-data-thunk |(sorted data))
# Later...
(def sdata (sorted-data-thunk))

Lazy Seqs

You can do these manually. See https://github.com/janet-lang/janet/blob/master/examples/lazyseqs.janet.

Sorting

Note that sort and sort-by sort in-place, whereas sorted and sorted-by return a new sorted array. Also note:

  • The function you pass as the 2nd arg to sort must be able to take two args and compare them returning a boolean (like >, <, etc.).
  • The function you pass to sort-by just takes one arg: the object you look at to figure out the value you want to sort on, which is what it then returns. Then < is used by default to sort by that.

For example:

(def a @[22 11 55 44])
(sort a)
(sort a >)   # instead of `<`

(defn f [x] (get-some-value-from x))
(sort-by f a)

See also the Janet docs on comparison operators.

any?, every?, some

any? is an optimist. It goes through the array looking for and returning the first truthy value it finds (otherwise returns nil).

every? is a pessimist. It goes through and only returns true if every value is truthy (otherwise returns the first falsey value it finds).

some needs you to first pass it a predicate function, and goes through the array calling that pred on each item; if that pred call returns truthy, then that truthy return value is returned.

If you want a function that takes a pred and a list, and returns the first item for which (pred item) returns truthy, then you’ll have to write that one yourself as shown below. You could also use find.

(any? [nil false "hey" 5 nil])  #=> "hey"

(every? [0 1 "hey"])            #=> true
(every? [0 1 "hey" false 7])    #=> false
(every? [0 1 "hey" nil   7])    #=> nil

(some even? [43 45 46 49])      #=> true
(some even? [43 45 47 49])      #=> nil

(some (fn [n]
        (if (even? n) n))
      [43 45 46 49])            #=> 46

(find even? [43 45 46 49])      #=> 46
(find even? [43 45 47 49])      #=> nil

(find-index even?
            [43 45 46 49])      #=> 2