"Comma Commands" for the repl to provide utilities, shorten error messages

19 views
Skip to first unread message

Stephen C. Gilardi

unread,
Sep 13, 2008, 1:10:11 AM9/13/08
to Clojure
I've implemented a modification to the repl that hides stack traces from its output while allowing easy access to the most recent stack trace if it's desired. The idea is borrowed from other repls (Scheme48 and Gambit). Tokens that begin with a comma are treated as commands directly to the repl. The set of commands is extensible if we come up with more useful ones over time.

Here's an example:

Clojure
user=> ,?
Comma Commands
,s    Show the most recent exception's stack trace
,r    Show the most recent object returned by read
,e    Show the most recent object returned by eval
,h    Show this help
,?    Show this help
user=> (conj '(1 2 3) [4 5 6])
([4 5 6] 1 2 3)
user=> ,r
(conj (quote (1 2 3)) [4 5 6])
user=> ,e
([4 5 6] 1 2 3)
user=> ,s
no exceptions yet!
user=> (/ 1 0)
java.lang.ArithmeticException: Divide by zero
user=> ,s
java.lang.ArithmeticException: Divide by zero
at clojure.lang.Numbers.divide(Numbers.java:142)
at user.eval__2288.invoke(Unknown Source)
at clojure.lang.Compiler.eval(Compiler.java:3850)
at clojure.lang.Repl.main(Repl.java:95)
user=> 

I've enclosed a patch to Repl.java. Comments and suggestions are welcome.

--Steve

comma-commands.patch

Parth Malwankar

unread,
Sep 13, 2008, 1:39:50 AM9/13/08
to Clojure
This is really neat addition for the repl.
Thanks Steve.

For some reason I can't see the patch so I haven't had
a chance to try it yet.

One question, is it possible to use ,e in expressions we type
at the prompt?
e.g.
user => ,e
10
user => (vector ,e ,e)
[10 10]

A possible nice to have (if its not a big change) could be
something like the CL *,** etc.
http://www.lispworks.com/documentation/HyperSpec/Body/v__stst_.htm#STSTST

,e
,ee
,eee

(or maybe ,e ,e-1 ,e-2 ... e-9)

I am not really requesting the features, just throwing
the ideas around, in case these are just a small changes.

Parth



>
> --Steve

Stephen C. Gilardi

unread,
Sep 13, 2008, 2:05:58 AM9/13/08
to clo...@googlegroups.com
On Sep 13, 2008, at 1:39 AM, Parth Malwankar wrote:

I've enclosed a patch to Repl.java. Comments and suggestions are
welcome.

This is really neat addition for the repl.
Thanks Steve.

Thanks!

For some reason I can't see the patch so I haven't had a chance to try it yet.

I see that it didn't make it to the Google group. I'll attach it again to this message and if it fails to show up on the website again, I'll upload it to the files area.

comma-commands.patch

squeegee

unread,
Sep 13, 2008, 2:11:32 AM9/13/08
to Clojure
I uploaded the patch to the files area of the Google group:

http://groups.google.com/group/clojure/web/comma-commands.patch

--Steve

Rich Hickey

unread,
Sep 13, 2008, 12:14:41 PM9/13/08
to Clojure
I suggest using keywords for commands. They evaluate to themselves and
there is no purpose to entering them at the repl otherwise (other than
demonstrating that keywords evaluate to themselves, I guess). Commas
violate the read/data rules and are ugly.

More important, I don't see a strong case for commands yet. Commands
for printing the last object read and the last evaluated value and
last stack trace are substantially less useful than vars that evaluate
to those values. While * isn't available, *1 *2 *3 *ex (and various
other possibilities) are.

Rich

Stephen C. Gilardi

unread,
Sep 13, 2008, 1:59:16 PM9/13/08
to clo...@googlegroups.com

On Sep 13, 2008, at 12:14 PM, Rich Hickey wrote:

I suggest using keywords for commands. They evaluate to themselves and
there is no purpose to entering them at the repl otherwise (other than
demonstrating that keywords evaluate to themselves, I guess). Commas
violate the read/data rules and are ugly.

More important, I don't see a strong case for commands yet. Commands
for printing the last object read and the last evaluated value and
last stack trace are substantially less useful than vars that evaluate
to those values. While * isn't available, *1 *2 *3 *ex (and various
other possibilities) are.

I've uploaded a patch that provides *1, *2, *3, *e, and *r. *1, *2, and *3 are the 3 most recent evaluated values. *r is the most recently read object, and *e is the most recent exception. They are all bound to nil initially.

