Clojure

for-as

Details

• Type: Enhancement
• Status: Closed
• Priority: Minor
• Resolution: Declined
• Affects Version/s: Release 1.5
• Fix Version/s: None
• Component/s: None
• Labels:
None

Description

A common pattern in programming is building up some data structure step by step:

In Python:

```x = {0: 1}
for item in stuff:
x[item] = item * x.get(item - 1, 0)```

etc.

In an imperative for loop this is easy since we have easy access to the "current" data structure being built up.

I propose the addition of a function for-as similar to as-> except the value of the last loop iteration is bound to the name.

So we can write the above as:

```(last (for-as [x {0 1}]
[item stuff]
(assoc x item (* item (get x (- item 1) 0)))))```

An (un-optimized) implementation might be something like:

```(defmacro reduce-for [[res init] for-seq-exprs body-expr]
`(reduce #(%2 %1) ~init
(for ~for-seq-exprs
(fn [~res]
~body-expr))))```

Note: reduce-for does not return a seq, instead it returns the result of the last loop body iteration.

Activity

Field Original Value New Value
Description A common pattern in programming is building up some data structure step by step:

In Python:

[code]
x = {0: 1}
for item in stuff:
x[item] = item * x.get(item - 1, 0)
[/code]
etc.

In an imperative for loop this is easy since we have easy access to the "current" data structure being built up.

I propose the addition of a function for-as similar to as-> except the value of the last loop iteration is bound to the name.

So we can write the above as:

[code]
(last (for-as [x {0 1}]
[item stuff]
(assoc x item (* item (get x (- item 1) 0)))))
[/code]

An (un-optimized) implementation might be something like:

[code]
(defmacro reduce-for [[res init] for-seq-exprs body-expr]
`(reduce #(%2 %1) ~init
(for ~for-seq-exprs
(fn [~res]
~body-expr))))
[/code]

Note: reduce-for does not return a seq, instead it returns the result of the last loop body iteration.
A common pattern in programming is building up some data structure step by step:

In Python:

{code}
x = {0: 1}
for item in stuff:
x[item] = item * x.get(item - 1, 0)
{code}
etc.

In an imperative for loop this is easy since we have easy access to the "current" data structure being built up.

I propose the addition of a function for-as similar to as-> except the value of the last loop iteration is bound to the name.

So we can write the above as:

{code}
(last (for-as [x {0 1}]
[item stuff]
(assoc x item (* item (get x (- item 1) 0)))))
{code}

An (un-optimized) implementation might be something like:

{code}
(defmacro reduce-for [[res init] for-seq-exprs body-expr]
`(reduce #(%2 %1) ~init
(for ~for-seq-exprs
(fn [~res]
~body-expr))))
{code}

Note: reduce-for does not return a seq, instead it returns the result of the last loop body iteration.
 Comment [ (Fixed formatting) {code} x = {0: 1} for item in stuff:     x[item] = item * x.get(item - 1, 0) {code} {code} (last (for-as [x {0 1}]         [item stuff]   (assoc x item (* item (get x (- item 1) 0))))) {code} {code} (defmacro reduce-for [[res init] for-seq-exprs body-expr]   `(reduce #(%2 %1) ~init     (for ~for-seq-exprs       (fn [~res]         ~body-expr)))) {code} (Someone please fix the formatting in above and delete this comment.) ]
Hide
Kevin Downey added a comment -

this is not super clear to me, but it seems like a request for a `for` like macro for reduce.

```(reduce (fn [x item] (assoc x item (* item (get x (- item 1) 0)))) {0 1} stuff)
```
Show
Kevin Downey added a comment - this is not super clear to me, but it seems like a request for a `for` like macro for reduce.
```(reduce (fn [x item] (assoc x item (* item (get x (- item 1) 0)))) {0 1} stuff)
```
Hide
Alex Miller added a comment -

This case seems adequately handled by reduce or loop/recur. I don't think the proposal is compelling enough to consider adding to core.

Show
Alex Miller added a comment - This case seems adequately handled by reduce or loop/recur. I don't think the proposal is compelling enough to consider adding to core.