Open Binto86 opened 2 years ago
This is called Design by Contract, and the previous proposal of C#s !!
was essentially a special case for a not-null precondition for that. They are a perfect use-case for decorators I believe. It has the advantage that it requires no additional language elements. A made-up implementation of your example, partially based on the metaprogramming issue:
#[macro(decorator)]
func PreCondition(args: MacroArgs, target: SyntaxTree): SyntaxTree
{
val target = target.cast[SyntaxTree.FuncDeclaration];
val condition = parse_expr(args[0]);
return quote!{
#(target.signature)
{
if not (#(args.condition)) throw ArgumentException();
return { #(target.body) };
}
};
}
An example usage could be:
#[PreCondition(n > 0)]
func log_positive(n: int32) = Console.WriteLine(n);
Which would be transformed by the macro to
func log_positive(n: int32)
{
if not (n > 0) throw ArgumentException();
return { Console.WriteLine(n) }; // Looks odd but it's OK, returns unit
}
That looks good to me
This can be achieved with active patterns. F# example
let (|NonNull|) x =
if isNull x then
nullArg "x"
else
x
let f (NonNull x) = // x is never null
printfn "%A" x
It's a simple and very powerful tool, which can be used anywhere, where pattern matching is allowed. With addition for CallerArgumentExpression it's even can capture real argument name.
Research document: https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/p29-syme.pdf
While active patterns are cool and we have discussed them related to the pattern matching issue, they will probably not make it into the language, as we are planning to expose a pattern matching protocol that would be a more general tool. I believe this case is more neatly solved with decorators, but that's just my 2 cents.
You may want to throw an exception when value inputed into your function doesn't match what you want (value is null is the most common example). In c# you would problably need to manually check if value matches this rule using
if
s and throwing exception in the function. It would be nice to be able to specify some structure that could throw on the method call without you needing to manually check the value. I think that this could be solved by new structurerule
. I am thinking of this syntax:The
rule
structure would need to have at least onethrow
statement an would accept only one parameter. Question is how to specify that you want certain rule to be aplied to your parameter, i usedis
keyword, but thats probably not the best way.