http://clojure.googlegroups.com/web/star-vars.patch

Where a command might be useful is as a shortcut for "(.printStackTrace *e)". I experimented with writing the stack trace to a string and storing that, but when the repl prints it, it's as one horizontal string with embedded "\n" and \t".

Here's an example of the star-vars in action:

Clojure
user=> (+ 3 4)
7
user=> (+ 1 5)
6
user=> (* *1 *2)
42
user=> *r
(* *1 *2)
user=> *e
nil
user=> egan
java.lang.Exception: Unable to resolve symbol: egan in this context
user=> *e
clojure.lang.Compiler$CompilerException: NO_SOURCE_FILE:0: Unable to resolve symbol: egan in this context
user=> (.printStackTrace *e)
clojure.lang.Compiler$CompilerException: NO_SOURCE_FILE:0: Unable to resolve symbol: egan in this context
at clojure.lang.Compiler.analyze(Compiler.java:3713)
at clojure.lang.Compiler.analyze(Compiler.java:3671)
at clojure.lang.Compiler.eval(Compiler.java:3895)
at clojure.lang.Repl.main(Repl.java:88)
Caused by: java.lang.Exception: Unable to resolve symbol: egan in this context
at clojure.lang.Compiler.resolveIn(Compiler.java:4015)
at clojure.lang.Compiler.resolve(Compiler.java:3972)
at clojure.lang.Compiler.analyzeSymbol(Compiler.java:3955)
at clojure.lang.Compiler.analyze(Compiler.java:3686)
... 3 more
nil
user=> 

Parth and Rich: Thanks very much for your comments and suggestions.

--Steve

Rich Hickey

unread,
Sep 18, 2008, 12:46:23 PM9/18/08
to Clojure
Thanks Steve,

I'm willing to add this with a couple of changes:

You can def the vars in boot.clj, with no roots. Please provide doc
strings.

Lose *r, it's not really useful

In the Repl, push bindings for them (where ns is pushed), then use
star1.set(...) etc to update the per-thread binding. As written, these
vars can't be used by more than one repl/thread without conflict.

Thanks,

Rich

Stephen C. Gilardi

unread,
Sep 18, 2008, 6:02:49 PM9/18/08
to clo...@googlegroups.com

On Sep 18, 2008, at 12:46 PM, Rich Hickey wrote:

Thanks Steve,

I'm willing to add this with a couple of changes:

You can def the vars in boot.clj, with no roots. Please provide doc
strings.

Lose *r, it's not really useful

In the Repl, push bindings for them (where ns is pushed), then use
star1.set(...) etc to update the per-thread binding. As written, these
vars can't be used by more than one repl/thread without conflict.

Thanks Rich, I've uploaded star-vars-2.patch to the file area of the Clojure group which implements these changes. Please let me know it needs further refinement.

--Steve

Rich Hickey

unread,
Sep 18, 2008, 8:36:56 PM9/18/08
to Clojure
Patch applied (plus some tweaked error handling), thanks!

Rich

Mike Hinchey

unread,
Sep 20, 2008, 7:27:07 PM9/20/08
to Clojure
I added support for *1 *2 *3 in my fork of swank-clojure (for emacs/
slime), http://github.com/mikehinchey/swank-clojure.

I did one thing different which is to not reset the vars if the eval
is one of the vars themselves. Rich noted most CL repls don't do
this, but it seems useful to me. Thoughts?

user> :a
:a
user> :b
:b
user> :c
:c
user> *1
:c
user> *2
:b
user> *3
:a
user> (list *1 *2 *3)
(:c :b :a)

Stephen C. Gilardi

unread,
Sep 20, 2008, 9:02:23 PM9/20/08
to clo...@googlegroups.com
On Sep 20, 2008, at 7:27 PM, Mike Hinchey wrote:

I added support for *1 *2 *3 in my fork of swank-clojure (for emacs/
slime), http://github.com/mikehinchey/swank-clojure.

I'm glad to see this support in swank-clojure. Thanks!

I did one thing different which is to not reset the vars if the eval
is one of the vars themselves.  Rich noted most CL repls don't do
this, but it seems useful to me.  Thoughts?

I think it's good idea. It does seem a shame to lose one of these values as a result of looking at one. I had considered it, but didn't see how to implement it reasonably. Having been shown the way on that (thanks!) I'm in favor. 

Other thoughts?

--Steve

Stuart Sierra

unread,
Sep 22, 2008, 8:08:41 PM9/22/08
to Clojure
Thanks, Steve, Rich. This is useful.
-Stuart
Reply all
Reply to author
Forward
0 new messages