4

F# has some nice succint argument checking functions that can be used like this:

let foo (bar : string) : string =
    if bar = null then
        nullArg "bar"
    ...

I prefer a more prescriptive expression, however, a la Code Contracts:

let foo (bar : string) : string =
    Contract.Requires (bar <> null, "bar is null")
...

The code I dream about writing is this, however:

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

let foo (bar : string) : string =
    nonNull <@ bar @>
    ...

The question is: can this be expressed in F#; or put another way, is there a working implementation for nonNull in F#?

It doesn't look like it to me but perhaps someone here can verify it.

svick
  • 236,525
  • 50
  • 385
  • 514
Bent Rasmussen
  • 5,538
  • 9
  • 44
  • 63
  • 1
    I don't think this is going to work. The quotation `<@ bar @>` doesn't contain any information about the parameter name. – svick Jul 13 '14 at 18:24
  • What would be the motivation? – Mark Seemann Jul 13 '14 at 18:37
  • 2
    @MarkSeemann The motivation is succint, precise expression of the function contract. – Bent Rasmussen Jul 14 '14 at 15:13
  • What's not succinct and precise about the first code example in your question? – Mark Seemann Jul 14 '14 at 17:49
  • @MarkSeeman It's not as compact; it's also not how I prefer to express contracts, as I wrote. I realize this is nitpicking and your mileage may vary. Actually, this is just my attempt at approximating the "requires" construct from Eiffel and elsewhere. – Bent Rasmussen Jul 15 '14 at 10:50
  • 1
    @BentRasmussen Indeed, it's nitpicking, but `if bar = null then nullArg "bar"` has 32 characters, while `Contract.Requires (bar <> null, "bar is null")` has 46 characters, so I fail to see how it's not as compact. In general, .NET just doesn't have Eiffel-like assertions... – Mark Seemann Jul 15 '14 at 12:35
  • @MarkSeeman That's the whole point of my Post, Mark. :-) My trick (3rd example), if it had had a working implementation, would only use 17 characters and would prescriptively express the contract (at least in the implementation). Design by Contract is already being used in the .NET Framework BCL albeit in a less-than-elegant way via Code Contracts. My simple ambition with my post was just to achieve the behavior of the first example through the compact syntax of the third. – Bent Rasmussen Jul 15 '14 at 14:37
  • 1
    Not an answer, and only tangentially related, but [unquote](http://stackoverflow.com/a/5669263/11635) does stuff in this direction and hence is interesting (except that, as pointed out by @TomasPetricek it all comes down to whether quotations has sufficient info sequestered away) – Ruben Bartelink Jul 15 '14 at 22:22

1 Answers1

4

As @svick mentioned in the comments, this is currently not going to work very well, because <@ bar @> will actually be represented as Value(null, typeof<string>). So, you can check whether the value is null, but you cannot currently get the name of the parameter.

The part that you can do looks like this:

open Microsoft.FSharp.Quotations

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

However, this is something that might improve in the next version :-) This F# feature request would require the ability to represent the name of variables in the quotation. So perhaps check with the next version of F#!

Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
  • Well, well, nice to see that other people have had a similar idea. :-) Thank you for the answer Thomas. And since this is the best possible at the moment, I will mark it as the answer (and give a vote on user voice). – Bent Rasmussen Jul 14 '14 at 15:23