Slices in Racket

#lang racket

(require racket/vector)

;; Slices are an important data type in Racket, giving
;; a more powerful interface to sequences than arrays.

;; Unlike arrays, vectors in Racket are dynamically sized.
;; An uninitialized vector is empty and has length 0.
(define s (vector))
(printf "uninit: ~a ~a ~a\n" s (empty? s) (= (vector-length s) 0))

;; To create an empty vector with non-zero length, use
;; make-vector. Here we make a vector of length 3
;; (initially filled with #f).
(set! s (make-vector 3))
(printf "emp: ~a len: ~a\n" s (vector-length s))

;; We can set and get just like with arrays.
(vector-set! s 0 "a")
(vector-set! s 1 "b")
(vector-set! s 2 "c")
(printf "set: ~a\n" s)
(printf "get: ~a\n" (vector-ref s 2))

;; vector-length returns the length of the vector as expected.
(printf "len: ~a\n" (vector-length s))

;; In addition to these basic operations, vectors support
;; several more that make them richer than arrays. One is
;; vector-append, which returns a new vector containing
;; the elements of the original vector plus additional elements.
(set! s (vector-append s (vector "d")))
(set! s (vector-append s (vector "e" "f")))
(printf "apd: ~a\n" s)

;; Vectors can also be copied. Here we create a new vector c
;; and copy the contents of s into it.
(define c (vector-copy s))
(printf "cpy: ~a\n" c)

;; Racket supports "slicing" of vectors using vector-take and vector-drop.
;; This gets a new vector of the elements s[2], s[3], and s[4].
(define l (vector-take (vector-drop s 2) 3))
(printf "sl1: ~a\n" l)

;; This slices up to (but excluding) s[5].
(set! l (vector-take s 5))
(printf "sl2: ~a\n" l)

;; And this slices up from (and including) s[2].
(set! l (vector-drop s 2))
(printf "sl3: ~a\n" l)

;; We can declare and initialize a vector in a single line as well.
(define t (vector "g" "h" "i"))
(printf "dcl: ~a\n" t)

;; Racket's vector-equal? function can be used to compare vectors.
(define t2 (vector "g" "h" "i"))
(when (vector-equal? t t2)
  (printf "t == t2\n"))

;; Vectors can be composed into multi-dimensional data
;; structures. The length of the inner vectors can
;; vary, unlike with multi-dimensional arrays.
(define twoD
  (for/vector ([i (in-range 3)])
    (for/vector ([j (in-range (add1 i))])
      (+ i j))))
(printf "2d: ~a\n" twoD)

Note that while vectors in Racket are different from slices in Go, they serve a similar purpose as dynamically-sized, indexed collections. Racket doesn’t have a direct equivalent to Go’s slices, so we’ve used vectors and vector operations to demonstrate similar concepts.

To run this program, you would typically save it to a file (e.g., vectors.rkt) and then run it using the Racket interpreter:

$ racket vectors.rkt
uninit: #() #t #t
emp: #(#f #f #f) len: 3
set: #("a" "b" "c")
get: c
len: 3
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))

This example demonstrates how to work with vectors in Racket, which are similar to slices in Go. It covers creating vectors, appending to them, slicing, and creating multi-dimensional vectors.