Var quote (#’) demystified

2025-01-03

(require '[ring.adapter.jetty :refer [run-jetty]])

(defn handler [_req] {:status 200 :body "plop"})

(run-jetty #'handler {:port 4321 :join? false})

#'handler is equivalent to (var handler) which returns the var bound to the symbol handler instead of the value inside that var.

This "var quoting" makes Jetty invoke the last defed value of handler. It works because a Clojure var can be invoked, and it will in turn try to invoke the value it currently holds.

A clojure var is also Callable and Runnable:

(import '(java.util.concurrent Executors ExecutorService))
(require '[clojure.test :refer [deftest is]])

(defn f [] :plop)

(deftest vars-are-polyvalent
  (with-open [exec (Executors/newVirtualThreadPerTaskExecutor)]
    (is (= nil (.get (^[Runnable] ExecutorService/.submit exec #'f))))
    (is (= :plop (.get (^[Callable] ExecutorService/.submit exec #'f))))))

There are functions that expects a var as input, but I have not encountered many of them:

(clojure.test/run-test-var #'vars-are-polyvalent)

To dig deeper into the subject of functions and vars, I have enjoyed this article by Aaron Lahey: 8thlight.com/insights/the-relationship-between-clojure-functions-symbols-vars-and-namespaces.

Bonus: how to make a StackOverflowError with a var
(with-local-vars [a :unused-value]
  (var-set a a)
  (a))