This seems... unexpected? I don't recall anything that says bare 'do' (not in list-head position) should get any special wrapping treatment at the start of let / fn bodies
Clojure 1.12.0
user=> (let [] do)
nil
user=> (let [] do 123)
123
user=> (let [] 123 do)
Syntax error compiling at (REPL:1:1).
Unable to resolve symbol: do in this context
user=> ((fn [] do))
nil
I think i had a fix for this in jira somewhere
indeed you did: https://clojure.atlassian.net/browse/CLJ-1216
Closest thing I found was some past discussions about shadowing of special forms http://ask.clojure.org/index.php/1132/special-symbols-can-be-shadowed-inconsistently which from what I can tell is about the Lisp-2-ish special treatment of these special-symbols at the head of list - but not when they're in value-position, where it appears legal to use them as local binding names
(let [do 123] do) ;; => nil
(let [do 123] do do) ;; => 123
(let [do 123] [do]) ;; => [123]
(let [if :abc] if) ;; => :abc
; but not
(let [if (constantly nil)] (if)) ;=> throws
I think you may have found a bug
yeah, seems that clojurescript handles it differently too
ClojureScript 1.11.132
cljs.user=> (let [] do)
^
WARNING: Use of undeclared Var cljs.user/do at line 1
nil
cljs.user=> (let [do :something] do)
:somethingIs behavior of special forms defined in situations like these? E.g. (let [] def).
https://clojure-doc.org/articles/language/macros/ ahh, this guide points out the exact failure case ('Ouch!') and says 'Never use special names as local binding or global variable names.' It's a community guide though, not sure how definitive that statement is - are we to take it as undefined behaviour?
I think this one is special to do ?
special forms are just overridden in call sites, not as local names
special forms as globals is definitely already a thing in the wild, eg. clojure.spec.alpha/def
yep, empirically it's just do which behaves weird in value position
user=> (doseq [sym (sort (keys clojure.lang.Compiler/specials))
:let [f (list `let* [sym :ok] sym)]]
(println sym "\t" (try (eval f) (catch Exception e (ex-message e)))))
& :ok
. Syntax error compiling fn* at (1:1).
case* :ok
catch :ok
def :ok
deftype* :ok
do nil
finally :ok
fn* :ok
if :ok
let* :ok
letfn* :ok
loop* :ok
monitor-enter :ok
monitor-exit :ok
new :ok
quote :ok
recur :ok
reify* :ok
set! :ok
throw :ok
try :ok
var :ok
clojure.core/import* Syntax error compiling let* at (1:1).
nilopen an ask about this
I've gotta ask: how did you discover this??? 🤯
Strangely I don't even remember the context 😦 just found it in a "huh that's weird" note to self while cleaning up some old fiddle files earlier, and decided to investigate a bit further