Fork me on GitHub
#clojure
<
2023-12-24
>
Takis_00:12:45

Hello, i used this in past and it was working, the (load-string "...") could see the enviroment, but now it says runtimeException undefined q symbol, q is a macro, functions seems to be visable ok

(prn "code" (q :squerylive.1 {:command true}))     ;;works fine
(prn "load-code" (load-string "(q :squerylive.1 {:command true})"))   ;;now it doesn't work, in past it worked somehow, cant find q, but q is included in :use in ns

hiredman00:12:05

Depends what you mean by environment

hiredman00:12:08

eval in clojure doesn't have access to the local lexical environment eval was called in

hiredman00:12:45

So no let bound names

Takis_00:12:56

q symbol is in a namespace, that its used in (:use ...) , i dont use eval, load-string, the weird is that it worked in past. hm

hiredman00:12:26

Oh, then it is likely because the value of the *ns* (the current namespace for compilation/evaluation) is not what you expect it to be

hiredman00:12:30

It is best to consider *ns* to be sort of undefined, if you haven't explicitly set it to be anything, it could be anything

Takis_00:12:31

hm i will try once more with leinengen as i did it in past, and see if it will works, thank you for helping me.

hiredman00:12:39

When eval encounters a non-locally bound symbol, it looks at the namespace bound to *ns* to find it

hiredman00:12:27

But *ns* is generally only used like that during compilation / evaluation

hiredman00:12:07

When code is actually running the value could be anything and it often isn't ever even looked at

hiredman00:12:33

This can trip people up when moving from running code on the repl, where the repl maintains a binding of *ns*

hiredman00:12:46

To running code outside of the repl

Takis_00:12:57

i cant say that i understanded what you mean, but with leinengen without aot, same code is ok with load-string .

"code" #ordered/map (["aggregate" "1"] ["pipeline" []] ["cursor" #ordered/map nil] ["maxTimeMS" 1200000])
"load-code" #ordered/map (["aggregate" "1"] ["pipeline" []] ["cursor" #ordered/map nil] ["maxTimeMS" 1200000])
got the same

Takis_00:12:35

it seems that its related with aot maybe or with the https://github.com/clojurephant/clojurephant gradle tool that i used

Takis_00:12:28

seems that its the aot, lein with aot didn't work also.

Takis_01:12:49

now it works fine, q was a macro so instead of

(load-string "(q :squerylive.1 {:command true})")
i did
(load-string "(mynamespace/q :squerylive.1 {:command true})")
and its fine, i think its related with macros not sure, because functions from enviroment load-string could see even without namespace/

Takis_01:12:09

anyway thank you, sometime i should understand how load-string works : )

hiredman01:12:27

Aot and not lein will be launching the code differently

hiredman01:12:11

Without aot *ns* however lein launches the code ends up being the namespace you expect

hiredman01:12:30

But with aot it is likely clojure.core or possibly user

hiredman01:12:24

whatever lein's behavior is without aot may be different again with the clojure.main launcher

hiredman01:12:38

So you need to set *ns* to whatever you want it to be using binding around the call to load-string

Takis_13:12:35

thank you : ) i will read those you said and i will try load-string again, for now problem is solved, even if i dont real understand the cause

joshcho17:12:41

In Jonathan Blow’s programming language Jai, “captures” are used to prepare a certain snippet of code for refactoring. Essentially you are making sure all of the variables are captured within the scope before factoring it out. I wonder if something like that is possible with a macro or continuation? You essentially need to bring clojure back to its pure environment with only the captured variables. https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md

joshcho17:12:48

I suppose as a simple workaround, you could check all symbols in the code that are within the current namespace & see if they are captured. Otherwise, error.

p-himik18:12:25

To me, it's really weird to see an affordance for refactoring being built into a language. Usually it's a part of the IDE that's familiar with the language. E.g. in IntelliJ IDEA, I can select a piece of Java code and extract it into a function - everything will be done for me, automatically. All names that come from the outside of of that piece of code will become arguments (unless they're members of the class). Cursive doesn't seem to have that capability, but just manually extracting something will let you know which symbols need to be defined. It takes a few seconds to add all those to the arg vector in a newly created function.

respatialized19:12:28

You might also take a look at the way the Unison programming language https://www.unison-lang.org/docs/the-big-idea/ - an even more general capability that opens up powerful tools for refactoring, manipulating, and otherwise working with code as an immutable data structure.

❤️ 1