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.
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
- 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.
- The stack trace adds nothing to the error. If anything, it makes it less understandable, as the sheer amount of text is offputting.
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.
It’s unfortunate that reporting errors is so much harder than detecting them.
On Aug 20, 2016, at 9:03 AM, Alex Miller <al...@puredanger.com> wrote: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)
On Aug 20, 2016, at 9:03 AM, Alex Miller <al...@puredanger.com> wrote:
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.
On Aug 20, 2016, at 9:03 AM, Alex Miller <al...@puredanger.com> wrote: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)This is interesting. Here’s why I missed it. I attach the error message I saw from `lein midje`. Notice that the spec error appears twice, once at the top, once at the end. The line showing the source file appears only with the top one. The one at the bottom of the screen is the one I looked at. I think that’s pretty natural.
I disagree (strongly) with your position here Brian. I’ll try to explain clearly why but first a little background…
At World Singles, we’ve always done multi-version testing against the stable version of Clojure that we plan to use in production and also against the very latest master SNAPSHOT. This gives us an early heads up when a breaking change is introduced. When the ns spec hit master, our build broke. We had three namespaces with incorrect syntax – based on the documentation and what all the books and tutorials show – so we simply fixed them (one was require, two were import). Luckily none of the libraries we rely on had similar breakages.
Then we moved to Alpha 11 and found another namespace with require – clearly our tests don’t have sufficient coverage (duly noted, JIRA issue to follow I expect).
Despite having to fix our code, we welcome the stricter compiler checking here. There are very few things in language design that frustrate me more than preserving bad compiler behavior in the name of “backward compatibility” on the grounds that “if we fix this, people who have code that we never intended to work will see breakages, and be forced to correct their bad code”. That’s what you’re asking for here: that Clojure/core preserve unintended behavior so that people who have code that works “accidentally” aren’t forced to modify their code to match what has always been intended.
Why do I feel so strongly about this? A few things… I built one of the first ANSI-validated C compilers which focused on “the letter of the law” as far as flagging undefined, unspecified, and implementation-defined behavior. After that, I was on the ANSI C++ Standards Committee for eight years where we had to deal with this same sort of issue over and over again in terms of deciding what unintended legacy behaviors should be enshrined as standard vs outlawed (vs pushed to one of those three behaviors). After all that standards work, I then had to deal with Macromedia / Adobe ColdFusion on and off since 2001: a product that values backward compatibility so deeply that it repeatedly does exactly what you’re asking Clojure/core to do – it won’t fix any number of bugs because they might break unintentionally working code. You can’t begin to imagine what decades of that position does to a language – it’s a horrible, inconsistent, mess of a language, full of special cases, warts, and surprising behavior. I wouldn’t wish that on any sane developer.
Sean Corfield -- (904) 302-SEAN
An Architect's View -- http://corfield.org
--
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
---
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+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
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+unsubscribe@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 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
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+unsubscribe@googlegroups.com.
On Aug 20, 2016, at 5:26 PM, se...@corfield.org wrote:I disagree (strongly) with your position here Brian. I’ll try to explain clearly why but first a little background…
--
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
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+unsubscribe@googlegroups.com.
On Aug 20, 2016, at 6:30 PM, Timothy Baldridge <tbald...@gmail.com> wrote:Brian, let's make it more concrete then...why should the Clojure compiler continue to support undocumented features that make code unportable?
--
--
With respect to preserving undocumented behaviour, while in general I'm in favour of making compilers stricter, in this case it seems like the change breaks a lot of existing code in ways that are impossible for library consumers to fix themselves - they have to wait for an update to the library, or fork it. Leaving the symbol option seems like a very low-impact change, it's not going to be a massive amount of technical debt in Clojure itself. There are many areas of unspecified behaviour in the reader (for example, keywords starting with numbers, the keyword function allowing creation of unreadable keywords etc) which have not been fixed because it would break some existing code - I suspect the impact of fixing that would be far less than the impact of this change.I don't understand why this particular change is so important that significant breakage to real code is considered acceptable. I agree with Brian that it doesn't seem very pragmatic.
On 21 August 2016 at 13:22, Brian Marick <mar...@roundingpegs.com> wrote:
On Aug 20, 2016, at 6:30 PM, Timothy Baldridge <tbald...@gmail.com> wrote:Brian, let's make it more concrete then...why should the Clojure compiler continue to support undocumented features that make code unportable?Because:1. People who want to port to clojurescript will incur exactly the same cost as they do now.2. People who don’t want to port to clojurescript will incur no additional cost.3. Clojurescript maintainers will incur no additional cost.4. Clojure maintainers will incur the cost of adding “or symbol” to current code.5. No one writing documentation will incur any cost, as what was not mentioned before will continue to be unmentioned.6. There will be a psychic cost because of an undocumented inconsistency between clojure and clojurescript.7. If, at some point, clojure and clojurescript shared code for the implementation of `ns`, one or the other would have to change the pre 1.9-alpha11 behavior.Do I have this enumeration of costs wrong?It’s a bit surprising to me that my explicit appeal to consider costs and benefits to real people is not being addressed.
--
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
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+u...@googlegroups.com.
--
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
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+u...@googlegroups.com.
I'd prefer getting rid of the symbol option. Some kind of deprecation warning for a version or two might be an idea though.
--
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
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+u...@googlegroups.com.
So again I will state: while the current spec does not support the symbol version we are in an investigatory period and things may change before release.
As an update. I’ve fixed the `ns` oopsie in Suchwow (one file), and the coincident `ns` oopsie in Midje (one file). But this happens when running Midje’s self-tests against Clojure 1.9alpha11:
> Exception in thread "main" java.lang.IllegalArgumentException: Call to clojure.core/fn did not conform to spec:
> In: [0] val: clojure.core.unify/var-unify fails spec: :clojure.core.specs/arg-list at: [:args :bs :arity-1 :args] predicate: vector?
> In: [0] val: clojure.core.unify/var-unify fails spec: :clojure.core.specs/args+body at: [:args :bs :arity-n] predicate: (cat :args :clojure.core.specs/arg-list :prepost (? map?) :body (* any?))
> :clojure.spec/args (clojure.core.unify/var-unify [varp v expr binds] (clojure.core/if-let [vb__10124__auto__ (binds v)] (clojure.core.unify/garner-unifiers varp vb__10124__auto__ expr binds) (clojure.core/if-let [vexpr__10125__auto__ (clojure.core/and (varp expr) (binds expr))] (clojure.core.unify/garner-unifiers varp v vexpr__10125__auto__ binds) (if (clojure.core.unify/occurs? varp v expr binds) (throw (java.lang.IllegalStateException. (clojure.core/str "Cycle found in the path " expr))) (clojure.core.unify/bind-phase binds v expr)))))
> , compiling:(clojure/core/unify.clj:82:18)
I suspect the problem is that Midje uses an old version of clojure.core.unify (0.5.2). I use that old version because a later versions (like the current 0.5.7) failed in my use case for no reason I could quickly understand.
So I decided to just stick with the older, working version because forced upgrades make kittens suffer. And I am a kitten. And also: by semver
, why should a satisfied user of 0.5.2 care about 0.5.7?
(Note: I don’t know whether clojure.core.unify 0.5.7 is conformant to whatever spec is breaking.)
FYI, while I disagree with your conclusion (I think we should go fix libraries instead), I ran into the same issue just now for roughly the same reason, except the thing that pulled in an old version of core.unify was core.typed, which pulls in 0.5.3 through core.contracts.
Call to clojure.core/defn did not conform to spec: In: [1 0] val:
({:keys [money/major money/minor money/currency], :or #:money{major
0, minor 0, currency :EUR}}) fails spec:
:clojure.core.specs/arg-list at: [:args :bs :arity-1 :args]
predicate: (cat :args (* :clojure.core.specs/binding-form) :varargs
(? (cat :amp #{(quote &)} :form
:clojure.core.specs/binding-form))), Extra input In: [1 0] val:
{:keys [money/major money/minor money/currency], :or #:money{major
0, minor 0, currency :EUR}} fails spec:
:clojure.core.specs/arg-list at: [:args :bs :arity-n :bodies :args]
predicate: vector? :clojure.spec/args (format-money [{:keys
[money/major money/minor money/currency], :or #:money{major 0,
minor 0, currency :EUR}}] (str major "," (if (zero? minor) "-"
minor) " €"))
On Aug 22, 2016, at 11:23 AM, Leon Grapenthin <grapent...@gmail.com> wrote:Still the error messages are simply far from good enough and that is what appears to me as the main problem OP has.
--
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
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+unsubscribe@googlegroups.com.
I'm interested to see any discussion regarding this point. No doubt translating spec data into more friendly formats has been discussed.Getting the data right is clojure's problem. That's the concrete foundation and building blocks required for tooling. Seems like Rich has done spectacularly there.Potentially it's up to tooling to do more with that data. I'd love to hear Bruce (figwheel), Collin's (cursive) and Bozhidar (cider) opinions about that.
I agree that the ability to get a machine-readable parse failure is very important for tooling. However I feel very strongly that the error messages that are printed by default on macro validation failures should be easily understandable, and the current ones are not. If we completely punt to tooling for this, firstly users will receive different (and different quality) error messages depending on the tool they're using, and anyone using plain vanilla Clojure will not get good errors at all.
The big syntax macro cases like ns or let are way past the "average" spec. ... I don't think it's fair to judge the general performance of spec's errors on just those use cases.
--
Sorry, I missed this one in the thread somehow. This happens to be a case where you have *both* defn and destructuring specs in play, so it has even greater potential for confusion in generic errors.
I welcome the strict checking over backwards compatibility for broken syntax. E. g. allowing things like symbols in the ns decl would require supporting that as a feature in future updates, analyzer code, other hosts etc. The Clojure devs should not have to worry things with so little use.Still the error messages are simply far from good enough and that is what appears to me as the main problem OP has. If the compiler had pointed him to two fixes he could have done in a minute then he had not complained and instead felt more happy with his new compiler.Here is my story when I loaded a large codebase today with 1.9-alpha11:
You mentioned you knew exactly the location and the above gives you the form that is failing to match, so you've narrowed it down to a particular form in a particular file.
here's the actual value that is failing - so this does include the part that's wrong (:or map with non-symbol keys)
here we name another spec - you can use this to (doc :clojure.core.specs/arg-list) to get more info (and so on). There will be probably be some kind of a way to do this in a "deep" way at some point.
the path through the specs - can be combined with the spec name above and the spec for defn to give you a lot more info - this is the kind of thing that a sideband tool in an IDE could do amazing things with.
the predicate that is actually failing in the spec, probably not particularly helpful given the complexity (and recursiveness) of the destructuring specs
this is the part of cat that I think could be made more explicit - could be saying here that the value it had (above) was expected to match the next part of the cat (binding-form). So that could say the equivalent of "Expected binding-form but had non-matching value ..." and could even find what parts of that value matched and maybe which didn't (the :or keys) such that you'd have a more precise description. There is some more stuff Rich and I have worked on around "hybrid maps" which is the case here with map destructuring - it's particularly challenging to get a good error out of that at the moment, but there's more that can be done.
This whole block is another (non-applicable) alternative that spec tried out (the multi-arity case). We know that's not what we were trying to do, but it's reported anyways. This is where fan-out kicks in and you can get a lot of noise that's not applicable. I think there's probably enough information to either be better about saying which case we thought you were matching or to hide some of them, etc.
And this is just reporting the actual passed args to the macro - I think this is confusing because it doesn't look like the call (because it's missing the macro name). As I said prior, I think this particular part of macro error reporting can do better as it knows more about what's going on - this should really be tied back up to the macro name at the top.
--
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
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+unsubscribe@googlegroups.com.
In the data representing fragments of the user's code returned with these macro errors, does it include metadata with :line and :column keys in it?
On Aug 22, 2016, at 7:50 PM, Alex Miller <al...@puredanger.com> wrote:
You've complained in other channels about the "learning to read" error messages part and I think you've taken it entirely the wrong way or maybe I just disagree. There are benefits from reporting errors in a generic, consistent way. […]
- Getting the error data (specifically the explain-data output) to be both sufficient and generically useful is the first priority. I think at this point that's pretty close and unlikely to change significantly.
--
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
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+unsubscribe@googlegroups.com.
So we need players. I would rant here, but I won't. But look at this guitar player with blisters. A harpist has blisters, a bass player with blisters. There's this barrier to overcome for every musician. Imagine if you downloaded something from GitHub and it gave you blisters.[Audience laughter]Right? The horrors! And yet how many people here play an instrument or have at one point in their lives? Yeah, a lot of programmers do. And for how many people did you just pick it up and it was awesome? How many wished, like, something could have made it more straightforward to get started with and, like, just made it easy? And how many would have believed after that that they could play it later? No, not at all. This is - it's actually quite important. The level of engagement that's required is quite important.So we shouldn't sell humanity short. Humans are incredible. In particular, they're incredible learners.One of the things that's really cool is you give a five-year-old or, I don't know, eight, maybe, a cello and some decent instruction, and they will learn how to play cello if they spend enough time doing it. In fact, humans will pretty much learn how to do anything that they spend enough time doing. We're incredibly good at it.And we're also really good teachers, in general. So I don't think we need to go to our tools and our instruments and make them oriented towards the first five seconds of people's experience because that's not going to serve them well. It's especially not going to serve anyone well who wants to achieve any kind of virtuosic ability with the tools. No one would become a virtuoso on the cello if they had red and green lights when they started.So neither of these two things is effort free, but we shouldn't be in a game to try to eliminate effort because we are novices, right?There's a sense in which we're only going to briefly be novices.You're only a complete beginning at something for an incredibly short period of time, and then you're over it.It's like we should not optimize for that. But, on the flipside, we're always learners no matter how much time you spend on the violin. Who sits there and says, "I'm done. I've completed learning violin. I finished it"? That's awesome. I personally don't play violin at all, but I don't think there would be a player on earth, no matter how great they are, who would say, "Yeah, I finished violin and I moved on to something else." We're constantly. It's just the human condition to do this.Things take effort. Just like we shouldn't target beginners, we shouldn't try to eliminate all effort.
--
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
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+unsubscribe@googlegroups.com.
We expect Clojure users to become familiar with spec and its output as it is (now) an essential part of the language. You will see specs in error messages.
But creating error messages that are optimal for a user with no knowledge or Clojure or spec is just not the goal.
--
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+u...@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+unsubscribe@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+unsubscribe@googlegroups.com.
predicate: (cat :args (* :clojure.core.specs/binding-form) :varargs (? (cat :amp #{(quote &)} :form :clojure.core.specs/binding-form))),the predicate that is actually failing in the spec, probably not particularly helpful given the complexity (and recursiveness) of the destructuring specsExtra inputthis is the part of cat that I think could be made more explicit - could be saying here that the value it had (above) was expected to match the next part of the cat (binding-form). So that could say the equivalent of "Expected binding-form but had non-matching value ..." and could even find what parts of that value matched and maybe which didn't (the :or keys) such that you'd have a more precise description. There is some more stuff Rich and I have worked on around "hybrid maps" which is the case here with map destructuring - it's particularly challenging to get a good error out of that at the moment, but there's more that can be done.
(s/def ::arg-list (s/and vector? (s/cat :args (s/* ::binding-form) ;; :varargs (s/? (s/cat :amp #{'&} :form ::binding-form)) )))
(s/explain (:args (s/get-spec 'clojure.core/defn)) '[foo [{:or {a/b 42}}]])
In: [1 0] val: {:or #:a{b 42}} fails spec: :clojure.core.specs/local-name at: [:bs :arity-1 :args :args :sym] predicate: simple-symbol?In: [1 0 0] val: ([:or #:a{b 42}]) fails spec: :clojure.core.specs/seq-binding-form at: [:bs :arity-1 :args :args :seq] predicate: (cat :elems (* :clojure.core.specs/binding-form) :rest (? (cat :amp #{(quote &)} :form :clojure.core.specs/binding-form)) :as (? (cat :as #{:as} :sym :clojure.core.specs/local-name))), Extra inputIn: [1 0 :or a/b 0] val: a/b fails spec: :clojure.core.specs/or at: [:bs :arity-1 :args :args :map :or 0] predicate: simple-symbol?In: [1 0] val: {:or #:a{b 42}} fails spec: :clojure.core.specs/arg-list at: [:bs :arity-n :bodies :args] predicate: vector?
--
On Aug 24, 2016, at 8:39 AM, Stuart Halloway <stuart....@gmail.com> wrote:3. "Follow the inverted pyramid so people see what is most important." This kind of thing is easily done in a layer above spec, e.g. a custom REPL printer for spec macro errors. Worth working on but not critical to getting spec right.
On Aug 24, 2016, at 9:28 PM, adrian...@mail.yu.edu wrote:I do not think your tone and lack of constructive feedback to Alex's (and others) thoughtful responses is helping your case.
I really don't understand how you expect anyone to take your criticism seriously if you keep implying you're happily abandoning the language for greener pastures.Why would anyone developing Clojure look at anything you have to say at this point as anything less than trolling?Back on topic, I find Colin's suggestions about implementing an error reporting heuristic intriguing. What he has laid out could form the basis for a solution to this problem which can satisfy everyone's requirements when integrated well with spec's explain-data. I am curious to hear what Alex and others think about it.
--
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+unsubscribe@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 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
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+unsubscribe@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+unsubscribe@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 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
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+unsubscribe@googlegroups.com.
I really don't understand how you expect anyone to take your criticism seriously if you keep implying you're happily abandoning the language for greener pastures.
Why would anyone developing Clojure look at anything you have to say at this point as anything less than trolling?
--
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+u...@googlegroups.com.
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 inputYou 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 inputspecs way of saying that it found something (the val above) but it wasn't what the spec expected nextI'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 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
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+unsubscribe@googlegroups.com.
I think one obvious area that specs error messages could be improved is with some basic formatting and cosmetic changes. If spec presented errors not as a wall of text and syntax but with some simple formatting it would make a big difference to legibility.
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+unsubscribe@googlegroups.com.
One thing that I think would help a lot would be if it were possible to show the actual text from the failing expression rather than pretty printing a seq representation of it. This would mean modifying the reader such that it either caches the program text from each top-level form as it reads it, or perhaps re-reading the file on an error. This means the relevant code is likely to look more familiar to the user, and also avoids any need to pretty print. Pretty printing is likely to be complicated since it normally works top-down, and uses the type of each form to decide how to lay its sub-parts out. If you're only pretty-printing a fragment from within, say, a large ns form, pprint is unlikely to format it as the user would expect.
Hi Rick,That looks really excellent, and is a huge improvement. Particularly in combination with Leon's proposed change which more precisely identifies the likely failing part of the grammar, this looks like a big win for not much extra effort.
One thing that I think would help a lot would be if it were possible to show the actual text from the failing expression rather than pretty printing a seq representation of it. This would mean modifying the reader such that it either caches the program text from each top-level form as it reads it, or perhaps re-reading the file on an error. This means the relevant code is likely to look more familiar to the user, and also avoids any need to pretty print. Pretty printing is likely to be complicated since it normally works top-down, and uses the type of each form to decide how to lay its sub-parts out. If you're only pretty-printing a fragment from within, say, a large ns form, pprint is unlikely to format it as the user would expect.
--
I agree that tidied up the error messages are much more understandable. Replacing things like "path" with a description of what it means goes a long way. My main issue with the original error which persists in your version is that the failing predicate really doesn't help much identifying the problem. However Leon's investigations hopefully will help to make that better by more precisely identifying the failing predicate.
I'd envisioned the source text for a particular top-level form only being held for as long as required to eval or compile the form, not being stored permanently in metadata.
But I'd have to go and look at the code to see if that's feasible or not. AOTing would not be a problem since the macroexpansion errors would be found when the form was AOTed, those errors would never occur at runtime.
Thanks for the kind words about Cursive too, one of my main goals is to make Clojure more approachable (hence the obsession with error messages), so I'm glad it's helped your co-workers! And you never know, maybe you'll like it enough one day to switch :-)