Share your thoughts in the 2024 State of Clojure Survey!

Welcome! Please see the About page for a little more info on how this works.

+1 vote
in Compiler by
retagged by

The following two code snippets behave very differently, depending only on the order you define the functions. I find this behavior surprising, and probably not intended.

(ns jimka-test
  (:require [clojure.pprint :refer [cl-format]]))

(declare f)

(defn g []
  (map f '(1 2 3)))

(def ^:dynamic f (fn [x] (* x x)))

(defn h []
  (assert (= (g) '(1 4 9)))
  (binding [f (fn [x] (+ x x))]
    (assert (= (g) '(2 4 6))
            (cl-format false "(g) returned ~A" (g)))))

(h)

Now swap the order of definitions of f and g.

(ns jimka-test
  (:require [clojure.pprint :refer [cl-format]]))

(declare f)

(def ^:dynamic f (fn [x] (* x x)))

(defn g []
  (map f '(1 2 3)))

(defn h []
  (assert (= (g) '(1 4 9)))
  (binding [f (fn [x] (+ x x))]
    (assert (= (g) '(2 4 6))
            (cl-format false "(g) returned ~A" (g)))))

(h)

My suggestion is that if a variable is declared non-dynamic, then a later definition as dynamic should issue a warning.

This issue was also discussed on clojureverse

2 Answers

0 votes
by

I supposed the other direction should be warned as well. If a variable is redefined from dynamic to lexical, there should also be a warning emitted.

by
I think the other way does have a warning.
0 votes
by
...