Janet Notes and Examples

Looping

Convenient side-effecty looping over data structures:

  • each : loop over each value in a ds
  • eachk : loop over each key in a ds
  • eachp : loop over each pair in a ds

plus:

  • loop : General looping (use seq similarly for list comprehensions)
  • while
  • for : C-style looping
# Arrays --------------------
(def a @[44 55 66])

(each  e a (pp e))  # 44, 55, 66
(eachk i a (pp i))  # 0, 1, 2
(eachp p a (pp p))  # 2-element tuples:
# (0 44)
# (1 55)
# (2 66)
# Or unpack the indices and elements as you go:
(eachp [i e] a (pp (string i "-->" e)))

# Tables --------------------
(def t @{:a 1 :b 2 :c 3})

(each  v t (pp v))  # 3, 1, 2
(eachk k t (pp k))  # :c, :a, :b
(eachp p t (pp p))  # 2-element tuples:
# (:c 3)
# (:a 1)
# (:b 2)
# Or unpack the keys and values as you go:
(eachp [k v] t (pp (string k "-->" v)))

# Strings --------------------
# Those all also work on strings too, where the values are
# decimal integer byte values.

# General looping --------------------
# The loop "head" is the tuple it starts with. The head may
# contain:
#
#   - "bindings"     (3 parts: "binding :verb object/expression") and
#   - "conditionals" (2 parts: ":modifier argument").

(loop [n :range [4 7]] # loop head contains one binding
  (pp n))  # 4, 5, 6

(loop [n :range [1 7]      # binding
       :when (odd? n)      # conditional
       :let [m (+ n 10)]]  # conditional
  (pp (string n "--" m)))
# "1--11"
# "3--13"
# "5--15"

(loop [n :range [1 5]     # binding
       m :range [14 16]]  # binding
  (pp (string n "--" m)))
# "1--14"
# "1--15"
# "2--14"
# "2--15"
# "3--14"
# "3--15"
# "4--14"
# "4--15"

(loop [x :in [22 33 44]]
  (pp x))
# 22
# 33
# 44

(loop [x :pairs {:a 1 :b 2 :c 3}]
  (pp x))
# (:c 3)
# (:a 1)
# (:b 2)

(loop [[k v] :pairs {:a 1 :b 2 :c 3}]
  (pp (string k "--" v)))
# "c--3"
# "a--1"
# "b--2"

# Use `:iterate` to tell the loop how to compute
# the next local loop value (here, `i`).
(var n 2)
(defn foo [x] (* 2 x))
(loop [i :iterate (foo n)
       :while (< n 1000)
       :after (set n i)]
  (pp i))

# though, you could also accomplish that with something like:
(while (< n 1000)
  (pp n)
  (set n (foo n)))

# or
(for _ 1 10
  (pp n)
  (set n (foo n)))

# And speaking of `for`...

# C-style looping --------------------
(for i 0 5 (pp i))  # counts 0 to 4

Where there’s no side-effects, you can do list comprehensions with seq, which otherwise works similarly to loop.