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

Inconsistent dot vectorization? #30450

Closed
jarlela opened this issue Dec 19, 2018 · 2 comments
Closed

Inconsistent dot vectorization? #30450

jarlela opened this issue Dec 19, 2018 · 2 comments
Labels
broadcast Applying a function over a collection

Comments

@jarlela
Copy link

jarlela commented Dec 19, 2018

I see the following behaviour:

julia> x = [1,2];
julia> println.(getindex.(Ref(x),1:lastindex(x)));
1
2
julia> println.(getindex.(Ref(x),:));
[1, 2]

Is this diffence in behaviour intentional?

There seems to be no difference in the return value from getindex.:

julia> getindex.(Ref(x), 1:lastindex(x))
2-element Array{Int64,1}:
 1
 2
julia> getindex.(Ref(x),:)
2-element Array{Int64,1}:
 1
 2

My versioninfo:

Julia Version 1.0.3
Commit 099e826241 (2018-12-18 01:34 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Core(TM) i7-3920XM CPU @ 2.90GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-6.0.0 (ORCJIT, ivybridge)
@mbauman
Copy link
Member

mbauman commented Dec 19, 2018

Thanks for the report. To be honest, this behavior surprises me quite a bit, too, but for different reasons than what you expected. I expected an error.

In short, : is, by itself, just a single placeholder value. It doesn't get expanded to the collection-of-all-indices-in-that-dimension until it gets inside the getindex function call. So what broadcast sees is simply the single value :. That single value gets broadcasted over all combinations of other arguments, just like the number 1 would.

Now, I actually expected broadcasting over : to be an error as it's not an iterable structure, which would have made this mistake a little clearer. But it turns out that : is also itself a Function (to support the infix range syntax 1:10), and we special-case functions to behave as scalar values in broadcast to support easily broadcasting over higher-order functions.

This is all further confused by the fact that getindex does its own form of non-scalar evaluation that is similar to, but not exactly the same as broadcast. That means that getindex.(Ref(X), :) is the same as getindex(X, :) (they both return arrays). But this is then further confused because broadcast has a special rule that if you broadcast over zero-dimensional arguments (as in getindex.(Ref(X), :) it returns an unwrapped value (an array), but println.(getindex.(Ref(X), :)) will fuse into a single loop over the arguments and thus just print the array (instead of its elements, which you might expect because of how it gets unwrapped).

In other words, this is behaving quite cromulently. But it's a horrible combination of quirks.

@mbauman mbauman added the broadcast Applying a function over a collection label Dec 19, 2018
@mbauman
Copy link
Member

mbauman commented Dec 19, 2018

I think we can close this in favor of:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
broadcast Applying a function over a collection
Projects
None yet
Development

No branches or pull requests

2 participants