You create clojure immutable vectors as an abstract datatype.
(package clojure [copy give immutable]
(datatype immutable
__________________
<> : (immutable A);
X : A; V : (immutable A);
=========================
(@v X V) : (immutable A);
______________________________________
copy : ((immutable A) --> (vector A));
______________________________________
give : ((vector A) --> (immutable A));)
\\ fast copy with native vectors
(define copy
EmptyCopy (absvector (+ Limit 1))
StandardV (address-> EmptyCopy 0 Limit)
(copyh Vector StandardV Limit)))
(define copyh
_ Copy 0 -> Copy
Vector Copy N -> (copyh Vector (address-> Copy N (<-address Vector N)) (- N 1)))
\\ coerces to immutable status
(define give
Vector -> Vector) )
Here is destructive add.
(define destructive-add1
{(vector number) --> (vector number)}
Here we declare a global as an immutable vector.
(datatype globals
______________________________________
(value *immutable*) : (immutable number);)
____________________________________________________________________________
\\ This fails because immutable vectors cannot be built this way.
(41+) (set *immutable* (vector 7))
type error
\\This fails too.
(42+) (set *immutable* (@v 1 2 a <>))
type error
\\This works.
(43+) (set *immutable* (@v 1 2 3 <>))
<1 2 3> : (immutable number)
\\Cannot mutate an immutable vector
(44+) (vector-> (value *immutable*) 2 6)
type error
\\But you can if you copy it.
(45+) (vector-> (copy (value *immutable*)) 2 6)
<1 6 3> : (vector number)
\\ Still immutable!
(46+) (value *immutable*)
<1 2 3> : (immutable number)
\\ Return an immutable vector
(47+) (give (vector-> (copy (value *immutable*)) 2 6))
<1 6 3> : (immutable number)
\\ Cannot mutate it.
(48+) (destructive-add1 (value *immutable*))
type error
\\ So copy it.
(49+) (destructive-add1 (copy (value *immutable*)))
<2 3 4> : (vector number)
You create an abstract datatype and the type checker controls access to objects of that type and ensures they are immutable.
Mark