# Like a list comprehension but with several lines

**URL:** <https://discourse.julialang.org/t/like-a-list-comprehension-but-with-several-lines/95365>\
**Category:** General Usage\
**Created:** [March 1, 2023, 3:53am UTC](https://discourse.julialang.org/t/like-a-list-comprehension-but-with-several-lines/95365 "2023-03-01T03:53:37Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Gus\_Hart](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gus_hart/32/6987_2.png) [@Gus\_Hart](https://discourse.julialang.org/u/Gus_Hart)\
**Post date:** [March 1, 2023, 3:53am UTC](https://discourse.julialang.org/t/like-a-list-comprehension-but-with-several-lines/95365/1 "2023-03-01T03:53:37Z")

</div>

It frequently happens that I have a loop with ~10 lines. I’d like to return some value at the end of each iteration, collect that in an array, and then plot it. I can pre-allocate some array, or append to an array as the loop goes…but I’d like to do something like a list comprehension that just returns an array, without me worrying about its size or bothering to append. When the operation is something simple, and not 10 lines of code, I usually just do a list comprehension. How does one do a list comprehension when the thing you want to do to each iterate is 10 lines of code?

It seem like a `do` block might work for this but I’ve been messing around without success. Here’s a highly contrived MWE.

```julia
using Random
its = 10:2:30
out = []
for i in its
    t = randperm(i)
    s = maximum(t)
    u = rand(s)[1]
    append!(out,u)
end
plot(out)

```

I’d like to do this without using the ‘temporary’ `out` array

Something like:

```julia
its = collect(10:2:30) 
?? do i
    t = randperm(i)
    s = maximum(t)
    u = rand(s)[1]
end |> plot

```

---

<div class="post-metadata">

**Author:** ![Gus\_Hart](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gus_hart/32/6987_2.png) [@Gus\_Hart](https://discourse.julialang.org/u/Gus_Hart)\
**Post date:** [March 1, 2023, 4:19am UTC](https://discourse.julialang.org/t/like-a-list-comprehension-but-with-several-lines/95365/2 "2023-03-01T04:19:04Z")

</div>

This seems to work. Would love feedback…

```julia
using Random
its = 10:2:30
map(its) do i
    t = randperm(i)
    s = maximum(t)
    u = rand(s)[1]
end |> plot

```

---

<div class="post-metadata">

**Author:** ![JackDevine](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jackdevine/32/1048_2.png) [@JackDevine](https://discourse.julialang.org/u/JackDevine)\
**Post date:** [March 1, 2023, 5:36am UTC](https://discourse.julialang.org/t/like-a-list-comprehension-but-with-several-lines/95365/3 "2023-03-01T05:36:17Z")

</div>

I like that idea – I will have to use it in my own code!

Have you seen [Chain · Julia Packages](https://juliapackages.com/p/chain)?

You could do this:

```julia
using Random
using Chain
its = 10:2:30
@chain its begin
    randperm.(_)
    maximum.(_)
    rand.(_)[1]
end

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [March 1, 2023, 6:03am UTC](https://discourse.julialang.org/t/like-a-list-comprehension-but-with-several-lines/95365/4 "2023-03-01T06:03:15Z")

</div>

> [@Gus\_Hart](#):
>
> ```julia
> t = randperm(i)
> s = maximum(t)
> u = rand(s)[1]
> 
> ```

This code is pretty confusing. As far as I can tell, it’s equivalent to just `rand()`.

---

<div class="post-metadata">

**Author:** ![HanD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hand/32/213908_2.png) [@HanD](https://discourse.julialang.org/u/HanD)\
**Post date:** [March 1, 2023, 7:46am UTC](https://discourse.julialang.org/t/like-a-list-comprehension-but-with-several-lines/95365/5 "2023-03-01T07:46:25Z")

</div>

Hello Gus!

I was pondering a similar problem when I posted [this suggestion](https://discourse.julialang.org/t/proposal-to-extend-the-syntax-of-list-comprehensions-with-a-let-clause). Based on [this answer](https://discourse.julialang.org/t/proposal-to-extend-the-syntax-of-list-comprehensions-with-a-let-clause/87256/9), your contrived loop can be rewritten in list comprehension syntax as follows:

```plaintext
out = [rand(s)[1]
       for i in 10:2:30
       for t = Ref(randperm(i))
       for s = Ref(maximum(t))]

```

Whether you prefer this, the for loop or the map syntax is a matter of taste.

HTH.

---

<div class="post-metadata">

**Author:** ![rfourquet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rfourquet/32/3610_2.png) [@rfourquet](https://discourse.julialang.org/u/rfourquet)\
**Post date:** [March 1, 2023, 7:58am UTC](https://discourse.julialang.org/t/like-a-list-comprehension-but-with-several-lines/95365/6 "2023-03-01T07:58:50Z")

</div>

> [@Gus\_Hart](#):
>
> ```julia
> map(its) do i
> t = randperm(i)
> s = maximum(t)
> u = rand(s)[1]
> end 
> 
> ```

Similar to the answer above, you can directly translate this to a comprehension (but no need to introduce artificial iterations, a `begin` or `let` block will let you pack multiple lines):

```julia
[ let
     t = randperm(i)
     s = maximum(t)
     u = rand(s)[1]
  end for i in its ] 

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [March 1, 2023, 8:12am UTC](https://discourse.julialang.org/t/like-a-list-comprehension-but-with-several-lines/95365/7 "2023-03-01T08:12:30Z")

</div>

Here’s one option, similar to a let block:

```julia
[(t = randperm(i);
  s = maximum(t);
  rand(s)[1]) for i in its]

```

Or, on one line:

```julia
[(t = randperm(i); s = maximum(t); rand(s)[1]) for i in its]

```

And have you considered broadcasting?

```julia
(first ∘ rand ∘ maximum ∘ randperm).(its)
its .|> randperm .|> maximum .|> rand .|> first
(i -> (t=randperm(i); s=maximum(t); rand(s)[1])).(its)

```

---

<div class="post-metadata">

**Author:** ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)\
**Post date:** [March 1, 2023, 6:54pm UTC](https://discourse.julialang.org/t/like-a-list-comprehension-but-with-several-lines/95365/8 "2023-03-01T18:54:42Z")

</div>

> [@DNF](#):
>
> Here’s one option, similar to a let block:

As everything is an expression in Julia, you can just use a `let` block:

```julia
[let
     t = randperm(i)
     s = maximum(t)
     rand(s)[1]
 end
 for i in 10:2:30]

```

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [March 2, 2023, 3:35am UTC](https://discourse.julialang.org/t/like-a-list-comprehension-but-with-several-lines/95365/9 "2023-03-02T03:35:21Z")

</div>

I prefer placing locals on the same line:

```julia
[let t=randperm(i), s=maximum(t)
     rand(s)[1]
 end 
 for i = 10:2:30]

```

this way, when this comprehension is in local scope, it doesn’t inadvertently capture and overwrite any locals named `t` or `s` in its parent scope.
