Search code examples
f#programming-languagesmetaprogrammingnemerle

F# Meta-programming: is it possible to make IF X = 1 OR 2 syntax?


I want to simplify expression if(x == 1 || x == 2).
I wish I could write if(x == 1 or 2) but there is no syntax for that.
Other possibility is to use Contains or Any method like: if([1,2].Contains(x)) but this involves unnecessary call.

Can I create some operator which allows me to do this ?

In Nemerle language I can write macro:

macro @|||(left, right)
  match (left)
    | <[ $x == $y ]> => <[ $x == $y || $x == $right ]>
    | _ => Message.Error("Error"); <[ ]>

And then usage:

if (x == 1 ||| 2) { .. }

Can I create operator in such way in F# ?


Solution

  • You could use |> to accomplish this, borrowing from a common use of one of the haskell monoid instances.

    let appendResults f g = (fun x -> f(x) || g(x))
    let f x = x=1
    let g x = x=2
    let inline (>>||) x y = (appendResults f g) x y
    let x = 1
    if(x |> (1 >>|| 2)) then printfn "true" else printfn "false"
    

    For arbitrary numbers of arguments, just mimic the relevant mconcat method from haskell for the same effect, perhaps like this:

    let rec concatResults = function
    | [] -> (fun x -> false)
    | (x:xs) -> appendResults x (concatResults xs)
    

    Honestly though, you may as well just use Contains. If there is any special overhead doing that I doubt it really matters.