Motivation
lazy_broadcast is useful in a few situations:
Improved expressibility + fusing operations
Debugging broadcast machinery
Delaying execution of a broadcast expression
Improved expressibility + fusing operations
You may have an implimentation of broadcast that involves a matrix-vector multiplication, suppose we have two operators, foo_op and bar_op
has_foo_model && @. x += 2 * foo_op(y)
has_bar_model && @. x += 3 + bar_op(y)and if foo_op and bar_op are broadcasted in an implementation-specific way, you may not be able to (easily) write this to leverage dispatch:
foo(y, ::NoFooModel) = 0
foo(y, ::HasFooModel) = 2 * foo_op(y)
bar(y, ::NoBarModel) = 0
bar(y, ::HasBarModel) = 3 + bar_op(y)
@. x += foo(y, model) + bar(y, model)since foo_op and bar_op may need to exist in the broadcasted expression. It turns out that this is pretty easy to do with LazyBroadcast:
foo(y, ::NoFooModel) = 0
foo(y, ::HasFooModel) = @lazy @. 2 * foo_op(y)
bar(y, ::NoBarModel) = 0
bar(y, ::HasBarModel) = @lazy @. 3 + bar_op(y)
@. x += foo(y, model) + bar(y, model)This form has some advantages:
- we've fused the reads of vectors 
xandy, which can result in notably better performance - we've not duplicated logic (much). We could potentially use union splitting to achieve fusion, but this can become unwieldy as the number of combinations of cases increases.
 - the new functions would be in functional form, and more easily unit-tested
 
Debugging broadcast machinery
If you overload Julia's broadcast software layer, then you may find yourself constructing broadcast objects and working with them to write unit test on your overloaded implementation of broadcast. We've often found it more convenient to construct Base.Broadcasted objects using the standard dot-syntax + LazyBroadcast. Here is an example, instead of writing:
x = [1, 2]
y = [1, 2]
a = Base.Broadcast.instantiate
(Base.Broadcast.broadcasted(+ x, y))You can write
using
LazyBroadcast: lazy_broadcast
x = [1, 2]
y = [1, 2]
a = lazy_broadcast.(x .+ y)which is typically the more common form that broadcast expressions exist in applications.
Delaying execution of a broadcast expression
Another interesting use-case of LazyBroadcast is to use it for delaying execution.
For example, we can write an expression:
using LazyBroadcast: lazy_broadcast
a = [0, 0]
b = [0, 0]
c = lazy_broadcast.(a .+ b)
nothingPerform calculations
a .= [1, 1]
b .= [1, 1]
nothingAnd then finally evaluate the expression:
Base.materialize(c)2-element Vector{Int64}:
 2
 2