<#@ template language="C#" debug="true" hostSpecific="true" #> <#@ output extension=".cs" #> <#@ Assembly Name="System.Core.dll" #> <#@ import namespace="System" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Collections.Generic" #> // Attention : ce fichier a été automatiquement généré par un // template T4. Toute modification manuelle sera écrasée !!! using System; using System.Collections.Generic; namespace Developpez.Dotnet { public static partial class FuncExtensions { <# for(int n = 2; n <= 4; n++) { string genericTypes = GenericTypesDeclaration(n); string tupleName = string.Format("Tuple<{0}>", genericTypes); string funcTypeName = string.Format("Func<{0}, TResult>", genericTypes); string methodName = string.Format("AsCached<{0}, TResult>", genericTypes); string dictionaryTypeName = string.Format("Dictionary<{0}, TResult>", tupleName); string paramsList = ParametersList(n); // Génération des structures Tuple #> private struct <#= tupleName #> { <# for(int i = 1; i <= n; i++) { #> public readonly T<#= i #> Value<#= i #>; <# } #> public Tuple(<#= ParametersDeclaration(n) #>) { <# for(int i = 1; i <= n; i++) { #> this.Value<#= i #> = value<#= i #>; <# } #> } } <# // Génération des méthodes AsCached #> /// /// Renvoie un wrapper de la fonction qui met en cache le résultat /// pour chaque ensemble de valeurs des arguments, de façon à n'appeler la fonction /// qu'une seule fois pour chaque ensemble de valeurs des arguments /// <# for (int i = 1; i <= n; i++) { #> /// Le type du paramètre <#= i #> <# } #> /// Le type de retour de la fonction /// La fonction à mettre en cache /// Une version de la fonction qui met en cache ses résultats public static <#= funcTypeName #> <#= methodName #>(this <#= funcTypeName #> function) { var cachedResults = new <#= dictionaryTypeName #>(); return (<#= paramsList #>) => { TResult result; var paramsTuple = new <#= tupleName #>(<#= paramsList #>); lock(cachedResults) { if (!cachedResults.TryGetValue(paramsTuple, out result)) { result = function(<#= paramsList #>); cachedResults.Add(paramsTuple, result); } } return result; }; } <# } #> <# for (int n = 2; n <= 4; n++) { string genericTypes = GenericTypesDeclaration(n); string funcTypeName = string.Format("Func<{0}, TResult>", genericTypes); string curriedFuncTypeName = CurriedFuncReturnType(n); string curryFuncMethodName = string.Format("Curry<{0}, TResult>", genericTypes); string curryFuncBody = CurryFuncBody(n); string actionTypeName = string.Format("Action<{0}>", genericTypes); string curriedActionTypeName = CurriedActionReturnType(n); string curryActionMethodName = string.Format("Curry<{0}>", genericTypes); string curryActionBody = CurryActionBody(n); #> /// /// Renvoie une version curryfiée de la fonction /// <# for (int i = 1; i <= n; i++) { #> /// Le type du paramètre <#= i #> <# } #> /// Le type de retour de la fonction /// La fonction à curryfier /// une version curryfiée de la fonction public static <#= curriedFuncTypeName #> <#= curryFuncMethodName #>(this <#= funcTypeName #> function) { <#= curryFuncBody #> } /// /// Renvoie une version curryfiée de l'action /// <# for (int i = 1; i <= n; i++) { #> /// Le type du paramètre <#= i #> <# } #> /// L'action à curryfier /// une version curryfiée de l'action public static <#= curriedActionTypeName #> <#= curryActionMethodName #>(this <#= actionTypeName #> action) { <#= curryActionBody #> } <# } #> <# for (int n = 2; n <= 4; n++) { string genericTypes = GenericTypesDeclaration(n); string funcTypeName = string.Format("Func<{0}, TResult>", genericTypes); for (int p = 1; p <= n; p++) { string partialFuncTypeName = PartialFuncReturnType(n, p); string partialFuncMethodName = string.Format("Apply{0}<{1}, TResult>", _ordinalsCapital[p], genericTypes); string partialFuncBody = PartialFuncBody(n, p); string actionTypeName = string.Format("Action<{0}>", genericTypes); string partialActionTypeName = PartialActionReturnType(n, p); string partialActionMethodName = string.Format("Apply{0}<{1}>", _ordinalsCapital[p], genericTypes); string partialActionBody = PartialActionBody(n, p); #> /// /// Renvoie une application partielle de la fonction /// <# for (int i = 1; i <= n; i++) { #> /// Le type du paramètre <#= i #> <# } #> /// Le type de retour de la fonction /// La fonction à appliquer partiellement /// La valeur fixe pour le <#= _ordinalsLowerCaseFrench[p] #> paramètre de la fonction /// une application partielle de la fonction public static <#= partialFuncTypeName #> <#= partialFuncMethodName #>(this <#= funcTypeName #> function, T<#= p #> <#= _ordinalsLowerCase[p] #>Arg) { <#= partialFuncBody #> } /// /// Renvoie une application partielle de l'action /// <# for (int i = 1; i <= n; i++) { #> /// Le type du paramètre <#= i #> <# } #> /// L'action à appliquer partiellement /// La valeur fixe pour le <#= _ordinalsLowerCaseFrench[p] #> paramètre de l'action /// une application partielle de l'action public static <#= partialActionTypeName #> <#= partialActionMethodName #>(this <#= actionTypeName #> action, T<#= p #> <#= _ordinalsLowerCase[p] #>Arg) { <#= partialActionBody #> } <# } } #> } } <#+ string GenericTypesDeclaration(int n) { return BuildList(n, "T{0}{1}", ", "); } string ParametersDeclaration(int n) { return BuildList(n, "T{0} value{0}{1}", ", "); } string ParametersList(int n) { return BuildList(n, "value{0}{1}", ", "); } string BuildList(int n, string format, string separator) { StringBuilder sb = new StringBuilder(); for (int i = 1; i <= n; i++) { sb.AppendFormat(format, i, separator); } sb.Remove(sb.Length - separator.Length, separator.Length); return sb.ToString(); } string CurriedFuncReturnType(int n) { string type = "TResult"; for (int i = n; i >= 1; i--) { type = string.Format("Func", i, type); } return type; } string CurryFuncBody(int n) { string lambdaParams = BuildList(n, "arg{0}{1}", " => "); string finalCall = string.Format("function({0})", BuildList(n, "arg{0}{1}", ", ")); return string.Format("return {0} => {1};", lambdaParams, finalCall); } string CurriedActionReturnType(int n) { string type = string.Format("Action", n); for (int i = n - 1; i >= 1; i--) { type = string.Format("Func", i, type); } return type; } string CurryActionBody(int n) { string lambdaParams = BuildList(n, "arg{0}{1}", " => "); string finalCall = string.Format("action({0})", BuildList(n, "arg{0}{1}", ", ")); return string.Format("return {0} => {1};", lambdaParams, finalCall); } static readonly string[] _ordinalsCapital = new[] { "", "First", "Second", "Third", "Fourth", "Fifth", "Sixth", "Seventh", "Eighth", "Ninth", "Tenth" }; static readonly string[] _ordinalsLowerCase = new[] { "", "first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "Ninth", "Tenth" }; static readonly string[] _ordinalsLowerCaseFrench = new[] { "", "premier", "second", "troisième", "quatrième", "cinquième", "sixième", "septième", "huitième", "neuvième", "dixième" }; string PartialFuncReturnType(int n, int p) { StringBuilder sb = new StringBuilder(); for (int i = 1; i <= n; i++) { if (i == p) continue; if (sb.Length > 0) sb.Append(", "); sb.AppendFormat("T{0}", i); } if (sb.Length > 0) sb.Append(", "); sb.Append("TResult"); return string.Format("Func<{0}>", sb); } string PartialFuncBody(int n, int p) { StringBuilder sbLambdaParams = new StringBuilder(); for(int i = 1; i <= n; i++) { if (i == p) continue; if (sbLambdaParams.Length > 0) sbLambdaParams.Append(", "); sbLambdaParams.AppendFormat("{0}Arg", _ordinalsLowerCase[i]); } StringBuilder sbArgs = new StringBuilder(); for(int i = 1; i <= n; i++) { if (sbArgs.Length > 0) sbArgs.Append(", "); sbArgs.AppendFormat("{0}Arg", _ordinalsLowerCase[i]); } string finalCall = string.Format("function({0})", sbArgs); return string.Format("return ({0}) => {1};", sbLambdaParams, finalCall); } string PartialActionReturnType(int n, int p) { StringBuilder sb = new StringBuilder(); for (int i = 1; i <= n; i++) { if (i == p) continue; if (sb.Length > 0) sb.Append(", "); sb.AppendFormat("T{0}", i); } return string.Format("Action<{0}>", sb); } string PartialActionBody(int n, int p) { StringBuilder sbLambdaParams = new StringBuilder(); for(int i = 1; i <= n; i++) { if (i == p) continue; if (sbLambdaParams.Length > 0) sbLambdaParams.Append(", "); sbLambdaParams.AppendFormat("{0}Arg", _ordinalsLowerCase[i]); } StringBuilder sbArgs = new StringBuilder(); for(int i = 1; i <= n; i++) { if (sbArgs.Length > 0) sbArgs.Append(", "); sbArgs.AppendFormat("{0}Arg", _ordinalsLowerCase[i]); } string finalCall = string.Format("action({0})", sbArgs); return string.Format("return ({0}) => {1};", sbLambdaParams, finalCall); } #>