# How to broadcast over only certain function arguments?

I have a function that takes fixed input arrays and variable scalars to produce a scalar return value. I would like to use the broadcast capability of Julia to turn the variable scalars into arrays, and have it return an array of the same size. Is there a straightforward way to get the broadcast syntax `f.()` to interpret the input arguments correctly (not attempting to broadcast over the fixed arrays)? Or is there some other clever way using `map` or `broadcast`?

For now, I will initialize the return array and just use a `for` loop.

2 Likes

You can turn one of the arguments into a tuple to consider it as a scalar:

For example (if I understood your question correctly):

``````f(x,y) = sum(x) + y
f([1,2,3], 4) #-> 10
f([1,2,3], 5) #-> 11

f.([1,2,3], [4,5])    # -> error

f.(([1,2,3],), [4,5]) # -> [10, 11]
# this works because ([1,2,3],) is now considered
# to be scalar and is broadcasted
``````

Note how in the second case, the array argument `[1,2,3]` has been turned into a 1-element tuple containing the actual array argument: `([1,2,3],)`

It would also have been possible to use `Ref([1,2,3])` to achieve the same effect:

``````f.(Ref([1,2,3]), [4,5]) #-> [10, 11]
``````
6 Likes

Also see this (ongoing) discussion:

1 Like

Wrapping an argument in `Ref(x)` also works and is a common idiom for this.

9 Likes

If you want to override the broadcasting behaviour for a particular function, it’s possible by adding a new method to the broadcasted function. However, I’m not sure it’s a particularly advisable thing to do since your function will behave differently to most other functions.

``````julia> _f(x,y) = sum(x) + y
_f (generic function with 1 method)

julia> f(x, y) = _f(x,y)
f (generic function with 1 method)

julia> f.([1,2,3], [4,5])
2-element Array{Int64,1}:
10
11
``````
2 Likes

The tuple-wrapping trick seems to work with Julia v0.7. I didn’t have success with the `Ref()` trick - will need to experiment further.

Thanks!

It is not a “trick”, but part of the semantics of broadcasting. If it does not work, that is a bug, so please provide a self-contained MWE that demonstrates this.

This doesn’t seem to work, as of Julia 1.7. Has it been replaced/deprecated?

It should work. Can you provide a minimal example?

``````f(x,y)=2*x+3*y
``````

then

``````julia> f.(([1,2]),[3,4,5])
ERROR: DimensionMismatch("arrays could not be broadcast to a common size; got a dimension with lengths 2 and 3")
Stacktrace:
[1] _bcs1
[2] _bcs
[4] combine_axes
[5] instantiate
[7] top-level scope
@ REPL[32]:1
[8] top-level scope
@ ~/.julia/packages/CUDA/0IDh2/src/initialization.jl:52
``````

Hi Sorry - I tried Ref() again and it worked
[sorry - I thought I had tried it before, but something must have been different]

Thanks

Ah, OK.

It’s Ref(1,2) that doesn’t work here, which had confused me.

@compleat - You missed a trailing comma in your first argument above:

``````julia> ([1,2])
2-element Vector{Int64}:
1
2

julia> ([1,2],)
([1, 2],)

julia> typeof(ans)
Tuple{Vector{Int64}}
``````

Surrounding an item with parentheses doesn’t make it a tuple.

1 Like

Hi, thanks so much. [How did I miss that? I never knew]