Fork me on GitHub
#clojure
<
2023-11-22
>
Filipe Silva00:11:12

;; works
(do
  (require '[clojure.string :as str5])
  (str5/lower-case "FOO"))

;; works
(do
  (require '[clojure.string :as str6])
  ((fn [x] (str6/lower-case x)) "FOO"))

;; throws: No such namespace: str7
((do
   (require '[clojure.string :as str7])
   (fn [x] (str7/lower-case x)))
 "FOO")

;; throws: No such namespace: str8
((fn [x]
   (require '[clojure.string :as str8])
   (str8/lower-case x))
 "FOO")
I was a bit surprised the last two don't work. Is there a way to do a require and use it on the same expr?

seancorfield00:11:20

Top-level do is special, as I recall, but you might want to look at requiring-resolve for dynamically requiring and resolving symbols at runtime.

hiredman00:11:16

Symbols are resolved at compile time, but require doesn't have a compile time effects, it has a runtime effect

hiredman00:11:27

So if a form depends on the effect of a require, the require needs to be compiled and run before that form can be compiled

hiredman00:11:07

do is special in that a top level do (not nested in any other expression) is treated as a sequence of top level expressions to be compiled then executed one after the other instead of being treated as a single expression to be compiled and executed all at once

Filipe Silva00:11:20

makes sense, thanks for the insight!

Filipe Silva00:11:26

((fn [x]
   (requiring-resolve 'clojure.string/lower-case)
   (clojure.string/lower-case x))
 "FOO")
does work

hiredman00:11:40

It won't in a fresh repl

hiredman00:11:47

The compiling of the call to lower-case there is relying on the runtime effect of requiring-resolve

2
hiredman00:11:24

So that won't compile unless something has already loaded clojure.string before that form is compiled

hiredman00:11:03

You want ((requiring-resolve ...) x)

☝️ 2
oyakushev01:11:33

It will work in fresh REPL because clojure.string is required during the initialization of clojure.core. Same for http://clojure.java.io. This, for example, won't work:

((fn [x]
   (requiring-resolve 'clojure.set/intersection)
   (clojure.set/intersection #{} x))
 #{})

👍 2