You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
One issue with .Match is that it allocated objects for case matching functions to capture the closure. C# has a mechanism to prevent this from happening with a static keyword on lambda. However, for it to work the "closure" state has to be threaded manually.
Consider an example of such a match function called .FoldMatch based on your Expression example implemented in the Expression class. Functions StaticEvaluate and EvaluateUniqueVar show how such a utility could be used:
// Adapted from https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/discriminated-unions#using-discriminated-unions-for-tree-data-structuresusing System.Collections.Immutable;using Dunet;usingstatic Expression;varenvironment=newDictionary<string,int>(){["a"]=1,["b"]=2,["c"]=3,};varexpression=new Add(new Variable("a"),new Multiply(new Number(2),new Variable("b")));// Evaluate a + 2 * bvarresult= Evaluate(environment, expression);
Console.WriteLine(result);// 5staticintEvaluate(Dictionary<string,int>env,Expressionexp)=>
exp.Match(number => number.Value,add => Evaluate(env, add.Left)+ Evaluate(env, add.Right),multiply => Evaluate(env, multiply.Left)* Evaluate(env, multiply.Right),variable => env[variable.Value]);// Allows to evaluate expressions without allocating lambdasstaticintStaticEvaluate(Dictionary<string,int>env,Expressionexp)=>
exp.FoldMatch(
env,static(_,number)=> number.Value,static(e,add)=> StaticEvaluate(e, add.Left)+ StaticEvaluate(e, add.Right),static(e,multiply)=> StaticEvaluate(e, multiply.Left)* StaticEvaluate(e, multiply.Right),static(e,variable)=> e[variable.Value]);// An example of how to thread state through a recursive function// It simulates a (made up) use case where variables can be used only oncestatic(IImmutableDictionary<string,int> state,int result)EvaluateUniqueVar(IImmutableDictionary<string,int>env,Expressionexp)=>
exp.FoldMatch(
env,static(e,number)=>(e, number.Value),static(e,add)=>{(e,var left)= EvaluateUniqueVar(e, add.Left);(e,var right)= EvaluateUniqueVar(e, add.Right);return(e,left+right);},static(e,multiply)=>{(e,var left)= EvaluateUniqueVar(e, multiply.Left);(e,var right)= EvaluateUniqueVar(e, multiply.Right);return(e,left*right);},static(e,variable)=>(e.Remove(variable.Value), e[variable.Value]));[Union]publicpartialrecordExpression{partialrecordNumber(intValue);partialrecordAdd(ExpressionLeft,ExpressionRight);partialrecordMultiply(ExpressionLeft,ExpressionRight);partialrecordVariable(stringValue);public T FoldMatch<T,TState>(TStatestate,Func<TState,Number,T>number,Func<TState,Add,T>add,Func<TState,Multiply,T>multiply,Func<TState,Variable,T>variable)=>thisswitch{
Number x => number(state, x),
Add x => add(state, x),
Multiply x => multiply(state, x),
Variable x => variable(state, x),
_ =>thrownew InvalidOperationException()};}
The text was updated successfully, but these errors were encountered:
One issue with
.Match
is that it allocated objects for case matching functions to capture the closure. C# has a mechanism to prevent this from happening with astatic
keyword on lambda. However, for it to work the "closure" state has to be threaded manually.Consider an example of such a match function called
.FoldMatch
based on your Expression example implemented in theExpression
class. FunctionsStaticEvaluate
andEvaluateUniqueVar
show how such a utility could be used:The text was updated successfully, but these errors were encountered: