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

0.5-style comprehensions #16622

Merged
merged 9 commits into from Jul 11, 2016
Merged

0.5-style comprehensions #16622

merged 9 commits into from Jul 11, 2016

Conversation

JeffBezanson
Copy link
Sponsor Member

@JeffBezanson JeffBezanson commented May 27, 2016

This could be it! I no longer see a regression in 2d comprehensions. I also implemented @stevengj 's approach, using inference only in the empty case to avoid type inference regressions.

This also makes comprehensions shape-preserving, i.e. [2x for x in rand(2,2)] gives a 2d result.

Todo:

@yuyichao
Copy link
Contributor

using inference only in the empty case to avoid type inference regressions.

So will there be another breakage in the next (or later) release cycle to return a different type (or raise an error) for empty case?

end
end
end

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:-)

@tkelman
Copy link
Contributor

tkelman commented May 27, 2016

I no longer see a regression in 2d comprehensions.

What fixed this part? As of yesterday weren't you thinking you'd have to special-case 2d to avoid a regression?

@JeffBezanson
Copy link
Sponsor Member Author

JeffBezanson commented May 27, 2016

So will there be another breakage in the next (or later) release cycle

I'm not sure. It might also be ok to give an error in the empty case. That's certainly safest, I just don't have a good handle on how important empty comprehensions are.

What fixed this part?

Not sure; I haven't run the benchmark in 2 weeks. The generated code is definitely really different now. There are many more SROA variables. (test case #15402 (comment))

