I think there's considerable scope to produce better error messages
automatically than what spec produces, and I hope that can happen for 1.9.
The error message produced by the code I demoed at the conj last year would
be:

Unexpected symbol 'require' at <exact error location> while parsing
namespace clauses. Expected :refer-clojure, :require, :use, :import, :load
or :gen-class.

The only thing the grammar developer needs to do to get that error is to
provide a descriptive name of "namespace clauses" for the main alternation.
If they don't do that, the error message would just say "...while parsing
clojure.core/ns..." instead, which is still acceptable.

There is plenty of prior art on how to do this, it's not a "people are
hard" problem. I think the precise error messages you want for validating
data structures are not optimal for code error messages. I know the mantra
is that code is data, but in this case I believe that a specialised
implementation for code is superior. But I realise that ship has sailed.

On 21 August 2016 at 02:03, Alex Miller <a...@puredanger.com> wrote:

>
>
> On Saturday, August 20, 2016 at 5:17:59 AM UTC-5, Brian Marick wrote:
>>
>> Yesterday, a bug was filed against Suchwow under 1.9alpha11. It turns out
>> to have been a use of `ns …(require…` instead of `(ns …(:require`. Not in
>> Suchwow, but in Midje. Unfortunately, the Suchwow file the bug report
>> pointed at *also* had that typo - apparently I am prone to it - so adding
>> the colon to the require there didn’t make the problem go away.
>>
>> That caused me to lose my temper and make a fool of myself, which is
>> neither here nor there, except that I apologize to @puredanger.
>>
>> I have two suggestions, though:
>>
>> 1. It has long been the case that Clojure allowed `(ns (require…)` even
>> though that’s strictly incorrect. I suggest that, for backwards
>> compatibility, it be allowed going forward. That is, I think it does no
>> harm for a correct `ns` statement to allow symbols as well as keywords.
>> That wrong code in Midje has been there since Clojure 1.2.
>>
>
> We discussed this before releasing the specs and decided to start on the
> strict side. That said, this is still an alpha and there is plenty of time
> to change our minds prior to official release of 1.9 if that ends up being
> a catastrophic decision.
>
>
>>
>> 2. The following is not a good error message:
>>
>> Exception in thread "main" java.lang.IllegalArgumentException: Call to
>> clojure.core/ns did not conform to spec:
>> In: [2] val: ((require [such.vars :as var] [such.immigration :as
>> immigrate]) (require midje.checking.checkers.defining
>> midje.checking.checkers.chatty midje.checking.checkers.simple
>> midje.checking.checkers.combining midje.checking.checkers.collection))
>> fails at: [:args] predicate: (cat :attr-map (? map?) :clauses
>> :clojure.core.specs/ns-clauses),  Extra input
>>
>
> You left out this next important line too since it points you to exactly
> the file and line where the error occurs:
>
> , compiling:(such/sequences.clj:1:1)
>
> spec produces very detailed error messages driven by the specs and the
> value being validated. I admit that in some cases the output from a spec
> error (particularly for complicated syntaxes where there are wide
> alternative fan-outs) is daunting. However, spec error messages are going
> to be increasingly common for all of us to see and understand and I think
> it is worth taking the time to slow down and actually read them.
>
> > Call to clojure.core/ns did not conform to spec:
>               ^^^^^^^^^^^^^^ <- macro that was passed invalid values
> > In: [2]
>         ^^^ <- the data path in the :args passed to the macro, here, the
> 2th element is the require clause (ns = 0, such.sequences = 1)
>
> > val: ((require [such.vars :as var] ...)
>          ^^ <- the remaining part of the value that did not match (it has
> already matched or "consumed" the first two elements successfully)
>
> > fails at: [:args]
>                ^^^^^^ <- the path in the ns fdef spec to the failure point
>
> > predicate: (cat :attr-map (? map?) :clauses
> :clojure.core.specs/ns-clauses),
>                     ^^^etc -> the remaining part of the spec it was trying
> to match
>
> > Extra input
>   specs way of saying that it found something (the val above) but it
> wasn't what the spec expected next
>
>
> I'm not trying to pretend this is as easy to digest as an error message
> that would be produced by hand-written validation and error code, but it's
> also notoriously difficult to cover all possible cases (which is why the
> Clojure DSLs have so many error gaps despite having a lot of that code). We
> are looking to decrease the amount of custom error detection and reporting,
> so anything we do has to be something we can do generically.
>
> For the specific case of macroexpanded error reporting, I think there
> *are* more things we can do here (generically) that will improve
> readability. We *know* we are in the context of checking an fdef spec on a
> macro, so some of the ":args" stuff is maybe not necessary. Having the val
> and predicate for a s/cat forwarded to the point of mismatch is both great
> (as it's specific) but also confusing (because parts of both the input and
> the cat spec) are missing which removes important context. I think there
> are ways to indicate that's happening better. Earlier versions of this also
> reported the full args and we ended up removing that because in many cases
> it feels redundant (or is potentially large). Maybe there is some heuristic
> we could follow on when that would help.
>
>
>> - It would be better to say “`require` should be a keyword, not a symbol”
>> than "fails at: [:args] predicate: (cat :attr-map (? map?) :clauses
>> :clojure.core.specs/ns-clauses),  Extra input”
>>
>> - Suggest Clojure.spec error messages follow the “inverted pyramid”
>> structure of news reports: https://en.wikipedia.org/wiki/Inverted_pyramid 
>> That
>> would mean the text message about the error would come first, the spec
>> second, and the wrong expression last.
>>
>> - It would be better to name the namespace that has the problem.
>>
>
> As mentioned above, the next line that you omitted points to the file and
> line with the problem (I went to some trouble to ensure that was reported
> properly from the point of use).
>
>
>> - The stack trace adds nothing to the error. If anything, it makes it
>> less understandable, as the sheer amount of text is offputting.
>>
>
> I agree, but this is to some degree an orthogonal issue. Tools (including
> the base REPL) choose what to do when they receive an exception from the
> compiler.  I would like to think more carefully about what the compiler is
> producing (informationally) and also how tools should be expected to handle
> these errors. Certainly in cases like this, the stack trace is unnecessary
> and that's true of many compiler errors. That is a fixable problem and I am
> interested in making improvements in this area still in 1.9.
>
>
>> My https://github.com/marick/structural-typing does (a small) part of
>> what clojure.spec does. I went to a lot of effort to get it to produce good
>> error messages, and it turned out OK. I doubt it would be applicable to
>> clojure.spec, but I’d be happy to sign over any code that could be of use.
>>
>
> Thanks, I doubt there's much we could use directly.
>
>
>> It’s unfortunate that reporting errors is so much harder than detecting
>> them.
>>
>
> Indeed. Unfortunately errors are read by people and people are hard. :)
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@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+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@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+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to