Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

comprehension syntax should respect the local variables defined in if clause #32905

Open
yatra9 opened this issue Aug 15, 2019 · 5 comments
Open

Comments

@yatra9
Copy link

yatra9 commented Aug 15, 2019

It will be nice if comprehension syntax respects the local variables defined in if clause.

For example, filter_map of Ruby 2.7 or Rust will be implemented as follows

filter_map(f, a) = (y for x in a if (y=f(x)) !== nothing)

Python 3.8 will introduce the assignment expressions which makes this possible.
https://docs.python.org/3.8/whatsnew/3.8.html
https://www.python.org/dev/peps/pep-0572/#simplifying-list-comprehensions

@JeffBezanson
Copy link
Member

This is not so natural to implement in julia, since the expression y is not lexically inside the block with y=f(x), either in the source code or in what we lower it to. But this can be written as

(y for x in a for y in (f(x),) if y !== nothing)

@tkf
Copy link
Member

tkf commented Apr 26, 2020

I think a possible lowering of

($map_body for x in a if begin
    y1 = ...
    y2 = ...
    ...
    yn = ...
    $predicate
end)

is:

itr1 = Base.Generator(a) do x
    y1 = ...
    y2 = ...
    ...
    yn = ...
    (x, y1, y2, ..., yn)
end
itr2 = Iterators.filter(itr1) do (x, y1, y2, ..., yn)
    $predicate
end
itr3 = Base.Generator(itr2) do (x, y1, y2, ..., yn)
    $map_body
end
itr3

But this breaks the current behavior:

julia> let y
           itr = (y for x in 1:2 if (y = 2x; true))
           collect(itr), y
       end
([2, 4], 4)

@non-Jedi
Copy link
Contributor

On discourse, @dhanak proposed the following syntax as an alternative:

(y for x in a let y = f(x) if y !== nothing)

Personally, I feel as if comprehension syntax is complex enough already, but I thought it worthwhile to close the loop.

@StefanKarpinski
Copy link
Member

I have an alternative proposal here of allow trailing let clauses in comprehensions, which would let you write

(y for x in a for y in (f(x),) if y !== nothing)

a little more cleanly as:

(y for x in a let y = f(x) if y !== nothing)

This seems pretty clear to me and I can't imagine what else this would mean.

@flenzen
Copy link

flenzen commented May 23, 2024

Or, adopting a syntax inspired by Haskell:

(y for x in a if y !== nothing where y = f(x))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants