Skip to content

Instantly share code, notes, and snippets.

@enforser
Last active November 15, 2018 15:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save enforser/f5672cd0f8b40ffd909840075ed0cecc to your computer and use it in GitHub Desktop.
Save enforser/f5672cd0f8b40ffd909840075ed0cecc to your computer and use it in GitHub Desktop.
A collection of some examples of things I do to make REPL development more effective.
;; Demonstrates the usage of vars that are useful when working in the REPL.
;; Created: November 14, 2018
;;
;; My suggested method of reading this file is to copy it into some project and actually
;; go through the code snippets and evaluate in the REPL to play around with them.
;;
;; WARNING: Some of the examples will create a file called 'output.txt' from the directory
;; that your REPL is started in.
;;
;;
;; ===========================================================
;; Pretty printing all the time!
;; in your REPL run:
(clojure.main/repl :print clojure.pprint/pprint)
;;
;; ===========================================================
;; *print-length*
;; https://clojuredocs.org/clojure.core/*print-length*
;;
;; limits the number of objects which will be printed from a sequence
;; (iterate inc 0) will print forever since it is infinite
(do (set! *print-length* 10) ;; limit print length
(prn (iterate inc 0))
(set! *print-length* nil)) ;; back to normal
;; => (0 1 2 3 4 5 6 7 8 9 ...)
;; Note that the returned object is still infinite, it just stops printing after
;; 10 elements.
;; ===========================================================
;; *print-level*
;; https://clojuredocs.org/clojure.core/*print-level*
;;
;; limits the amount of levels will be printed in a nested data structure.
;; Useful when you don't care about data in a nested object beyond a certain level.
((fn f [x]
(if (zero? x)
x
[x (f (dec x))]))
5)
;; => [5 [4 [3 [2 [1 0]]]]]
(do (set! *print-level* 3) ;; limit print level
(prn ((fn f [x]
(if (zero? x)
x
[x (f (dec x))]))
5))
(set! *print-level* nil)) ;; back to unlimited printing!
;; => [5 [4 [3 #]]]
;; ===========================================================
;; *print-meta*
;; https://clojuredocs.org/clojure.core/*print-meta*
;;
;; Prints the metadata of prn followed by prn itself
;; must reference the function with var before printing it to get the metadata
(binding [*print-meta* true]
(prn (var prn)))
;;=> ^{:arglists ([& more]), :doc "Same as pr followed by (newline). Observes *flush-on-newline*", :added "1.0", :static true, :line 3706, :column 1, :file "clojure/core.clj", :name prn, :ns ^{:doc "Fundamental library of the Clojure language", :author "Rich Hickey"} #object[clojure.lang.Namespace 0x51ac75b4 "clojure.core"]} #'clojure.core/prn
;; nil
;; ===========================================================
;; *print-namespace-maps*
;; https://clojuredocs.org/clojure.core/*print-namespace-maps*
;;
;; Determines how namespaced maps are printed.
(def m {:foo/a 1
:foo/b 2})
(prn m)
;;=> #:foo{:a 1 :b 2}
(binding [*print-namespace-maps* false]
(prn m))
;;=> {:foo/a 1 :foo/b 2}
;; ===========================================================
;; *print-readably*
;; https://clojuredocs.org/clojure.core/*print-readably*
;;
;; Prints numbers and letters readably when set to true
;; Defaults to true
(prn "\\A")
;;=> "\\A"
;; nil
(binding [*print-readably* false]
(prn "\\A"))
;;=> \A
;; nil
;; ===========================================================
;; *1, *2, and *3
;; https://clojuredocs.org/clojure.core/*1
;; https://clojuredocs.org/clojure.core/*2
;; https://clojuredocs.org/clojure.core/*3
;; Stores the result of the past 3 outputs of the REPL, where *1 is the most recent.
;; Evaluate the following in the REPL as separate inputs
(+ 1)
(+ 1 2)
(+ 1 2 3)
;; Provided the above was evaluted one at a time into the REPL then you can get the values
;; from *1, *2, and *3.
;; *1 => 6
;; *2 => 3
;; *3 => 1
;; Note that if you evaluate one of the above in a REPL then it will become the new *1, and so on.
;; ===========================================================
;; *e
;; https://clojuredocs.org/clojure.core/*e
;; Stores the last exception thrown.
(/ 1 0)
*e ;; => 'Divide by Zero' exception.
(map 1 2)
*e ;; => 'Don't know how to create ISeq from: java.lang.Long' exception
;; You can treat *e as you would any exception object. ex. (.getMessage e)
;; ===========================================================
;; *out*
;; https://clojuredocs.org/clojure.core/*out*
;; Changes where print will write to.
(binding [*out* (clojure.java.io/writer "output.txt" :append true)]
#_#_ ;; uncomment the following print statements for this example to work.
(prn "This will be the first row in my output file!")
(prn "This will be the second row in my output file!")
true)
;; ===========================================================
;; *print-dup*
;; https://clojuredocs.org/clojure.core/*print-dup*
;; Makes printing objects formatted such that if they are in a file then
;; they will be read in with the right types in the future.
;; Useful for when you want to save some object somewhere and read
;; it in again later.
(binding [*print-dup* true]
(prn {:a 1 "b" 'c}))
;;=> #=(clojure.lang.PersistentArrayMap/create {:a 1, "b" c})
;; Can be used in conjunction with *out*
;; Writes the output of prn to a file such that it can later be
;; read back in with the right types.
;; This is better than reading in as string then using read-string.
(binding [*print-dup* true
*out* (clojure.java.io/writer "output.txt")]
#_ ;; uncomment the prn statement to make this example work.
(prn {:a 1 "b" 'c}))
(with-open [r (java.io.PushbackReader. (java.io.FileReader. "output.txt"))]
(read r))
;; returns {:a 1 "b" 'c} with their respective types still available.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment