What do you think of `(f1 & f2)(x)`?

There might be a thread or a github issue about that but it’s really hard to search for `or` and `and` terms, please redirect me if I missed it

I’d like to use a syntax that looks like that:

``````f = <(5) & >(1)
g = isnan | ismissing
``````

I can pirate them but obviously I’d rather not:

``````import Base: &, |
(&)(f1::Function, f2::Function) = x -> f1(x) & f2(x)
(|)(f1::Function, f2::Function) = x -> f1(x) | f2(x)
``````

I looked in here for alternative characters but none looks good to me

(I always mix `∧` and `∨` so I don’t want to use them)

was there already a discussion about this? Could it be added in Base Julia or is there a reason why it’s not defined?

edit: changed `&&` to `&` and `||` to `|` (doesn’t matter in my case)

1 Like

It’s not a bad idea, but one reason not to do this in Julia base is that it uses the `&` operator which normally means bitwise AND to mean logical AND. Or, in other words, if you wanted:

``````(<some_operator>)(f1, f2) = x -> f1(x) & f2(x)
``````

what operator would you use? The `&` operator seems like the logical and obvious choice, but your proposal would use that to mean something different.

On the other hand, in your own code you could use `and` and `or` as function names without needing to pirate anything. Alas, you can’t use them as infix operators, but that may be ok if it makes your code a bit more obvious and free of type piracy.

6 Likes

In the past when I’ve “needed” this (you never really need this though, do you…) I implemented \vee and \wedge like the Base implementation of `∘`

``````"""
f ∧ g ∧ ...

Create an anonymous function that evaluates to `f(x) && g(x) && ...`
"""
function ∧ end
∧(f) = f
∧(f, g) = (x...) -> f(x...) && g(x...)
∧(f, g, h...) = ∧((f ∧ g), h...)

function ∨ end
∨(f) = f
∨(f, g) = (x...) -> f(x...) || g(x...)
∨(f, g, h...) = ∨((f ∨ g), h...)
``````
``````julia> map(isascii ∧ isuppercase ∨ isdigit, ('A', '1', 'Σ'))
(true, true, false)
``````

Note that evaluation is “kind-of-short-circuiting”; you can’t replicate `&&` with a function, since it’s control flow, but the evaluation of the function chain will exit early if it hits a `false` (or `true`, depending). Also, all arguments to `∨` and `∧` are evaluated when the anonymous function is created (like with `ifelse`).
As an exercise a while back I also wrote a macro version of this to overcome the mentioned limitations, but I still haven’t been able to think of a single case where using it would be worthwhile…

``````macro and(args...)
ex = Expr(:&&, first(args))
ex′ = ex
for i in 2:length(args)
push!(ex′.args, Expr(:&&, args[i]))
ex′ = last(ex′.args)
end
esc(ex)
end
``````

edit: sorry, I didn’t find the right version of the macro, so the above doesn’t do what I said it does. Oh well…

6 Likes