Skip to content

Yet another programming solutions log

Sample bits from programming for the future generations.

Technologies Technologies
  • Algorithms and Data Structures
  • Java Tutorials
  • JUnit Tutorial
  • MongoDB Tutorial
  • Quartz Scheduler Tutorial
  • Spock Framework Tutorial
  • Spring Framework
  • Bash Tutorial
  • Clojure Tutorial
  • Design Patterns
  • Developer’s Tools
  • Productivity
  • About
Expand Search Form

Clojure transients – fast mutations in persistent world

farenda 2016-12-21 0

Clojure transients is a great way to optimize performance sensitive code without leaving familiar Clojure world. In this post we show how to use them to boost performance.

Basic flow with transients

The code structure is the same as in any Clojure code, except turning mutations on using transient function, modifications using bang! versions of functions, and persisting back with persistent! function:

(defn transient-flow [v]
  (let [tv (transient v)]
    (-> tv
        ;; mutate with bang! functions
        persistent!)))

Now you can call it like any other Clojure code:

(is (= [1 2 3] (transient-flow [1 2 3])))

Transient mutation functions

Like their immutable versions Transients support read-only operations with standard functions (count, get, etc.), but for mutations they have own versions, which we will cover here.

conj! – add elements to a transient collection

(defn conj-inline [coll val]
  (let [tv (transient coll)]
    (persistent! (conj! tv val))))

The test:

(is (= [1 2 3 42] (conj-inline [1 2 3] 42)))

assoc! – create/replace mapping for a key

Here we just replace each value with its multiplication by n:

(defn times [v n]
  (loop [tv (transient v) i (dec (count v))]
    (if (<= 0 i)
      (recur (assoc! tv i (* n (get tv i))) (dec i))
      (persistent! tv))))

And test:

(is (= [2 4 6] (times [1 2 3] 2)))

dissoc! – remove mapping for a key

(defn remove-key [m key]
  (-> m transient (dissoc! key) persistent!))

Let’s run it:

(is (= {:points 1234}
       (remove-key {:points 1234 :level 4} :level)))

pop! – remove last from a vector

(defn remove-last [v]
  (-> v transient pop! persistent!))

Pop from stack seems to work:

(is (= [1 2] (remove-last [1 2 3])))

disj! – remove last from a set

(defn remove-from-set [s key]
  (-> s transient (disj! key) persistent!))

The test:

(is (= #{1 3} (remove-from-set #{1 2 3} 2)))

Transient types – vectors, maps, sets

Only persistent vectors, hash maps, and hash sets can be transient. When you try to turn an unsupported type into a transient then ClassCastException will be thrown:

(defn transient-list [l]
  (persistent! (transient l)))

The test:

(deftest should-throw-exception-for-non-transientable-types
  (try
    (transient-list (range 10))
    (throw (IllegalStateException. "Should fail!"))
    (catch ClassCastException e
      (prn "List cannot be transient: " (.getMessage e)))))

Properties of transients

There are a few things that it’s good to keep in mind when using Clojure transients:

  • creating a transient takes O(1) time, persisting it back is O(1) too
  • they require thread isolation, because share mutable state between operations.

References:

  • Insertion Sort in Clojure with transients!
  • Check out other cool things in Clojure Tutorial!
  • The code is available at GitHub
Share with the World!
Categories Clojure Tags performance
Previous: Generate random numbers concurrently – ThreadLocalRandom
Next: Remove duplicates from List in Java

Recent Posts

  • Java 8 Date Time concepts
  • Maven dependency to local JAR
  • Caesar cipher in Java
  • Java casting trick
  • Java 8 flatMap practical example
  • Linked List – remove element
  • Linked List – insert element at position
  • Linked List add element at the end
  • Create Java Streams
  • Floyd Cycle detection in Java

Pages

  • About Farenda
  • Algorithms and Data Structures
  • Bash Tutorial
  • Bean Validation Tutorial
  • Clojure Tutorial
  • Design Patterns
  • Java 8 Streams and Lambda Expressions Tutorial
  • Java Basics Tutorial
  • Java Collections Tutorial
  • Java Concurrency Tutorial
  • Java IO Tutorial
  • Java Tutorials
  • Java Util Tutorial
  • Java XML Tutorial
  • JUnit Tutorial
  • MongoDB Tutorial
  • Quartz Scheduler Tutorial
  • Software Developer’s Tools
  • Spock Framework Tutorial
  • Spring Framework

Tags

algorithms bash bean-validation books clojure design-patterns embedmongo exercises git gof gradle groovy hateoas hsqldb i18n java java-basics java-collections java-concurrency java-io java-lang java-time java-util java-xml java8 java8-files junit linux lists log4j logging maven mongodb performance quartz refactoring regex rest slf4j solid spring spring-boot spring-core sql unit-tests

Yet another programming solutions log © 2022

sponsored