Generally, yes - writing `geman_mcclure.(d2, s)`

with `d2`

a `Vector`

and `s`

a scalar (or even a vector of the same length as `d2`

) is equivalent to

```
out_arr = similar(d2)
for i in eachindex(d2)
out_arr[i] = geman_mcclure(d2[i], s) # geman_mcclure(d2[i], s[i]) if `s` is broadcastable
end
out_arr
```

which is the same as your explicitly vectorized `geman_mcclure!`

function, modulo the additional allocation, which can be done ahead of time manually. If done ahead of time, you can (just with `geman_mcclure`

) then write `w .= geman_mcclure.(d2, s)`

, which is already equivalent to the loop above, except that `out_arr`

does not have to be allocated, because it already exists.

This is a common pattern - instead of writing explicitly vectorized versions of scalar functions like `geman_mcclure!`

, we usually only have the scalar version and broadcast/inplace-broadcast/map as necessary, allowing loop fusion to take place.

In comparison, `geman_mcclure!`

does not allow loop fusion with broadcast outside of itself. That is, this example will not fuse loops:

```
z .= a .+ geman_mcclure!(w, ds2, s)
```

(there will first be the inner loop inside of `geman_mcclure!`

, then the outer one over `z`

and `a`

) whereas this will:

```
z .= a .+ geman_mcclure.(ds2, s)
```

which is in fact equivalent to

```
for idx in eachindex(z, a, ds2)
z[idx] = a[idx] + geman_mcclure(ds2[idx], s)
end
```

This is also what I mean with “broadcasting inline” - simply using the scalar version in a broadcast is more flexible than having `geman_mcclure!`

, which is required to complete before the outer broadcast can be calculated. The general rule of thumb for when I use explicitly modifying functions is either when the operation is not a scalar operation (i.e., more than a single index is required to perform the calculation, forcing you to write a loop either way) or when there’s a truly persistent modification of a datastructure as a sideeffect happens, e.g. with `get!`

:

```
help?> get!
search: get! mergewith! get getpid getkey getfield getindex getglobal
get!(collection, key, default)
Return the value stored for the given key, or if no mapping for the
key is present, store key => default, and return default.
Examples
≡≡≡≡≡≡≡≡≡≡
julia> d = Dict("a"=>1, "b"=>2, "c"=>3);
julia> get!(d, "a", 5)
1
julia> get!(d, "d", 4)
4
julia> d
Dict{String, Int64} with 4 entries:
"c" => 3
"b" => 2
"a" => 1
"d" => 4
```