<< Back to previous view

[CLJ-207] for macro does not allow :let clause in first position Created: 25/Oct/09  Updated: 26/Dec/12  Resolved: 13/Apr/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Anonymous Assignee: Unassigned
Resolution: Declined Votes: 1
Labels: None

Attachments: Text File 0001-Implement-CLJ-207-let-as-first-for-binding-form.patch    
Patch: Code and Test


I like to try and keep my level of nesting under control, and this
often involves hiding or re-structuring the let macro. The for macro
can implicitly assemble a let macro for you, but with a limitation
that the :let clause can't be first:

1:5 user=> (for [:let [z [:foo :bar]] x z] (name x))
java.lang.IllegalStateException: Can't pop empty vector (repl-1:5)
1:6 user=> (for [x [:foo :bar] :let [z (name x)]] z)
("foo" "bar")
1:7 user=>

Is this limitation intentional? Could the error message be improved?

Here's what I wanted to write:

(defn add-script-links-for-imported-javascript-libraries
       [env dom-nodes]
       (extend-dom dom-nodes [:html :head] :top
               (template-for [:let [aggregation (-> env :cascade :resource-aggregation)
                                         libraries (@aggregation :libraries)]
                                   asset-map libraries
                                   :let [path (to-asset-path env asset-map)]]
                       :script { :type "text/javascript" :src path } [ linebreak ])))

(the formatting is probably scrambled)

But I had to juggle it to this:

(defn add-script-links-for-imported-javascript-libraries
       [env dom-nodes]
       (let [aggregation (-> env :cascade :resource-aggregation)
              libraries (@aggregation :libraries)]
               (extend-dom dom-nodes [:html :head] :top
                       (template-for [asset-map libraries
                                           :let [path (to-asset-path env asset-map)]]
                               :script { :type "text/javascript" :src path } [ linebreak ]))))

Of course there are any number of ways to write this, but I prefer the
first option, as it does less of a job of obscuring what the main
point of the function is: a call to extend-dom.

Comment by Assembla Importer [ 24/Aug/10 6:56 AM ]

Converted from http://www.assembla.com/spaces/clojure/tickets/207

Comment by Tassilo Horn [ 22/Mar/12 11:21 AM ]

The attached patch implements that feature and also adds tests for it. The new tests and all other tests still pass.

The patch exploits the fact that

(for [:let [a 1, b [1 2]], c [1 2 3]] ...)

is equivalent to

(for [a [1], b [[1 2]], c [1 2 3]] ...)

and thus transforms the former binding vector to the latter.

Comment by Rich Hickey [ 13/Apr/12 9:20 AM ]

just put the for in a let please

Comment by Carl Smotricz [ 26/Dec/12 5:13 AM ]

I came here to report this as a bug.

I respect Rich's decision to disallow :let at the beginning of a (for), of course, but I feel that if the syntax is to be declared illegal then the compiler should report an error rather than explode with an exception.

Thus I suggest catching the error in the compiler and reporting it as a syntax error.

Generated at Thu Jul 28 11:35:55 CDT 2016 using JIRA 4.4#649-r158309.