2

我想简化表达if(x == 1 || x == 2)
我希望我能写if(x == 1 or 2),但没有语法。
其他可能性是使用 Contains 或 Any 方法,例如:if([1,2].Contains(x))但这涉及不必要的调用。

我可以创建一些允许我这样做的操作员吗?

在 Nemerle 语言中,我可以编写宏:

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

然后用法:

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

我可以在 F# 中以这种方式创建运算符吗?

4

5 回答 5

9

我同意 Brian 的评论,即构建一个宏来保存三个字符可能不是一个好主意。这只会使程序更难阅读(对于那些不知道您的自定义宏或更改运算符含义的人)。

此外,您很可能可以使用标准 F# 构造(如模式匹配)以更简洁的方式编写相同的逻辑。例如:

match x with
| 1 | 2 -> printfn "yes"
| _     -> printfn "no"

惯用的解决方案将取决于具体案例,从您给出的示例中很难判断。

于 2012-08-27T15:39:07.700 回答
3

您可以使用|>其中一个 haskell monoid 实例的常见用法来完成此操作。

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"

对于任意数量的参数,只需模仿mconcathaskell 中的相关方法即可获得相同的效果,可能像这样:

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

不过老实说,您也可以只使用 Contains。如果有任何特殊的开销,我怀疑它真的很重要。

于 2012-08-27T13:48:27.097 回答
2

我同意布赖恩和托马斯的观点;发明自己可能只使用几次的宏有点实际意义。
但是,从研究函数式语言的内部结构来看,我确实觉得这很有趣。
考虑一下:

// Generic
let inline mOp1<'a> op sample x = op sample x, sample
let inline mOp2<'a> op1 op2 (b, sample) x = op1 b (op2 sample x), sample

// Implementation for (=) and (||)
let (==) = mOp1 (=)
let (|=) = mOp2 (||) (=)

// Use
let ret1 = x == 1 |= 2 |> fst

您可以在此处找到更多详细信息、其他运算符和性能测量:https ://stackoverflow.com/a/11552429/974789

于 2012-08-28T06:28:58.410 回答
0

这有点骇人听闻,但确实有效

let x = 1
let inline (|||) a b = [a;b]
let inline (==) a b = b |> List.exists (fun t -> t=a)

if x == (1 ||| 2) then printfn "true" else printfn "false"

它需要用于或和等于的自定义运算符。修改它以支持任意或链并不难

当然,如果您只需要 2 个数字,您可以这样做

let x = 1
let inline (|||) a b = (a,b)
let inline (==) a (c,d) = a=c ||a=d

if x == (1 ||| 2) then printfn "true" else printfn "false"
于 2012-08-27T10:54:36.880 回答
0

这是通过将元组转换为数组来实现的,因此不要期望获得最佳性能。

let inline (==) a b = 
    Microsoft.FSharp.Reflection.FSharpValue.GetTupleFields(b) 
        |> Array.exists((=) a)

例子:

3 == (1,2)      // false
3 == (1,2,3)    // true
于 2012-08-27T11:22:04.747 回答