janet-lang / janet

A dynamic language and bytecode vm
https://janet-lang.org
MIT License
3.45k stars 223 forks source link

if-let's else branch appears multiple times in its expansion #1191

Closed ianthehenry closed 1 year ago

ianthehenry commented 1 year ago

This is unrelated to the recent if-let changes -- if-let has always worked this way, but I found this very surprising:

repl:1:> (defmacro hello [] (print "hello") 1)
<function hello>
repl:2:> (if-let [a true] "ok" (hello))
hello
"ok"
repl:3:> (if-let [a true b true] "ok" (hello))
hello
hello
"ok"
repl:4:> (if-let [a true b true c true] "ok" (hello))
hello
hello
hello
"ok"

I would expect the else branch to only appear once in the expansion of if-let -- which I believe is not compatible with the desire to be able to reference the first binding form in the else branch.

primo-ppcg commented 1 year ago

It could also be implemented differently. Since we've already touched it, it may be worth addressing.

which I believe is not compatible with the desire to be able to reference the first binding form in the else branch.

It's not. Not expanding macros with side-effects more than once is more desirable and correct.