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

can this handle 3 arguments? #5

Open
denizyuret opened this issue Aug 15, 2017 · 2 comments
Open

can this handle 3 arguments? #5

denizyuret opened this issue Aug 15, 2017 · 2 comments

Comments

@denizyuret
Copy link

I ran into the following problem using JuliaLang/julia#22060 (comment) which I think may also apply to your code: Consider a .* (b ./ c) where a and b are regular numbers/arrays and c is the container type we want to protect from broadcast. This turns into broadcast(f, a, b, c), i.e. the special argument is in the fourth position. In both @ylxdzsw's hack and yours I think only second and third arguments are checked, but the "special" argument can occur anywhere in the argument list.

I had run into this problem before in AutoGrad and someone had suggested a workaround for defining a method signature which would apply "if at least one of the variable number of arguments is of the special type". Trying to find that hack now...

@denizyuret
Copy link
Author

OK, the trick mentioned in the first msg was this: JuliaArrays/StaticArrays.jl#136 (comment)

So we declare a variable number of arguments with type Union{SpecialType,RegularTypes...}. But in generic code like AutoGrad or the broadcasting trick RegularTypes can be anything -- number, array, KnetArray, other yet uninvented types! I guess Union{SpecialType,Any} would be meaningless...

@denizyuret
Copy link
Author

To answer my own question, the following seems to work ok (at least for regular types):

function broadcast(f, x::Union{Number,AbstractArray,Rec}...)
    bx = ntuple(i->(isa(x[i],Rec) ? Broadcasted(x[i]) : x[i]), length(x))
    f(bx...).value
end

However, by itself it matches regular broadcast operations (without Rec) because Base uses the less specific method broadcast(f, A, Bs...). To prevent this we need to declare a more specific method that has the same body as the Base method:

using Base.Broadcast: broadcast_c, containertype
broadcast(f, x::Union{Number,AbstractArray}...)=broadcast_c(f, containertype(x...), 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

1 participant