defs in Clojurescript REPL

83 views
Skip to first unread message

Mark Engelberg

unread,
May 14, 2012, 2:07:29 AM5/14/12
to clojure
In Clojure, when you def a variable, the REPL prints the name of the variable rather than the value.
In Clojurescript, when you def a variable, the REPL prints the value assigned to the variable.

This is problematic when working with lazy values.  Is there any particular reason the Clojurescript REPL is designed to behave in this way?

Thanks,

Mark

David Nolen

unread,
May 14, 2012, 8:06:46 AM5/14/12
to clo...@googlegroups.com
Do you have a more specific example of why this is a problem?
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Mark Engelberg

unread,
May 14, 2012, 7:27:45 PM5/14/12
to clo...@googlegroups.com
(def tree (function-that-produces-an-enormous-tree 2))

Want do that in Clojurescript, and you'll be treated to tons and tons of nested tree data printed to the REPL.

Want to time something that's supposed to be lazy, to make sure it's really lazy, and see how long it takes to produce the eager aspects?  In Clojure, that's easy:

(time (def result (lazy-function 10)))

In Clojurescript, the REPL will produce the whole lazy sequence.  That's bad.

So there are a couple examples of things that are harder to do when your REPL prints the values that are attached to variables.  But again, the real question here is, why does Clojurescript deviate on this point?  I know that Clojurescript doesn't exactly match Clojure, but shouldn't all deviations be done for a reason?

--Mark

David Nolen

unread,
May 14, 2012, 7:41:16 PM5/14/12
to clo...@googlegroups.com
On Mon, May 14, 2012 at 7:27 PM, Mark Engelberg <mark.en...@gmail.com> wrote:
(def tree (function-that-produces-an-enormous-tree 2))

Isn't doing this at the top level bad form?
 
So there are a couple examples of things that are harder to do when your REPL prints the values that are attached to variables.  But again, the real question here is, why does Clojurescript deviate on this point?  I know that Clojurescript doesn't exactly match Clojure, but shouldn't all deviations be done for a reason?

--Mark

There are a few good reasons to not reify things like vars and namespaces in ClojureScript - one of these is Google Closure Compiler.

Also I don't see how this isn't solved by modifying some habits.

(defn test-tree [] (function-that-produces-an-enormous-tree 2))
(time (test-tree))

David 

Mark Engelberg

unread,
May 14, 2012, 11:13:24 PM5/14/12
to clo...@googlegroups.com
On Mon, May 14, 2012 at 4:41 PM, David Nolen <dnolen...@gmail.com> wrote:
On Mon, May 14, 2012 at 7:27 PM, Mark Engelberg <mark.en...@gmail.com> wrote:
(def tree (function-that-produces-an-enormous-tree 2))

Isn't doing this at the top level bad form?

The purpose of a REPL is for interactive experimentation.  I want to give names to the things I'm building so I can play with them in the REPL.  Nothing bad form about that.
 
Also I don't see how this isn't solved by modifying some habits.

(defn test-tree [] (function-that-produces-an-enormous-tree 2))
(time (test-tree))


time prints out the value that is computed.  The above example would suffer the same problem of printing out the tree at the REPL.  You could do something like (time (do (test-tree) nil)) to suppress printing, but if you want to do further interactive manipulations to the tree, you'd end up recomputing it.  So then, you get into workarounds involving delay.  It starts to get ugly, I think.

Clojure's ability to give names to things without printing the values is a feature I use every day in my interactive explorations.


kovas boguta

unread,
May 15, 2012, 12:14:41 AM5/15/12
to clo...@googlegroups.com
I think this is a pretty valid feature request.

The main question is, can this be done without having vars in clojurescript.

One way to do it is to surpress output somehow, under certain conditions.

Either as a token at the end of a repl input, or in the semantics of def itself.

I don't have an ideal specific solution here, but I've noticed this
problem as well and found it pretty annoying.

There should be a way to solve it that is a reasonable compromise.



On Mon, May 14, 2012 at 11:13 PM, Mark Engelberg

Laurent PETIT

unread,
May 15, 2012, 2:26:36 AM5/15/12
to clo...@googlegroups.com
Clojurescript doesn't have vars, so why not have def return the symbol ?

kovas boguta

unread,
May 15, 2012, 2:28:23 AM5/15/12
to clo...@googlegroups.com
Yeah, that is sort of what I was implying in "changing the semantics of def"

Though I wasn't ready to totally committed to that, since I don't
understand the properties of symbols in clojurescript.

Like, how do go from the symbol to the javascript object we've just
bound to the symbol?

David Nolen

unread,
May 15, 2012, 6:08:05 AM5/15/12
to clo...@googlegroups.com
Returning the symbol seems odd at least to me. I think the best we could do is have a compiler flag so that defs can return nil for REPLs.

Michał Marczyk

unread,
May 15, 2012, 6:50:34 AM5/15/12
to clo...@googlegroups.com
Workaround:

(do (def foo (build-something-enormous)) nil)

As for the reason for this behaviour -- probably non other than it's
just the easiest thing for def in ClojureScript to do; "it" being to
inherit the return value from the JavaScript assignment def compiles
to.

Sticking a void () around the assignment (so that (def foo ...) would
do what (js* "void (~{})" (def foo ...)) does currently) would be a
straightforward way of suppressing the returned value. I can put
together the (trivial) patch to do that in :statement context in the
presence of a flag if this seems useful. The REPL could just set this
flag by default.

Sincerely,
Michał

kovas boguta

unread,
May 16, 2012, 2:58:42 AM5/16/12
to clo...@googlegroups.com
I'd rather see something at the beginning or at the end of the statement.

like ^:toss (def ...)

or (def ...) ;;

Michał Marczyk

unread,
May 16, 2012, 5:01:14 AM5/16/12
to clo...@googlegroups.com
That doesn't seem to free one from the need to take special care when
assigning potentially large lazy values to names with def.

If exercising special care on a case-by-case basis is not a problem,
then it's already possible to say

(do (def ...) nil)

or similar, as mentioned above. You can also say

(def toss (constantly nil))

and use

(toss (def ...)).

Sincerely,
Michał
Reply all
Reply to author
Forward
0 new messages