-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Define machinery so that Some can be used for broadcast #35778
Conversation
Is the problem that I'm using some function that's not yet defined? I don't see what's causing the build error. |
Yeah, that's a bootstrap error. It looks like Line 680 in a4641c8
julia/base/multidimensional.jl Line 1782 in a4641c8
|
Okay, I split out those new method definitions to a new file and put them after |
Co-authored-by: Matt Bauman <mbauman@gmail.com>
base/some.jl
Outdated
@@ -6,6 +6,8 @@ | |||
A wrapper type used in `Union{Some{T}, Nothing}` to distinguish between the absence | |||
of a value ([`nothing`](@ref)) and the presence of a `nothing` value (i.e. `Some(nothing)`). | |||
|
|||
`Some` is also used in broadcasting to treat it's enclosed value as a scalar. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe more accurate to say
`Some` is also used in broadcasting to treat it's enclosed value as a scalar. | |
`Some` is also used in broadcasting to broadcast a single value to all axes. |
? Though I see that a similar wording is already used in Ref
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like that suggestion is less likely to be understood. However, maybe not everyone knows the word "scalar" either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it's fine as-is if we also explain the actual interface it implements (i.e., it is a 0-dim iterable that supports indexing).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should say its
rather than it's
in the original formulation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Yuri!
We can also replace Lines 678 to 679 in 3da2c52
|
This is interesting and promising. I can't say I love Also I think it's very reasonable to have this behavior in wrap(x) = Some(x) ? |
Thinking a bit more about this, I feel using Then the obvious question is - what specific cases other than broadcast would benefit from such a completely generic wrapper facility? Would there be utility in user-defined types being able to overload |
Accidentally deleted the wrong comment, oops. It was something along the lines of
|
There's some discussion related to this on the Zulip right now. Currently, people are thinking aloud about the possibility of improving The idea would be that [view(A, :, i, j, :, ..., :) for i in axes(A, 2), for j in axes(A, 3)] Consequently, This also opens up some possibilities for syntax sugar. For instance, there were suggestions along the lines of &(A) == eachslice(A, dims=()) and A[i, j, &, k] == eachslice(A, dims=(1, 2, 4))[i, j, k] I'm not totally sure how I feel about this, but I think it's an interesting alternative avenue that could both solve this problem, and improve our |
I don't quite follow. The point is to make a non-indexable object work in a broadcast expression by putting it in a 0-dimensional container that has the indexing semantics we need. The extension of that definition of |
I don't think this is what we want. You'd need something that is guaranteed to "warp" something. Letting users to overload
(Edit: It was a race condition 😃. @mbauman already pointed out.) What we need is the concept of 0-dimensional array but the problem is that there is no common word for this (unlike vector and matrix). Looking at Empty product - Wikipedia, the closest thing I can find is |
|
Ah, you are right. But the main point still holds, right? The input |
Yes that's true, though there's nothing stopping us from having To be clear, I don't think there's much point of using |
Well, it'd increase the complexity of the implementation, right? If you don't need to special case eachslice(A; dims) =
(view(A, f(A, dims, inds)...) for inds in Iterators.product(axes.((A,), dims)...))
function f(A, dims, indx)
fullinds = ntuple(_ -> :, ndims(A))
for (i, d) in zip(idx, dims)
fullinds = setindex(fullinds, i, d)
end
return fullinds
end |
For an |
That's the special case and complexity I'm talking about. I think a dedicated type is much simpler. |
Just to record a couple of more speculative options mentioned on Zulip (https://julialang.zulipchat.com/#narrow/stream/137791-general/topic/.60Ref.60.20in.20broadcasting)
|
I think |
Would it make sense for |
I think ultimately everything is rather arbitrary except 0-dim immutable array literal (or maybe immutable (Though TBH I'm saying this probably because I just want |
Hmm... Can we use |
I think "box" is too overloaded, e.g. for "boxed values" in languages generally. |
So the big objection to adding functionality to Triage was largely in favor of using The challenge is that FillArrays.jl is a living and thriving package, and it'll be hard to meaningfully implement the necessary subset that is still functional and capable without some major piracy. It really needs to be defined before Perhaps the best option is simply to define the minimal |
I think the “best option” might indeed be the best option: that’s the most settled part of FillArrays.jl, where some of the other design choices (broadcasting, |
This removes the dependence on inlining for performance, so we also remove `@inline`, since it can harm performance. make Some type a zero-dim broadcast container (e.g. a scalar) Replaces JuliaLang#35778 Replaces JuliaLang#39184 Fixes JuliaLang#39151 Refs JuliaLang#35675 Refs JuliaLang#43200
This removes the dependence on inlining for performance, so we also remove `@inline`, since it can harm performance. make Some type a zero-dim broadcast container (e.g. a scalar) Replaces JuliaLang#35778 Replaces JuliaLang#39184 Fixes JuliaLang#39151 Refs JuliaLang#35675 Refs JuliaLang#43200
This removes the dependence on inlining for performance, so we also remove `@inline`, since it can harm performance. make Some type a zero-dim broadcast container (e.g. a scalar) Replaces JuliaLang#35778 Replaces JuliaLang#39184 Fixes JuliaLang#39151 Refs JuliaLang#35675 Refs JuliaLang#43200
As mentioned in #35675,
Some
may be a good candidate to use basically like an immutable version ofRef
in broadcast expressions. This makesSome
a zero dimensional container that knows how to broadcast efficiently.I figure it might be better to discuss the merits of this idea here rather than clogging up that PR. Another candidate brought up in that thread is to create a new singleton type
Only
.I think if we can make
Some
work for this without breaking anything, it would be preferable to creating yet another singleton type, but I'm wary that there could be hitherto unforeseen negative consequences to adding this behaviour toSome
. Perhaps someone is relying oneltype(Some(1)) == Any
Closes #18379