Fork me on GitHub
#babashka
<
2019-12-03
>
borkdude11:12:42

bb var branch:

$ ./bb "(def x 10) (defn foo [] x) (def x 11) (println (foo)) #'foo"
11
#'foo

borkdude21:12:24

$ bb "(def f (fn [& xs] (apply + xs))) (apply #'f (range 10))"
45

sogaiu21:12:46

the var-thing worked fine here :thumbsup:

borkdude22:12:01

The grey areas of Clojure/Script:

cljs.user=> (defmacro ^:dynamic foo [])
#'cljs.user/foo
cljs.user=> (binding [foo 10] foo)
10

borkdude22:12:09

user=> (defmacro ^:dynamic foo [])
#'user/foo
user=> (binding [foo 10] foo)
Syntax error compiling at (REPL:1:1).
Can't take value of a macro: #'user/foo

sogaiu22:12:23

for the cljs case, i've been unclear whether there is a canonical place to test this kind of thing -- somehow i have the impression that depending on which place this is tried the answer can differ (e.g. lumo, shadow-cljs, planck, etc.)

borkdude22:12:08

vars are a grey area in CLJS anyway

borkdude22:12:23

they don't really exist except in the REPL (or something)

sogaiu22:12:55

...and that repl appears to often be implemented differently in each of shadow-cljs, lumo, planck, etc., iiuc

sogaiu22:12:32

complicates writing tooling

sogaiu22:12:11

anyway, cool that vars seem to be coming along 🙂

borkdude22:12:25

yeah, one thing I'm still pondering about is the public API for creating Sci vars

borkdude22:12:28

right now it looks like this:

(defn new-var
  "Returns a new sci var."
  ([name] (new-var name nil nil))
  ([name val] (new-var name val (meta name)))
  ([name init-val meta] (sci.impl.vars.SciVar. init-val name meta)))

(defn new-dynamic-var
  "Same as new-var but adds :dynamic true to meta."
  ([name] (new-dynamic-var name nil nil))
  ([name init-val] (new-dynamic-var name init-val (meta name)))
  ([name init-val meta] (sci.impl.vars.SciVar. init-val name (assoc meta :dynamic true))))
But I already discovered this needs to change, because probably the namespace field should also be associated in

borkdude22:12:40

ah maybe they just used the namespaced symbol as a field

borkdude22:12:08

that could work, since it's not really that important to which namespace a var belongs in sci

borkdude22:12:02

fixed 🙂

$ lein run "(def x 10) #'x"
#'user/x

sogaiu22:12:34

i guess the comparison is to this (Var.java)?

static Keyword privateKey = Keyword.intern(null, "private");
static IPersistentMap privateMeta = new PersistentArrayMap(new Object[]{privateKey, Boolean.TRUE});
static Keyword macroKey = Keyword.intern(null, "macro");
static Keyword nameKey = Keyword.intern(null, "name");
static Keyword nsKey = Keyword.intern(null, "ns");

borkdude22:12:13

those are just keywords made in Java

sogaiu22:12:36

lol, so they are

borkdude22:12:19

but sci doesn't really have reified namespaces...

borkdude22:12:25

another rabbit hole I guess 🙂

sogaiu22:12:15

🐇 🕳️ that one means not going down at the moment, 🕳️ 🐇 this one means about to go down

borkdude22:12:30

I should probably add the *ns* dynamic var and that should have some contents...

ClojureScript 1.10.520
cljs.user=> *ns*
#object[cljs.core.Namespace]

sogaiu22:12:37

it's certainly convenient to have

borkdude22:12:15

I'll make another deftype for it

borkdude22:12:35

what do people use *ns* for in practice beyond inspecting what the current ns is? define vars in other namespaces?

borkdude22:12:56

except that it doesn't work:

$ clj -e "(binding [*ns* (find-ns 'clojure.core)] (def x 1))"
#'user/x

sogaiu22:12:32

my primary use case is the current ns -- i think i've used it in some tooling code

sogaiu22:12:20

(do (in-ns 'user) (binding [*ns* (find-ns 'clojure.core)] (print *ns*)))
#object[clojure.lang.Namespace 0x1c801a1a clojure.core]

sogaiu22:12:50

that was done in a non-clojure.core ns

borkdude22:12:33

yes, but def doesn't work there

borkdude22:12:11

def might always take the root binding of *ns*, I don't know exactly how it works

sogaiu22:12:30

i am pretty sure i understand it even less 🙂

borkdude22:12:37

well, it's good to find out before I implement it 😉

sogaiu22:12:53

i happen to be reading eval() in Compiler.java and noticed that things that start with "def" seem to be special-cased -- not sure if that is related

borkdude22:12:46

I was also reading that 🙂

borkdude22:12:06

I was reading the code for DefExpr

borkdude22:12:34

this part is also interesting. it seems to be using a method called currentNS, we're getting closer

borkdude22:12:06

so it's a bit surprising why the def example with binding didn't work

borkdude23:12:30

this does work:

user=> (ns bar) (ns foo)
nil
nil
foo=> (set! *ns* (find-ns 'foo))
#object[clojure.lang.Namespace 0x485e36bc "foo"]
foo=> (set! *ns* (find-ns 'bar))
#object[clojure.lang.Namespace 0x17cdf2d0 "bar"]
bar=>

sogaiu23:12:35

lol, without the initial (ns bar), i just had my repl die 🙂

sogaiu23:12:52

i tried (set! **ns** (find-ns 'bar))

sogaiu23:12:50

DefExpr's eval has:

var.bindRoot(init.eval());
what does that do?

borkdude23:12:03

oh that just sets the root binding

borkdude23:12:18

lol, it really kills your REPL

borkdude23:12:45

(defn exit-repl [] (set! *ns* (symbol (str (java.util.UUID/randomUUID)))))

borkdude23:12:19

check #clojure, hiredman explained what's going on

sogaiu23:12:26

ah, thanks

borkdude23:12:32

the current ns is checked at an earlier phase than the binding occurs

sogaiu23:12:19

must...remember...compile...time

borkdude23:12:00

same thing for plk:

$ plk -e "(ns foo) (ns bar) (binding [*ns* (find-ns 'foo)] (def x 1))"
WARNING: foo is a single segment namespace at line 1
WARNING: bar is a single segment namespace at line 1
#'bar/x

borkdude23:12:43

$ /usr/local/bin/joker
Welcome to joker v0.12.4. Use EOF (Ctrl-D) or SIGINT (Ctrl-C) to exit.
user=> (set! *ns* (find-ns 'foo))
<repl>:1:2: Parse error: Unable to resolve symbol: set!

borkdude23:12:32

I'm not sure if it would be bad if babashka would return #'foo/x, I might have to try hard to produce the same (unexpected for me) result of clojure and cljs

sogaiu23:12:37

i'm not sure the current case is so common -- putting a def directly in the body of a binding.

sogaiu23:12:24

could be handy to be able to search for such patterns across all of the latest clojars jars 🙂

borkdude23:12:27

well, since it's doesn't really do anything useful, I don't expect this to be anywhere really, but I made a not of it, implementing the same behavior in bb / sci will work

borkdude23:12:15

it's pretty funny that the current namespace is denoted by a var, but that a var always has a namespace