-
Notifications
You must be signed in to change notification settings - Fork 15
PatternMatchingValueOrError
This pattern matching guide is split into the following sections:
- Pattern matching on discriminated unions.
- Pattern matching on options
- Pattern matching on Success<T>
- Pattern matching on tuples
- Pattern matching on
ValueOrError- Covered here. - Type-based pattern matching for all other types
- Value-based pattern matching on all other types
A ValueOrError can contain some value string, or some error string. Pattern matching on a ValueOrError instance therefore consists of matching values, via Value() and matching errors, via Error().
The generalised syntax for value/error patterns can be expressed using BNF-like syntax. As with all Succinc<T> pattern matching cases, there are two types of match. Firstly, matching and returning a value:
result = {option}.Match<{result type}>()
[ValueExpression | ErrorExpression ]...
[ElseExpression]
.Result();
ValueExpression ==>
.Value().Do({value} => {result type expression}) |
.Value().Do({result type expression}) |
.Value() [WithExpression|WhereExpression]...
ErrorExpression ==>
.Value().Do({value} => {result type expression}) |
.Value().Do({result type expression}) |
.Value() [WithExpression|WhereExpression]...
WithExpression ==>
.With({value})[.Or({value})]... .Do({value} => {result type expression}) |
.With({value})[.Or({value})]... .Do({result type expression})
WhereExpression ==>
.Where({item} => {boolean expression}).Do({value} => {result type expression}) |
.Where({item} => {boolean expression}).Do({result type expression})
ElseExpression ==>
.Else({option} => {result type expression}) |
.Else({result type expression})
And the alternative is a match that invokes a void expression (ie, an Action<{item type}>):
{option}.Match()
[ValueExpression | ErrorExpression ]...
[ElseExpression]
.Exec();
SomeExpression ==>
.Value().Do({value} => {action on value}) |
.Value() [WithExpression|WhereExpression]...
ErrorExpression ==>
.Error().Do({value} => {action on value}) |
.Error() [WithExpression|WhereExpression]...
WithExpression ==>
.With({value})[.Or({value})]... .Do({value} => {action on value})
WhereExpression ==>
.Where({item} => {boolean expression}).Do({value} => {action on value})
ElseExpression ==>
.Else({option} => {action on option}) |
.IgnoreElse()
To explain the above syntax:
-
{}denotes a non-literal, eg{void expression}could be the empty expression,{}, or something likeConsole.WriteLine("hello"). - Items in
[]are optional. -
|isor, ie[x|y]reads as "an optional x or y". -
...after[x]means 0 or more occurrences of x. -
==>is a sub-rule, which defines the expression on the left of this symbol.
The most basic form is matching on there being a value or an error:
public static bool ContainsValue(ValueOrError data)
{
return data.Match()
.Value().Do(x => true)
.Error().Do(x => false)
.Result();
}
public static void PrintValueOrError(ValueOrError data)
{
data.Match()
.Value().Do(Console.WriteLine)
.Error().Do(Console.WriteLine)
.Exec();
}In both examples above, we have used both Value() and Error(), but we could optionally use Else():
public static bool ContainsValue(ValueOrError data)
{
return data.Match()
.Value().Do(x => true)
.Else(x => false)
.Result();
}
public static void PrintValueOrError(ValueOrError data)
{
data.Match()
.Value().Do(Console.WriteLine)
.Else(Console.WriteLine)
.Exec();
}Else() or IgnoreElse() is invoked if there is no match from any specified Value() or Error() expressions.
One further change can be made to the functional example. We are supplying a parameter, x, which isn't then used. In this case, we can dispense with the lambda and just specify the return value:
public static bool ContainsValue(ValueOrError data)
{
return data.Match()
.Value().Do(true)
.Else(false)
.Result();
}The previous examples just matched any value or error. We might want to match specific values and errors though. We have two choices here: using Or() and Where().
To demonstrate
Firstly, using Or we could write a method to print whether the value is 1, 2 or 3, and simply report an error if it has one:
public static void OneToThreeReporter(ValueOrError data)
{
data.Match()
.Value().Of("1").Or("2").Or("3").Do(Console.WriteLine)
.Value().Do(v => Console.WriteLine("{0} isn't 1, 2 or 3!", v))
.Error().Do(_ => Console.WriteLine("Error"))
.Exec();
}If we want to check a range of values, or test the strings for something other than equality, we can use Where:
public static Option<int> IntParser(ValueOrError data)
{
return data.Match<Option<int>>()
.Value().Where(s => s.StartsWith("Int:")).Do(s => s.Substring(4).ParseInt())
.Else(Option<int>.None())
.Result();
}Action/FuncconversionsCyclemethods- Converting between
ActionandFunc - Extension methods for existing types that use
Option<T> - Indexed enumerations
IEnumerable<T>cons- Option-based parsers
- Partial function applications
- Pattern matching
- Pipe Operators
- Typed lambdas
AnyEither<TLeft,TRight>NoneOption<T>Success<T>Union<T1,T2>Union<T1,T2,T3>Union<T1,T2,T3,T4>UnitValueOrError