Inorequals

A fairly common pattern for me is to have a part of a function depend on what amounts to flags:

using Plots

function f(x; extras=[])
    pl = plot(x)
    if :v in extras
        vline!(pl, 0)
    end
    if :h in extras
       hline!(pl, 0)
    end
    return pl
end

I often find myself wanting something akin to

if extras === :h || extras isa AbstractArray && :h in extras

to allow scalar arguments to be passed as well as a vector. Is there a builtin workaround to make this less cumbersome? Or would you rewrite this? (perhaps extras = extras isa AbstractArray ? extras : [extras]) In my specific case, the most common usage would be to supply just one symbol, so it feels silly to enforce array-ness.

Two ideas:

  1. any(extras .== :h)
  2. At the start of your function, do extras isa Symbol && (extras = [extras]) Edit: I now notice this is almost what you wrote in parentheses.
1 Like
function inorequals(a, b)
    try
        return a in b
    catch
        return a === b
    end
end

does the job, but feels a bit dirty.

  1. Oh, I tried the shortcutting any(isequal(:h), extras) (which errors with no method iterate(::Symbol)). Didn’t even consider a normal broadcasting, that’s probably the neatest solution.
  2. Testing for isa Symbol is probably better than isa AbstractArray, because it catches Tuples etc. too.

You could do something like this. The symbol is typed out as \in<TAB>\_=<TAB>. You could define it directly as a function, but I feel like it’s a gross enough abuse of unicode that it should have an easy to type, written-out version as well.

julia> in_or_equals(a, b) = a==b || a∈b
in_or_equals (generic function with 1 method)

julia> const ∈₌ = in_or_equals
in_or_equals (generic function with 1 method)

julia> :v ∈₌ :v
true

julia>  :v ∈₌ [:v, :h]
true

The problem with that is in(:a, :b) is not false, it errors out.

That’s why the a==b comes first. If b is not iterable (e.g. a Symbol), it will error on in. Doing it this way allows it to check for equality first and bypass the in if equality holds.

EDIT: Oh, I see what you mean. For something like :v ∈₌ :h, you hit an error because it goes to the in branch.

julia> in_or_equals(a, b) = a == b || any(a .== b)
in_or_equals (generic function with 1 method)

julia> :v ∈₌ :h
false