 ;;; -*- lexical-binding: t -*-
 
 ;; Constructors.
+(defmacro Go--slice (data offset len cap)
+  `(cons ,data
+         (cons ,offset
+               (cons ,len ,cap))))
 (defun Go--make-slice (len zero-val)
-  (cons (make-vector cap zero-val)
-        (cons 0 ;; offset
-              (cons len len))))
+  (Go--slice (make-vector len zero-val) 0 len len))
 (defun Go--make-slice-cap (len cap zero-val)
   (if (= len cap)
       (Go--make-slice len zero-val)
     (let ((data (make-vector cap nil)))
       (dotimes (i len)
         (aset data i zero-val))
-      (cons data
-            (cons 0
-                  (cons len cap))))))
+      (Go--slice data 0 len cap))))
 (defun Go--make-slice-from-list (&rest vals)
   (let* ((data (vconcat vals))
          (len (length data)))
-    (cons data
-          (cons 0 ;; offset
-                (cons len len)))))
+    (Go--slice data 0 len len)))
 
 ;; Getters.
 (defmacro Go--slice-data (slice)   `(car ,slice))

        ;; then re-set slice data with `vconcat' of old and new data.
        (let ((new-data (make-vector 16 nil)))
          (aset new-data 0 val)
          (Go--slice-data! slice
            (vconcat (Go--slice-data slice)
                     new-data))
          (Go--slice-cap! slice
            (+ (Go--slice-cap slice)
               (length new-data))))
      ;; Insert new value directly.
      (Go--slice-set slice pos val))
    slice))

(defmacro Go--slice-len (slice)    `(car (cdr (cdr ,slice))))
(defmacro Go--slice-cap (slice)    `(cdr (cdr (cdr ,slice))))

;; Setters.
(defmacro Go--slice-data! (slice data)
  (declare (indent 1))
  `(setcar ,slice ,data))
(defmacro Go--slice-offset! (slice offset)
  (declare (indent 1))
  `(setcar (cdr ,slice) ,offset))
(defmacro Go--slice-len! (slice len)
  (declare (indent 1))
  `(setcar (cdr (cdr ,slice)) ,len))
