Adding to the previous answer: in Java a "value type", is just a regular object that is final and allows no mutation. This provides the same semantics as a Clojure map, vector, etc. These "immutible objects" gained prominence in the realm of multi-threading since they avoided race conditions.
Background: When Java was first introduced, the "marketing" people made a big deal about Java having "no pointers", just "references" (unlike C/C++). Well kids, a Java "reference" is just a pointer on which you cannot call free
or delete
, etc. Note that this is not identical to a subroutine using "pass by reference" in C++ (or many older langs).
To reiterate, a "variable" in Java is a reference (aka pointer) to an object. If that object is an instance of an immutable class, it is called a "value object" or an instance of a "value type".
P.S. The above ignores primitive types like long
. However, boxed objects like Long
are the OG of immutable or "value" types.
P.P.S. If you truly want to "pass by reference" in Clojure with the goal of allowing a subroutine to mutate the value (eg "5"), then you will wrap the value in a Clojure atom
like(atom 5)
, and pass that reference to the subroutine. The reference to the atom
is immutable, but the contents of the atom
can be mutated:
(ns tst.demo.core
(:use tupelo.test))
(defn increment-arg
[atom-ref] ; immutable reference to an `atom` holding a value
(swap! atom-ref inc)) ; increment by +1 the contents of the atom
(verify
(let [aref (atom 5)] ; reference to an atom holding the immutable value 5
(increment-arg aref) ; call increment function on the atom reference
(is= 6 (deref aref)) ; extract current value from the atom
))
Example built using my favorite template project.
P.P.P.S. You can find more fine-grained details here.