This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-01-11
Channels
- # admin-announcements (8)
- # announcements (1)
- # boot (343)
- # braid-chat (23)
- # cider (20)
- # clara (5)
- # cljsrn (48)
- # clojars (5)
- # clojure (90)
- # clojure-canada (3)
- # clojure-czech (1)
- # clojure-russia (107)
- # clojure-sg (2)
- # clojurebridge (2)
- # clojured (10)
- # clojurescript (70)
- # community-development (73)
- # cursive (106)
- # datavis (40)
- # datomic (40)
- # docs (4)
- # editors (1)
- # emacs (1)
- # events (4)
- # funcool (2)
- # hoplon (46)
- # jobs (2)
- # ldnclj (11)
- # mount (8)
- # om (214)
- # onyx (12)
- # re-frame (35)
- # reagent (31)
- # spacemacs (12)
- # yada (18)
In a function argument list, if I refer to some earlier argument in the list at some later point in the list, Cursive marks it as undefined. Is this a bug?
moving :or
to (let [b (or (b (first a))]
should fix that, but I'm guessing that's not how you want to write that code
I think you are in the area of "undefined" wrt ordering and you shouldn't do that
no, related to destructuring
destructuring is a macro, so order of evaluation is up to the macro
there are known issues with relying on the ordering of binding in :or for example - the :or definition is an (unordered) map, so each :or binding might be evaluated in any ordering (and this ordering has changed between releases in the past)
the assumption here is that the sequential outer destructuring binds a prior to the associative destructuring bindings in :or
@alexmiller: that's good to know
Oh I see, that makes sense. But in this case isn't the a
outside of the map destructuring clause so the order should be defined?
@jaen: that's true, I'm really just thinking through this as I type
it does seem to work at the repl, I'm just trying to convince myself that Clojure would guarantee that it should
I added explicit code for handling some of the tricky :or
cases, but I might have missed that one. I actually didn’t realise that the values of :or
could refer to other parameters.
Like @alexmiller says, it sounds like a recipe for ordering confusion
But I’m assuming that all the :or
clauses are evaluated after the actual parameters are bound.
I think that code is making an assumption about how defn works that is not guaranteed by any docs or reference material
which does not mean it doesn't work now or for an arbitrary period of time, but also means it could stop working at some future point
seems like it should let you configure additional symbols to be indented like e.g. defn, ec.
@jaen: I'd say the vector guarantees that the incoming arguments are maintained in order. it does not necessarily mean that defn binds the incoming arguments to the parameters in order (although that's a reasonable assumption)
@spieden: It does. Place the caret on the head symbol of the form you’d like to change indentation for. From the popup, select the option that corresponds to the formatting you need.
@spieden: That specific instance of the form will be reformatted right away, others will need to be reformatted explicitly.
@jaen: for example, the defn macro implementation could pair up parameters and arguments in an (unordered) map and then let bind them in arbitrary order
@alexmiller: hmm... if I understand you correctly - given Clojure has strict evaluation what you mean is that, before calling a function, the arguments are evaluated left to right in the order of the argument vector, but the order compiler resolves binding names might not be sequential nonetheless, even though they are defined in a vector?
@jaen yes, essentially - those are two separate things - the vector in a defn is just syntax defined by the defn macro - it's up to defn how it's interpreted
The fact that the indent is two spaces is set separately in Settings->Editor->Code Style->Clojure->Indent
Cursive indents forms assuming that you have a head symbol, some number of parameters, and then some number of body forms
So the head symbol gets no indentation, then the parameters are all aligned, then the body forms are all just indented from the parent.
@alexmiller: gotcha; though I must say it might be somewhat confusing for the programmer given that vectors in Clojure imply ordering.
No worries, it needs some explanation in the doc, for sure, and probably in the popup too
@cfleming: careful how you talk about my little emoticon buddies - they have feelings too, you know
@jaen @alexmiller looking at it slightly differently, one could argue that this should be explicitly considered bad coding and no guarantees made as to the order of binding of args to params
I disagree. I can agree that {a :a b :b :or {a b b a}}
is certainly bad coding, because maps don't guarantee ordering. But a vector?
the vector does guarantee the order of binding of arg to params, but not evaluation of params in the :or destructing
Well, if you say
> vector does guarantee the order of binding of arg to params
then [a & {:keys [b] :or {b (first a)}}]
is valid according to that. a
is ordered before the destructuring map.
The thing Alex is trying to point out that there can be an abstraction leak of an implementation detail here - if the macro implementation is using a map (which are unordered) to store the parameter names, not a vector, it will break that guarantee.
I don't like overly complex destructing in the param def but I'm not sure I can win this argument.
Oh sure, I agree overtly complex destructuring is bad, it quickly starts becoming less readable than having a let
in the body and destructuring there
I used to have an annoying friend that had a habit of saying "I agree with you 100% but..."
@jaen: fwiw, I agree with you that your expectation is reasonable, and that it shouldn't be ambiguous :)
destructuring is actually implemented in clojure.core/destructure - a fn that rewrites into the bindings for a let
so this example would be invoked with something like (destructure '[[a & {:keys [b] :or {b (first a)}}] [[1]]])
where the data being bound is [[1]]
the result (re-formatted a bit) is the binding part of a let:
[vec__21 [[1]]
a (clojure.core/nth vec__21 0 nil)
map__22 (clojure.core/nthnext vec__21 1)
map__22 (if (clojure.core/seq? map__22)
(clojure.lang.PersistentHashMap/create (clojure.core/seq map__22))
map__22)
b (clojure.core/get map__22 :b (first a))]
and it's clear that this happens in-order such that a is available for the :or destructuring
while I maintain that nothing exists in the Clojure docs to guarantee this behavior, I think given the extensive use of this code both inside and outside Clojure, I think it's highly unlikely we would alter this aspect of the implementation
I'm going to file a ticket to clarify this stuff and add tests related to :or (which do not exist)
Yeah, would be nice to document the fact that vector destructuring is sequential so that it is part of the language spec.
@alexmiller: you rock!
Yeah, at 26 it's probably just annoying : V But at least we do get a doc improvement out of that.
there is really a cluster of problems (mostly around :or) that would be nice to clear up (both in docs and in implementation)
@alexmiller: Anything that makes the semantics of this clearer is great by me!
@jaen I created a ticket for this specific issue at http://dev.clojure.org/jira/browse/CLJ-1881 and a thing that groups a bunch of other tickets at http://dev.clojure.org/display/design/Destructuring+cleanup