Friendlier error messages, no perf hit

295 views
Skip to first unread message

John D. Hume

unread,
May 12, 2015, 10:09:49 AM5/12/15
to cloju...@googlegroups.com
Hi all,
I'd like to follow up on an idea I first heard floated by Alex Miller at Elena Machkasova's Clojure/West talk (https://youtu.be/k5erDyDPzgc). The context was that Elena's group has created a library that replaces common clojure.core functions with wrappers that do extensive argument validation and provide error messages that are easy for intro-to-CS students to understand. (16:20 in the video is where she talks about that specific approach.)

Alex suggested possibly putting pre & post conditions (or assert-args, whatever) that could produce error messages helpful for a Clojure beginner in clojure.core itself and wrapping those checks in reader conditionals to omit them from the standard clojure.jar while providing an alternative "friendly" jar with all checks included.

I like this idea and want to nudge it forward.

It seems there are at least two issues that would need to be decided for anything to happen:

1. Do the benefits of adding such a thing to Clojure outweigh the costs?
- The primary drawback would seem to be added code for the maintainers to deal with. Hopefully the checks could by succinct and expressive enough that they'd be comparable to docstrings.
- Maybe being tied to Clojure's release cycle would be a hindrance to the development of the verbose checks, but this seems like a minor issue.

2. How should the brand new Reader Conditionals feature be modified to support such a thing?
- I haven't experimented with it, but my reading of http://dev.clojure.org/display/design/Reader+Conditionals it that it's an error to put a reader conditional into a .clj file. Should reader conditionals be allowed in all clojure code?
- Should Clojure specify and support standard features beyond the existing platform features?
- There would need to be some new way to specify a reader feature set when building Clojure. On the JVM this could be a system property. I don't know what makes sense for ClojureScript or the CLR. I would think the same approach should work for dynamically loaded (non-AOT) code and be useable by third party code.

Are there other issues I'm missing?

Thanks.
-hume.

adrian...@mail.yu.edu

unread,
May 12, 2015, 10:46:35 AM5/12/15
to cloju...@googlegroups.com
This is already supported through the assert macro, which pre/post conditions expand into. It only expands into code when *assert* is true. 

Andy Fingerhut

unread,
May 12, 2015, 12:14:54 PM5/12/15
to cloju...@googlegroups.com
Is there an implementation of the idea that has been published somewhere?

Does anyone know how it compares performance and feature-wise to dynalint and Dire?  https://github.com/frenchy64/dynalint/issues/6

I am not against the possibility of having something like this in core.  But if performance overhead can be made low enough with a not-in-core approach, e.g. perhaps via aggressive use of alter-var-root, then it could be usable much sooner.

Andy

--
You received this message because you are subscribed to the Google Groups "Clojure Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure-dev...@googlegroups.com.
To post to this group, send email to cloju...@googlegroups.com.
Visit this group at http://groups.google.com/group/clojure-dev.
For more options, visit https://groups.google.com/d/optout.

John D. Hume

unread,
May 12, 2015, 6:36:05 PM5/12/15
to cloju...@googlegroups.com
On Tue, May 12, 2015 at 9:46 AM, <adrian...@mail.yu.edu> wrote:
This is already supported through the assert macro, which pre/post conditions expand into. It only expands into code when *assert* is true. 

Is there a good way to get *assert* set to false before clojure.core is loaded? The idea is not to have optional pre- and post-conditions in user code, it's to add them to clojure.core fns.



On Tue, May 12, 2015 at 11:14 AM, Andy Fingerhut <andy.fi...@gmail.com> wrote:
Is there an implementation of the idea that has been published somewhere?

I believe the current work from that group is here:
https://github.com/Clojure-Intro-Course/clojure-intro-class

Agreed that something like alter-var-root would probably be a good way to get their pre-conditions in place from a 3rd-party lib.

Ambrose Bonnaire-Sergeant

unread,
May 12, 2015, 6:50:23 PM5/12/15
to cloju...@googlegroups.com
On Wed, May 13, 2015 at 8:36 AM, John D. Hume <duelin....@gmail.com> wrote:

Agreed that something like alter-var-root would probably be a good way to get their pre-conditions in place from a 3rd-party lib.

This is how dynalint works. From communications via Alex Miller, Rich is not interested in this ad-hoc approach. I believe a more integrated debug-mode is more desirable, which he has mentioned at Clojure Conj 2012.

Thanks,
Ambrose

John D. Hume

unread,
May 14, 2015, 12:15:54 AM5/14/15
to cloju...@googlegroups.com
On Tue, May 12, 2015 at 5:50 PM, Ambrose Bonnaire-Sergeant <abonnair...@gmail.com> wrote:
This is how dynalint works. From communications via Alex Miller, Rich is not interested in this ad-hoc approach. I believe a more integrated debug-mode is more desirable, which he has mentioned at Clojure Conj 2012.


One obvious option worth considering would be to use the Java library's assertion support. There are already command line options for globally enabling or disabling as well as targeting specific packages and/or classes. An advantage is that one compiled binary can carry helpful assertions while the JVM can easily optimize away disabled assertions.

For those unfamiliar, in any Java class that uses assert, javac generates a static final boolean field called "$assertionsDisabled," set based on a call to Class#desiredAssertionStatus(). Each assert compiles into the equivalent of:
  if(!$assertionsDisabled) if(!assertedExpr) throw new AssertionError(yourMessage);

If assert were a special form, it would be easy to do the same thing as javac. At the moment it doesn't seem to me like it could be done from a plain macro, but I may be too tired to realize it's possible.

I wouldn't be surprised if Rich Hickey considered this approach when implementing clojure.core/assert in the first place and decided it was a poor fit. If so, knowing why might be helpful for better understanding what sort of debug mode would make sense for Clojure to provide more helpful error messages.

-hume.


Elena Machkasova

unread,
May 19, 2015, 4:29:13 PM5/19/15
to cloju...@googlegroups.com

Hi All,


I was very excited to see this discussion! I think it would be great to have the ability to run Clojure with beginner-friendly messages (by using a flag or some such on the user side -- and reader conditionals may be a way to go). Integrating such a mode with clojure.core would make maintenance easier since it would be immediately clear where changes to core affect error messages.


However, there are a couple of things to clarify here:

  • We are working on transforming/augmenting error messages, but at this point I wouldn’t call it a library, it’s very much an in-development thing with quite a few quirks for historic reasons. The technical side of things would need to be modified. It’s not a huge undertaking, but makes this a bit more fragile than it already is.

  • The error messages are not tested in a real-life usage on the target audience (which, for us, is learners with no programming background at all). I suspect that for that audience we will need to simplify a few things even from what we now consider quite simple.

  • Messages that would be ideal for beginners with no programming experience may not (or may -- we just don’t know) be a good fit for Clojure beginners that come from other programming background. It would be really confusing/unwise to be making adjustments reactively (and therefore likely inconsistently) between different versions of Clojure trying to serve both categories of beginners.

  • Ideally beginner-friendly messages should eventually be incorporated with debugging and refactoring tools. While this is a long road, it’s important not to discover later that error messages and debugging/refactoring tools cannot be easily connected, technically or in terms of terminology/approaches. Macros are one possible source of issues here.

There is also a bigger issue of what error messages in Clojure should be, for all users. Is Clojure committed to Java exceptions? With all the good reasons for this (after all, Clojure errors *are* Java exceptions!), it is an adoption barrier.


In practice, I think for now we will continue with developing an independent wrap-up around clojure.core functions and, hopefully, study its usability in a real-life learning experience. If this looks promising, means of integrating it into clojure.core should be discussed. I am just worried that this is a fairly drastic step, and would like to see it done (reasonably) right the first time.


But I would love to revisit this discussion once we have a set of pre-conditions based messages that are (provably) working well for beginners.


Cheers,

Elena


Andy Fingerhut

unread,
May 21, 2015, 2:33:05 PM5/21/15
to cloju...@googlegroups.com, Elena Machkasova
Elena:

I would encourage you and your group to try out Dynalint.  It does not include the additional string library or sequence functions that you have worked on -- it focuses on improved error messages when one calls Clojure functions with incorrect arguments (and a few macros).  I have a fork of the project that has some changes that I believe are improvements to the documentation, and a tiny bit on functionality.  I'd be happy to assist you in learning how to customize the messages or enhance it in other ways.

I have not released my modifications anywhere as a JAR file yet, so if you want to try it out at this moment you need to install the JAR locally on any machine where you want to try it.  Here are the steps to do that.

cd dynalint
lein install

The last step will make a JAR file and install it in a subdirectory beneath your $HOME/.m2 directory somewhere.

Then follow the instructions in the README [2] showing how to add a few lines to your project.clj file.  Be sure to use the version number 0.1.4-SNAPSHOT rather than the 0.1.3 mentioned in most places in the README right now (0.1.3 is the latest normally-released version).

Andy




Elena Machkasova

unread,
May 21, 2015, 3:04:21 PM5/21/15
to cloju...@googlegroups.com
Sounds good, will do. I am not familiar with it, but it's been on our to-look-into list for quite some time. Thanks!

Elena

--
You received this message because you are subscribed to a topic in the Google Groups "Clojure Dev" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojure-dev/A_BXNne8w44/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojure-dev...@googlegroups.com.

To post to this group, send email to cloju...@googlegroups.com.
Visit this group at http://groups.google.com/group/clojure-dev.
For more options, visit https://groups.google.com/d/optout.



--
Dr. Elena Machkasova
Associate Professor of Computer Science
Division of Science and Mathematics
University of Minnesota, Morris
Office: Sci 2325

Reply all
Reply to author
Forward
0 new messages