This library introduces mutable variables into the Clojure programming language, providing a way to declare and mutate variables within a scoped block.
Clojure is a language that strongly favors immutability as a core principle for building robust, concurrent, and predictable software. This library provides mutable variable capabilities as a specialized tool for scenarios where mutable state is necessary or significantly simplifies certain kinds of operations. It should be used judiciously and with a thorough understanding of the implications. Frequent use of mutable variables can lead to code that contradicts the foundational design principles of Clojure and may result in software that is harder to reason about and maintain. Ensure you understand the necessity and implications of introducing mutable state into your application before using this library.
To include mutable-var
in your project, add the dependency to your project configuration file depending on the build tool you are using:
Add the following to your project.clj
file:
[com.xadecimal/mutable-var "0.2.0"]
Add the following to your deps.edn
:
{:deps {com.xadecimal/mutable-var {:mvn/version "0.2.0"}}}
You can define a variable scope using var-scope
, and within this scope, you can declare and initialize mutable variables using (var <name> <value>)
. The variable is accessible from the point of declaration to the end of the var-scope
. To mutate the variable, use (set! <name> <new-value>)
.
Example:
(ns example
(:require [com.xadecimal.mutable-var :refer [var-scope]]))
(var-scope
(var name (read-line))
(println "Hello" name)
(set! name "Bob")
(println "Hello" name))
Mutable variables adhere to the following rules:
var-scope
where they are defined.(set! <name> <new-value>)
.long
, only long
values can be assigned to it.var-scope
, enhancing control over variable lifecycles and state management.set!
for explicit mutations, maintaining clarity in state changes within the block.This library is designed with performance in mind, by utilizing plain arrays of size 1 as the containers to manage mutable variables. This allows quick access and update operations, closely mimicking the behavior of mutable fields in other programming contexts. I can't promise it's as fast as mutable variables in Java, but it should get close.
long[]
, double[]
). This use of primitive arrays eliminates the need for boxing and unboxing operations, thereby optimizing performance.The mutable-var
library supports primitive types, enhancing performance by allowing direct operations on these types without the overhead of boxing and unboxing. Clojure's type inference is robust and often suffices for determining the appropriate primitive type. However, there are scenarios where manual intervention via explicit type hints is necessary to ensure optimal performance and correctness.
In most cases, mutable-var
can automatically infer the primitive type based on the value assigned during variable initialization:
(var-scope
(var i 42) ; Automatically inferred as a long
(var f 3.14) ; Automatically inferred as a double
(set! i (+ i 1)))
Explicit type hints are necessary when:
Explicit type hints can be provided either by annotating the initializing expression or by using casting to enforce the variable to be treated as a desired type or by wrapping in an (identity ...)
when you want Object type:
(var-scope
(var i ^long (#(+ 1 2))) ; Type hinting the function return
(var j (int (#(+ 1 2)))) ; Casting to int, even though function returns a long
(var k (identity 42)) ; Ensuring variable can hold nil values by typing it to Object
(set! k nil))
var
declaration. Always hint the value or use a casting function.set!
a value of a different type will result in a runtime error.If a variable of a primitive type is attempted to be mutated with a different type, it will lead to a runtime error, which will often appear as No matching method aset found taking 3 args
. This might mean you have type mismatches.
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close