F#参数检查

F#参数检查,f#,arguments,code-contracts,design-by-contract,quotations,F#,Arguments,Code Contracts,Design By Contract,Quotations,F#有一些很好的简洁的参数检查函数,可以这样使用: let foo (bar : string) : string = if bar = null then nullArg "bar" ... open Microsoft.FSharp.Quotations let nonNull (expr : Expr) = match expr with | Patterns.Value(null, _) -> failwith "it is null"

F#有一些很好的简洁的参数检查函数,可以这样使用:

let foo (bar : string) : string =
    if bar = null then
        nullArg "bar"
    ...
open Microsoft.FSharp.Quotations

let nonNull (expr : Expr) =
  match expr with 
  | Patterns.Value(null, _) -> failwith "it is null"
  | _ -> ()
然而,我更喜欢一种更具规定性的表达方式,即la代码:

let foo (bar : string) : string =
    Contract.Requires (bar <> null, "bar is null")
...
let foo(条:字符串):字符串=
合同。要求(栏为空,“栏为空”)
...
然而,我梦想编写的代码是:

let nonNull (expr : Expr) : unit =
    // quotation magic

let foo (bar : string) : string =
    nonNull <@ bar @>
    ...
设为非空(expr:expr):单位=
//引文魔术
让foo(bar:string):string=
非空
...
问题是:这能用F表示吗;或者换句话说,F#中是否有非null的有效实现


对我来说,它看起来不像,但也许这里有人可以验证它。

正如@svick在评论中提到的,这目前不会很好地工作,因为
实际上将表示为
值(null,typeof)
。因此,您可以检查该值是否为
null
,但当前无法获取参数的名称

您可以执行的部分如下所示:

let foo (bar : string) : string =
    if bar = null then
        nullArg "bar"
    ...
open Microsoft.FSharp.Quotations

let nonNull (expr : Expr) =
  match expr with 
  | Patterns.Value(null, _) -> failwith "it is null"
  | _ -> ()

但是,这在下一个版本中可能会有所改进:-)这需要能够在引号中表示变量的名称。因此,也许可以使用下一个版本的F#

我认为这是行不通的。引号
不包含任何有关参数名称的信息。动机是什么?@MarkSeemann动机是函数契约的简洁、精确的表达。@BentRasmussen的确,这是吹毛求疵,但是
如果bar=null,则空值“bar”
有32个字符,而
契约.Requires(bar null,“bar为空”)
有46个字符,所以我看不出它为什么没有那么紧凑。一般来说,.NET没有像埃菲尔那样的断言……不是答案,只是有切点关系,但有这个方向的东西,因此很有趣(除此之外,@TomasPetricek指出,这一切都取决于报价是否有足够的信息被隐藏)好吧,好吧,很高兴看到其他人也有类似的想法。:-)谢谢你的回答,托马斯。既然这是目前最好的答案,我将把它标记为答案(并对用户声音进行投票)。