Details
-
Type:
Defect
-
Status:
Open
-
Priority:
Minor
-
Resolution: Unresolved
-
Affects Version/s: Release 1.5
-
Fix Version/s: Release 1.6
-
Component/s: None
-
Labels:None
-
Patch:Code and Test
-
Approval:Screened
Description
My intuitive understanding of the classic threading macros is that the meaning of forms like (-> a b c) can be understood syntactically independent of the meaning of the symbols involved or the fact that the two threading macros are defined recursively. However the recursive definition breaks that expectation. After
(macroexpand-1 (macroexpand-1 '(-> a b c))) => (c (-> a b))
c is now in control if it is a macro, and is now seeing the argument (-> a b) rather than (b a) as would be the case if we had written (c (b a)) originally.
Admittedly I do not know of a realistic example where this is an important distinction (I noticed this when playing with a rather perverse use of ->> with macros from korma), but at the very least it means that the behavior of the threading macros isn't quite as easy to accurately explain as I thought it was.
Attachments
Activity
| Field | Original Value | New Value |
|---|---|---|
| Patch | Code and Test [ 10002 ] | |
| Attachment | 0001-CLJ-1121-Reimplement-and-without-recursion.patch [ 11751 ] |
| Description |
My intuitive understanding of the classic threading macros is that the meaning of e.g. {{(-> a b c)}} can be understood syntactically independent of the meaning of the symbols involved or the fact that {{->}} and {{->>}} are defined recursively. However the recursive definition breaks that expectation. Two expansions on {{(-> a b c)}} yields {{(c (-> a b))}}, where {{c}} is now in control if it is a macro, and is now seeing the argument {{(-> a b)}} rather than {{(b a)}} as would be the case if we had written {{(c (b a))}} originally.
Admittedly I do not know of a realistic example (I noticed this when playing with a rather perverse use of {{->>}} with macros from korma), but at the very least it means that the behavior of the threading macros isn't quite as easy to accurately explain as I thought it was. |
My intuitive understanding of the classic threading macros is that the meaning of e.g. {{(-> a b c)}} can be understood syntactically independent of the meaning of the symbols involved or the fact that {{->}} and {{->>}} are defined recursively. However the recursive definition breaks that expectation. Two expansions on {{(-> a b c)}} yields {{(c (-> a b))}}, where {{c}} is now in control if it is a macro, and is now seeing the argument {{(-> a b)}} rather than {{(b a)}} as would be the case if we had written {{(c (b a))}} originally.
Admittedly I do not know of a realistic example where this is an important distinction (I noticed this when playing with a rather perverse use of {{->>}} with macros from korma), but at the very least it means that the behavior of the threading macros isn't quite as easy to accurately explain as I thought it was. |
| Description |
My intuitive understanding of the classic threading macros is that the meaning of e.g. {{(-> a b c)}} can be understood syntactically independent of the meaning of the symbols involved or the fact that {{->}} and {{->>}} are defined recursively. However the recursive definition breaks that expectation. Two expansions on {{(-> a b c)}} yields {{(c (-> a b))}}, where {{c}} is now in control if it is a macro, and is now seeing the argument {{(-> a b)}} rather than {{(b a)}} as would be the case if we had written {{(c (b a))}} originally.
Admittedly I do not know of a realistic example where this is an important distinction (I noticed this when playing with a rather perverse use of {{->>}} with macros from korma), but at the very least it means that the behavior of the threading macros isn't quite as easy to accurately explain as I thought it was. |
My intuitive understanding of the classic threading macros is that the meaning of forms like {{(-> a b c)}} can be understood syntactically independent of the meaning of the symbols involved or the fact that the two threading macros are defined recursively. However the recursive definition breaks that expectation. After
{noformat} (macroexpand-1 (macroexpand-1 '(-> a b c))) => (c (-> a b)) {noformat} {{c}} is now in control if it is a macro, and is now seeing the argument {{(-> a b)}} rather than {{(b a)}} as would be the case if we had written {{(c (b a))}} originally. Admittedly I do not know of a realistic example where this is an important distinction (I noticed this when playing with a rather perverse use of {{->>}} with macros from korma), but at the very least it means that the behavior of the threading macros isn't quite as easy to accurately explain as I thought it was. |
| Attachment | CLJ-1121-v002.patch [ 11780 ] |
| Approval | Triaged [ 10120 ] |
| Approval | Triaged [ 10120 ] | Vetted [ 10003 ] |
| Fix Version/s | Release 1.6 [ 10157 ] |
| Assignee | Stuart Halloway [ stu ] |
| Approval | Vetted [ 10003 ] | Screened [ 10004 ] |
I just realized that my patch also implements CLJ-1086.