Slices in Clojure

Clojure provides a powerful and flexible way to work with sequences, which are similar to slices in other languages. Let’s explore how to use them.

(ns clojure-slices-example.core
  (:require [clojure.string :as str]))

(defn main []
  ;; In Clojure, we use vectors as a common sequence type.
  ;; An empty vector is represented by [].
  (let [s []]
    (println "uninit:" s (empty? s) (zero? (count s))))

  ;; To create a vector with initial values, we can use the vector function
  ;; or simply use the literal syntax.
  (let [s (vector "a" "b" "c")]
    (println "init:" s "len:" (count s)))

  ;; We can get and set values in a vector using standard functions.
  (let [s ["a" "b" "c"]]
    (println "get:" (get s 2))
    (println "set:" (assoc s 1 "d")))

  ;; To add elements to a vector, we use the conj function.
  (let [s ["a" "b" "c"]
        s (conj s "d")
        s (apply conj s ["e" "f"])]
    (println "apd:" s))

  ;; To copy a sequence, we can use the into function.
  (let [s ["a" "b" "c" "d" "e" "f"]
        c (into [] s)]
    (println "cpy:" c))

  ;; Clojure provides powerful sequence operations like subvec for slicing.
  (let [s ["a" "b" "c" "d" "e" "f"]]
    (println "sl1:" (subvec s 2 5))
    (println "sl2:" (subvec s 0 5))
    (println "sl3:" (subvec s 2)))

  ;; We can create and initialize a vector in a single line.
  (let [t ["g" "h" "i"]]
    (println "dcl:" t))

  ;; Clojure has built-in equality comparison for sequences.
  (let [t ["g" "h" "i"]
        t2 ["g" "h" "i"]]
    (when (= t t2)
      (println "t == t2")))

  ;; We can create nested vectors to represent multi-dimensional data structures.
  (let [two-d (vec (for [i (range 3)]
                     (vec (for [j (range (inc i))]
                            (+ i j)))))]
    (println "2d:" two-d)))

(main)

To run this Clojure program, you would typically use a Clojure REPL or build tool like Leiningen. Here’s an example of how you might run it using Leiningen:

$ lein run
uninit: [] true true
init: [a b c] len: 3
get: c
set: [a d c]
apd: [a b c d e f]
cpy: [a b c d e f]
sl1: [c d e]
sl2: [a b c d e]
sl3: [c d e f]
dcl: [g h i]
t == t2
2d: [[0] [1 2] [2 3 4]]

Note that Clojure’s approach to sequences is quite different from languages with mutable arrays. Clojure emphasizes immutable data structures and functional programming paradigms. The vector type in Clojure is immutable, so operations like assoc and conj return new vectors rather than modifying the original.

Clojure’s sequence abstractions provide a rich set of functions for working with collections, making it very powerful for data manipulation tasks.