String Formatting in Clojure

Clojure offers excellent support for string formatting. Here are some examples of common string formatting tasks.

(ns string-formatting
  (:require [clojure.pprint :as pp]))

(defrecord Point [x y])

(defn main []
  ;; Clojure offers several printing functions designed to
  ;; format general Clojure values. For example, this prints
  ;; an instance of our Point record.
  (let [p (->Point 1 2)]
    (println "record1:" p)

    ;; The `pprint` function provides more detailed output,
    ;; including the record's field names.
    (println "record2:")
    (pp/pprint p)

    ;; To print the type of a value, use `type`.
    (println "type:" (type p))

    ;; Formatting booleans is straightforward.
    (println "bool:" true)

    ;; There are many options for formatting integers.
    ;; Use `str` for standard formatting.
    (println "int:" (str 123))

    ;; This prints a binary representation.
    (println "bin:" (Integer/toBinaryString 14))

    ;; This prints the character corresponding to the given integer.
    (println "char:" (char 33))

    ;; Use `format` with "%x" for hex encoding.
    (println "hex:" (format "%x" 456))

    ;; There are also several formatting options for floats.
    ;; For basic decimal formatting use `str`.
    (println "float1:" (str 78.9))

    ;; Use `format` with "%e" and "%E" for scientific notation.
    (println "float2:" (format "%e" 123400000.0))
    (println "float3:" (format "%E" 123400000.0))

    ;; For basic string printing, just use the string directly.
    (println "str1:" "\"string\"")

    ;; To print a representation of a pointer (which doesn't exist in Clojure),
    ;; we can print the hash code of the object instead.
    (println "hash:" (hash p))

    ;; When formatting numbers you will often want to control the width
    ;; and precision of the resulting figure. Use `format` for this.
    (println "width1:" (format "|%6d|%6d|" 12 345))

    ;; You can also specify the width of printed floats.
    (println "width2:" (format "|%6.2f|%6.2f|" 1.2 3.45))

    ;; To left-justify, use the "-" flag.
    (println "width3:" (format "|%-6.2f|%-6.2f|" 1.2 3.45))

    ;; You may also want to control width when formatting strings.
    (println "width4:" (format "|%6s|%6s|" "foo" "b"))

    ;; To left-justify use the "-" flag as with numbers.
    (println "width5:" (format "|%-6s|%-6s|" "foo" "b"))

    ;; `format` in Clojure works similarly to `sprintf` in other languages.
    (let [s (format "format: a %s" "string")]
      (println s))

    ;; You can format and print to other output streams using
    ;; `binding` with `*out*`.
    (binding [*out* *err*]
      (println "io: an error"))))

(main)

To run the program, save it as string_formatting.clj and use clojure command:

$ clojure string_formatting.clj
record1: #string_formatting.Point{:x 1, :y 2}
record2:
#string_formatting.Point{:x 1, :y 2}
type: string_formatting.Point
bool: true
int: 123
bin: 1110
char: !
hex: 1c8
float1: 78.9
float2: 1.234000e+08
float3: 1.234000E+08
str1: "string"
hash: 1234567  ; This will be a different number each time
width1: |    12|   345|
width2: |  1.20|  3.45|
width3: |1.20  |3.45  |
width4: |   foo|     b|
width5: |foo   |b     |
format: a string
io: an error

This Clojure code demonstrates various string formatting techniques. While Clojure doesn’t have a direct equivalent to Go’s fmt.Printf, it provides similar functionality through the format function and other built-in functions. The clojure.pprint namespace is used for pretty-printing complex data structures.