# Arrays and Tuples

Recall:

 tuple: immutable `[1 2 3]` array: mutable `@[1 2 3]`
``````(type  [1 2 3])  # => :tuple
(type '(1 2 3))  # => :tuple ' # Please don't write tuple literals like this.
(type @[1 2 3])  # => :array
(type @(1 2 3))  # => :array   # Please don't write array literals like this.

(def a @[44 55 66])
(length a)  # => 3

# Can also make an array with:
(array 44 55 66)  # => @[44 55 66]

(keys a)  # => @[0 1 2]

(a 1)               # => 55
(get a 1)           # same
(in  a 1)           # same
(get a 5)           # => nil
(in  a 5)           # ERROR (not in range)
(get a 5 :default)  # => :default

# This works too... though it makes me shift uneasily in my chair.
(1 a)  # => 55

(last a)                  # => 66
(get a (- (length a) 1))  # same

# Cannot use negative indices with `get` (but you *can* with
# `slice` (see below)).

# Change the second element in `a`.
# `a` is              @[44  55 66]
(put a 1 100)       # @[44 100 66]
(array/push a 200)  # @[44 100 66 200]

# Fills in the empty slots with `nil`s.
(put a 6 99)        # @[44 100 66 200 nil nil 99]

# Remove and return the last element of the array.
(array/pop a)       # => 99
# `a` is              @[44 100 66 200 nil nil]

# You can also use the `set` special.
# `a` is              @[44 100 66 200 nil nil]
(set (a 5) 88)      # @[44 100 66 200 nil 88 ]

# Get (but don't remove) last element (like Python's `a[-1]`).
(array/peek a)  # => 88  (Note, only works on arrays (not tuples).)
# `a` is still        @[44 100 66 200 nil 88]

# To get a slice (subarray) of an array:
(def b                    @[44 55 66 77 88 99])
(slice       b 2 5)  # =>   [      66 77 88   ]  --- returns a tuple
(array/slice b 2 5)  # =>  @[      66 77 88   ]  --- `b` is unchanged.

# Can use negative indices in `slice` and `array/slice`.
(slice b 2 -2)  # => (66 77 88)

# These work just like you'd expect:
array/concat   # Concats everything into the first arg.
array/fill

# To insert single or multiple values into an array starting at a given index:
# `b`                          @[44 55         66 77 88         99]
(array/insert b  2 100 200)  # @[44 55 100 200 66 77 88         99]
(array/insert b -2 440 540)  # @[44 55 100 200 66 77 88 440 540 99]

(array/new-filled 5 :hi)   # => @[:hi :hi :hi :hi :hi]

# `array/remove` removes one or more elements from an array.
# `b`                    @[44 55 100 200 66 77 88 440 540 99]
(array/remove b 6  )   # @[44 55 100 200 66 77    440 540 99]
(array/remove b 1 3)   # @[44 66            77    440 540 99]
(array/remove b 2 99)  # @[44 66                            ]  --- Ok going past end.
# Can also use negative index here for index from end of array.

# So, to add and remove from the *front*:
(def a3 @[44 55])
(array/insert a3 0 11)  # @[11 44 55]
(array/remove a3 0)     # @[44 55]

(drop 3 [22 33 44 55 66])  # => (55 66)
# `take`, `take-until`, `take-while`.

(partition 2 [30 31 32 33 34 35])  # => @[(30 31) (32 33) (34 35)]

# De-dupe (remove duplicates, or uniq) a tuple or array:
(distinct [1 1 2 2 2 3])  # => @[1 2 3]

# Check if an element is in an array:
(def a4 [55 56 57 58 59])
(index-of 57 a4)  # => 2
(index-of 60 a4)  # => nil

# Find the first element that satisfies some predicate:
(find even? a4)      # => 56
(find |(> \$ 58) a4)  # => 59
(find |(> \$ 60) a4)  # => nil

# Convert a string to a tuple of integer byte values
(string/bytes "abc")          # => (97 98 99)
# Back to a string
(string/from-bytes 97 98 99)  # => "abc"``````