-
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
/Func
conversionsCycle
methods- Converting between
Action
andFunc
- 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
Any
Either<TLeft,TRight>
None
Option<T>
Success<T>
Union<T1,T2>
Union<T1,T2,T3>
Union<T1,T2,T3,T4>
Unit
ValueOrError