# Lazy broadcast Nullable

**URL:** <https://discourse.julialang.org/t/lazy-broadcast-nullable/4596>\
**Category:** General Usage\
**Tags:** question\
**Created:** [July 2, 2017, 1:07pm UTC](https://discourse.julialang.org/t/lazy-broadcast-nullable/4596 "2017-07-02T13:07:25Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 2, 2017, 1:07pm UTC](https://discourse.julialang.org/t/lazy-broadcast-nullable/4596/1 "2017-07-02T13:07:25Z")

</div>

I could express a certain class computation with variations on composing small but occasionally expensive functions. Sometimes the functions produce `Nullables`, in which case I want computation to short-circuit and not compute the other expensive parts.

MWE:

```julia
f(a) = (println("fcall was expensive"); a.+1)
g(b) = (println("gcall even more expensive"); b.+2)
h(x,y) = x.+y

h(f(1),g(2)) # paid the price
h(f(Nullable{Int}()),g(2)) # this should short circuit, no gcall
h(f(9),g(Nullable{Int}())) # it would be nice if this did, too, ie no fcall

```

I could express the logic with a bunch of conditionals, but if there is an idiomatic way, it would make my code very compact and organized and I would love that. Suggestions are appreciated.

---

<div class="post-metadata">

**Author:** ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)\
**Post date:** [July 2, 2017, 3:50pm UTC](https://discourse.julialang.org/t/lazy-broadcast-nullable/4596/2 "2017-07-02T15:50:46Z")

</div>

In Julia 0.6, `h.(f.(Nullable{Int}()), g(2))` will directly return `Nullable()` without evaluating `f` nor `h`.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 2, 2017, 3:54pm UTC](https://discourse.julialang.org/t/lazy-broadcast-nullable/4596/3 "2017-07-02T15:54:10Z")

</div>

Magic! But then doesn’t this violate function call semantics? Suppose `f` and `g` had side effects.

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [July 2, 2017, 4:08pm UTC](https://discourse.julialang.org/t/lazy-broadcast-nullable/4596/4 "2017-07-02T16:08:41Z")

</div>

I think that broadcast makes no assertions about how many times your function gets called (this came up in the discussion of broadcast over sparse arrays where you would want to check if the function preserves sparsity by calling it once). `g(2)` will always be called though (as I understand it).

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 2, 2017, 4:15pm UTC](https://discourse.julialang.org/t/lazy-broadcast-nullable/4596/5 "2017-07-02T16:15:59Z")

</div>

You are right: updated MWE

```julia
f(a) = (println("fcall was expensive"); a+1)
g(b) = (println("gcall even more expensive"); b+2)
h(x,y) = x+y

```

then

```julia
julia> h(f(1),g(2)) # paid the price
fcall was expensive
gcall even more expensive
6

julia> h.(f.(Nullable{Int}()),g(2)) # just gcall
gcall even more expensive
Nullable{Int64}()

julia> h.(f.(Nullable{Int}()),g.(2)) # no fcall or gcall
Nullable{Int64}()

julia> h.(f.(9),g.(Nullable{Int}())) # no fcall or gcall
Nullable{Int64}()

```

And I can accept that `broadcast` may not have standard evaluation semantics, but need to wrap my head around that. Not that I was intending to program with side effects, just an academic question.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 2, 2017, 7:03pm UTC](https://discourse.julialang.org/t/lazy-broadcast-nullable/4596/6 "2017-07-02T19:03:41Z")

</div>

A related question: is there a shortcut version of

```julia
Nullable(f(1), false)

```

ie one that would not evaluate the first argument when the second is `false`?

---

<div class="post-metadata">

**Author:** ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)\
**Post date:** [July 2, 2017, 7:53pm UTC](https://discourse.julialang.org/t/lazy-broadcast-nullable/4596/7 "2017-07-02T19:53:20Z")

</div>

No, you need to use `if` manually. There’s also the difficulty that you need to know the type that `f(1)` would have had if it had been called (if you want to ensure type stability).

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 3, 2017, 8:32am UTC](https://discourse.julialang.org/t/lazy-broadcast-nullable/4596/8 "2017-07-03T08:32:44Z")

</div>

I think I figured out a way to avoid specifying the type, inspired by your original solution:

```julia
f(a) = (println("fcall was expensive"); a+1)
pass(x, flag) = x
pass.(f.(9), Nullable{Bool}()) # f not called
pass.(f.(9), Nullable(true)) # f called

```

Just instead of `true`, use a flag, eg

```julia
maybef(flag) = pass.(f.(9), Nullable(flag, flag))

```

which looks type-stable. The logic above is not elegant, but if I design all of my functions this way (ie return Nullable’s), I can avoid it entirely.

Now I wonder if there is a simpler way, or at least something from `Base` I could use in place of `pass`.

---

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [July 4, 2017, 9:36am UTC](https://discourse.julialang.org/t/lazy-broadcast-nullable/4596/9 "2017-07-04T09:36:22Z")

</div>

If your `Nullable` either `isnull` or contains `true`, then there’s no point in storing a `Bool` in it.

```julia
const true_flag = Nullable(nothing)
const false_flag = Nullable{Void}()
@assert typeof(false_flag) == typeof(true_flag)
bool2flag(b::Bool) = b ? true_flag : false_flag

f(a) = (println("fcall was expensive"); a+1)
pass(x, flag) = x
pass.(f.(9), false_flag) # f not called
pass.(f.(9), true_flag) # f called
maybef(b::Bool) = pass.(f.(9), bool2flag(b)) # f called iff b

```

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 4, 2017, 9:40am UTC](https://discourse.julialang.org/t/lazy-broadcast-nullable/4596/10 "2017-07-04T09:40:00Z")

</div>

It is basically costless, and your code is much more complicated.

---

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [July 4, 2017, 9:49am UTC](https://discourse.julialang.org/t/lazy-broadcast-nullable/4596/11 "2017-07-04T09:49:38Z")

</div>

> [@Tamas\_Papp](#):
>
> and your code is much more complicated

No, it is identical in complexity to your code. The extra lines are strictly for readability. The below does the same thing.

```julia
f(a) = (println("fcall was expensive"); a+1)
pass(x, flag) = x
pass.(f.(9), Nullable{Void}()) # f not called
pass.(f.(9), Nullable(nothing)) # f called
maybef(flag::Bool) = pass.(f.(9), Nullable(nothing, flag)) # f called iff flag

```
