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

+1 vote
in Compiler by

The compiler does not complain about let binding (or def-ing) special symbols, but the binding only works if not used at the beginning of a list:

These work:

(let [try :a] try) => :a (let [try (constantly :a)] (apply try :b)) => :a

This doesn't work:

(let [try (constantly :a)] (try :b)) => :b

This is true for all special symbols, not just publicly exposed ones like try and new, but also internal ones like fn**.

I would expect consistent behaviour: either the compiler does not permit shadowing special symbols at all, or shadowing them works in all cases.

6 Answers

0 votes
by

Comment made by: bronsa

I don't think that shadowing special symbols is a good idea, but probably having all the special symbols namespace qualified (clojure.core/import* is the only one ns-qualified atm) along with checking for the symbol in the locals env first and fallbacking to the special symbols map after that, would probably help in those scenarios

0 votes
by

Comment made by: oakley jurgens

I think that shadowing special symbols is a bad idea. If that was possible, we'd have to change most macros in clojure.core to make them safe (i.e. explicitly add a namespace to each special symbol usage). And how would we handle special symbols that are not just implementation specific, like try and new? Every 3rd party macro that uses those might become unsafe.

My personal preference would be to prohibit the shadowing of special symbols.

0 votes
by

Comment made by: bronsa

That won't be the case since what I'm proposing includes making syntax-quote aware of the namespaced special symbols.
`def would expand to 'clojure.core/def for example.

0 votes
by

Comment made by: oakley jurgens

That's true, but macros don't have to use the syntax quote. See for example the definition of when.

0 votes
by
Reference: https://clojure.atlassian.net/browse/CLJ-1411 (reported by alex+import)
0 votes
by

Writing a "fix" for this, to throw if a var or local would shadow a special was surprisingly not too bad. However, just in clojure itself there are many instances of var and new and others used in let bindings.

Maybe instead of throwing an error it could print something: "WARNING: shadowing a special symbol is naughty and should not be done!" That's already done in a couple places when defining new vars or in let binds.

by
Yeah, you don't want to throw, it would break backwards compatibility. You might also want to turn it off, like *warn-on-reflection*.
by
That seems right to me. I'll play around with an alternative, maybe `*warn-on-shadowed-specials*`, see how it feels.
...