Stream: helpdesk (published)

Topic: ✔ `ifelse` with functions


view this post on Zulip Chad Scherrer (Apr 13 2022 at 16:11):

I think I'm missing something obvious. This works fine:

julia> function f(a,b)
       a || return ifelse(b, "ft", "ff")
       b || return "tf"
       return "tt"
       end
f

julia> function check(fun)
       for a in (true, false)
           for b in (true, false)
               println((a,b) => fun(a,b))
           end
       end
       end
check

julia> check(f)
(true, true) => "tt"
(true, false) => "tf"
(false, true) => "ft"
(false, false) => "ff"

But I'd expect this to also work:

julia> function g(a,b)
       ifelse(a, () -> nothing, () -> return ifelse(b, "ft", "ff"))()
       ifelse(b, () -> nothing, () -> return "tf")()
       return "tt"
       end
g

julia> check(g)
(true, true) => "tt"
(true, false) => "tt"
(false, true) => "tt"
(false, false) => "tt"

The idea for g is to have a way to make ifelse lazy, so it could work with StaticBools as well as Bools. What am I missing?

view this post on Zulip Chad Scherrer (Apr 13 2022 at 16:19):

As a side note, I'm moving away from using StaticBool as an optimization and toward only using this when I need it for dispatch. But I do need it temporarily to for short-term backward compatibility

view this post on Zulip Richard Reeve (Apr 13 2022 at 16:21):

Surely the return x statements are inside the lambda functions you have created, so the first two lines don't return from the main g() function?

view this post on Zulip Chad Scherrer (Apr 13 2022 at 16:23):

...Are they not? It looks to me like they're inside the lambdas. Anyway, I'm having the opposite problem - g always returns tt, which must mean both ifelse lines reduce to nothing

view this post on Zulip Chad Scherrer (Apr 13 2022 at 16:29):

If a is false, I'd think

ifelse(a, () -> nothing, () -> return ifelse(b, "ft", "ff")) == () -> return ifelse(b, "ft", "ff")

So applying this (the () at the end) should....

Oh wait, I think I get it, it's interpreting the return as part of the anonymous function, instead of as part of g

view this post on Zulip Chad Scherrer (Apr 13 2022 at 16:30):

That threw me, since I never use return to just return a value from an anonymous function

view this post on Zulip Notification Bot (Apr 13 2022 at 16:31):

Chad Scherrer has marked this topic as resolved.

view this post on Zulip Mason Protter (Apr 13 2022 at 17:02):

The secret is to just never use return. It’s just a less useful goto.

view this post on Zulip Chad Scherrer (Apr 13 2022 at 17:15):

That's worked well for me in some cases, but here I want to short-circuit most of the code. Would you use a @goto for this?

view this post on Zulip Mason Protter (Apr 13 2022 at 17:24):

I’d just not use ifelse at all and instead write if x == true and then make it so that True() == true

view this post on Zulip Chad Scherrer (Apr 13 2022 at 17:25):

Nice, I hadn't thought of that

view this post on Zulip Chad Scherrer (Apr 13 2022 at 20:34):

julia> Static.True() == true
true

:thumbs_up:

view this post on Zulip Mason Protter (Apr 13 2022 at 20:43):

Another option would be something like

istrue(::True) = true
istrue(::False) = false
istrue(b::Bool) = b
if istrue(a)
    # ...
end

if you prefer how that looks

view this post on Zulip Mason Protter (Apr 13 2022 at 20:44):

You can also make anything you feel like 'truthy' in this way. E.g.

istrue(x::Integer) = x % Bool
istrue( ::Missing) = false

Last updated: Oct 02 2023 at 04:34 UTC