@@ -977,7 +977,7 @@ X = [ i+2j for i=1:5, j=1:5 ]
@test X[2,3] == 8
@test X[4,5] == 14
@test isequal(ones(2,3) * ones(2,3)', [3. 3.; 3. 3.])
@test isequal([ [1,2] for i=1:2, : ], [1 2; 1 2])
# @test isequal([ [1,2] for i=1:2, : ], [1 2; 1 2])
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a note that this (undocumented / unused / unknown) syntax is gone now?

Copy link
Sponsor Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I was just going to bring that up for discussion. Unfortunately there's a bigger problem: this is hitting the infinite-recursion-via-codegen issue --- is there an issue for that? I was just trying to find it.

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure it has an issue number, although I couldn't find it just now either.

Copy link
Sponsor Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found it: #16201. It was closed.

@JeffBezanson
Copy link
Sponsor Member Author

What to do with the little-acknowledged n-d comprehension syntax, [ [1,2] for i=1:2, : ]? I have a sense it's never used. Easiest to remove it, but I think we can implement it as a function now if necessary.

@stevengj
Copy link
Member

stevengj commented May 28, 2016

Is [ [1,2] for i=1:2, : ] even documented? It seems awfully obscure — I'm still not 100% sure what it does even after trying it. Seems better to remove it and see whether people complain.

@mschauer
Copy link
Contributor

mschauer commented May 30, 2016

It prevents comprehensions from becoming vectors of vectors which are awkward to use in julia (compared to arrays), so the functionality is useful.

@GunnarFarneback
Copy link
Contributor

Had I known about it I would have used it a couple of times when I have resorted to hcat([some comprehension producing a vector of vectors]...) kind of solutions.

@stevengj
Copy link
Member

You can always do Vector{Int}[ [1,2] for i=1:2 ]

@GunnarFarneback
Copy link
Contributor

Maybe I was unclear. I was talking of the situation of having a comprehension producing a vector of vectors similar to

julia> [[1, 2] for i = 1:3]
3-element Array{Array{Int64,1},1}:
 [1,2]
 [1,2]
 [1,2]

but actually wanting these collected in a matrix, which can be done with

julia> hcat([[1, 2] for i = 1:3]...)'
3x2 Array{Int64,2}:
 1  2
 1  2
 1  2

Had I known about the multidimensional comprehension syntax I would instead have done

julia> [[1, 2] for i = 1:3, :]
3x2 Array{Int64,2}:
 1  2
 1  2
 1  2

for a shorter solution, without splatting a possibly arbitrarily long vector. But I agree that the syntax is obscure and I would be as happy using a function instead.

@nalimilan
Copy link
Member

I didn't know about that syntax, but I've felt the need for an equivalent of hcat(x...) which doesn't involve splatting. Is there a solution currently?

@andreasnoack
Copy link
Member

I'm not aware of any so I ended up writing my own in
https://github.com/andreasnoack/TSVD.jl/blob/f777ff95213992c7b7f8daeeb9b4ae8b242f2fc0/src/common.jl#L1-L14

On Tue, May 31, 2016 at 4:54 PM, Milan Bouchet-Valat <
notifications@github.com> wrote:

I didn't know about that syntax, but I've felt the need for an equivalent
of hcat(x...) which doesn't involve splatting. Is there a solution
currently?


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#16622 (comment),
or mute the thread
https://github.com/notifications/unsubscribe/AAe0qeTZEZwnsVITUKkCVsHPg6268GGYks5qHJ_ygaJpZM4Io7vH
.

@nalimilan
Copy link
Member

Could be good to have something like this in Base.

@mschauer
Copy link
Contributor

mschauer commented Jun 1, 2016

Basically this can be covered by collecting a Concatenate iterator mentioned in #14805 which would take a generator as argument. The form

Array(concat((1:10 for i = 1:3)))

seems pretty clear and does not create unnecessary intermediates of the ranges in this case.


'comprehension
(lambda (e)
(expand-forms (lower-comprehension #f (cadr e) (cddr e))))
(if (any (lambda (x) (eq? x ':)) (cddr e))
(error "N-d comprehension syntax has been removed"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only if some of the indices were colons, right?

Copy link
Sponsor Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what (if (any (lambda (x) (eq? x ':)) (cddr e)) checks.

Copy link
Contributor

@tkelman tkelman Jun 9, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant the error message should be more specific (I can at least read some scheme)

@JeffBezanson
Copy link
Sponsor Member Author

JeffBezanson commented Jun 9, 2016

I believe the only remaining failure here is due to #16201. A bit odd, since the code that hits it (quadgk) doesn't seem to involve comprehensions, but somehow there's an interaction. The issue is fixed by #16692.

@JeffBezanson
Copy link
Sponsor Member Author

Passing CI! Get excited!

for a in drop(argtypes,1)
if !(isa(a,Const) || (isType(a) && !has_typevars(a.parameters[1])))
return false
end
end

if f === return_type
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just adding a breadcrumb here that I'm still not sure if this is sound. Also, with the way this is currently being used, I expect it will tend to obscure any type errors, meaning this is probably very poorly tested right now.

JeffBezanson added a commit that referenced this pull request Jul 1, 2016
some generally-applicable changes from #16622
@davidagold
Copy link
Contributor

@JeffBezanson on this branch, with X a NullableArray{Float64, 1}, [ f(x) for x in X ] appears to get parsed (is that the right word choice?) into collect(Generator(f, X)), which ends up returning an Array. I want to overload collect so that the aforementioned comprehension returns a NullableArray. Is the ability to do that part of your plan for this PR, or is it not really recommended?

@yuyichao
Copy link
Contributor

yuyichao commented Jul 4, 2016

A comprehension always returns an Array (either on this branch or master). On 0.5, you can use something like NullableArray(f(x) for x in X) to do what you want.

@davidagold
Copy link
Contributor

That makes sense. Thanks, sorry for the noise.

@quinnj
Copy link
Member

quinnj commented Jul 7, 2016

Looks like Appveyor was a 32-bit failure related to some kind of GitError. Needs a rebase.

JeffBezanson and others added 9 commits July 8, 2016 12:09
this removes `static_typeof` and `type_goto`

fixes #7258
…ents

this removes an extra layer of wrapping with `IteratorND`

add some inline declarations for `Generator` iteration

remove unused `IteratorND` type
this implements the "Steve Johnson compromise":
- non-empty comprehensions don't depend on inference at all
- in the empty case, we use either Union{} or the inferred type
- therefore there is no regression in type precision in cases where
  we can infer a leaf type

add Core.Inference.return_type

This computes a return type (at compile time if possible) in a way that handles
recursive dependencies in inference.
this also uses the new lowering for typed comprehensions, allowing all
comprehensions on unknown-length iterables (fixes #1457)
@JeffBezanson
Copy link
Sponsor Member Author

I've looked at some of the regressions identified by nanosoldier. One issue is #17342.

Another issue is that the comprehension body is not always inlined. If we want, that can (probably) be easily fixed by inserting an :inline node in the function the frontend generates.

Since comprehension expressions tend to be small, it's surprising that they might not be inlined. #17340 has an example of some unexpectedly-large IR from small code, when indexing a LinSpace.

@JeffBezanson
Copy link
Sponsor Member Author

I think the causes of the (few) regressions here are well-understood and we'll be able to address them in the RC period, so I'll merge this now.

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

Successfully merging this pull request may close these issues.

None yet