Universal Func tapez c #

J’écris un petit interprète Lisp en C #, et ça marche déjà déjà. Actuellement, j’utilise une interface pour représenter des fonctions:

public interface LispFunction { object Apply(ArrayList parameters); } 

L’interface est implémentée par plusieurs classes pour les fonctions internes (standard), les lambdas, le développement de macros, les méthodes d’appel dans les objects .net par reflection, etc. Veuillez noter que la vitesse n’est PAS un problème ici, mais simplement le plaisir de faire travailler l’interprète et de l’utiliser au travail.

J’aimerais maintenant que mon petit Lisp accepte l’utilisation de lambdas C # arbitraires au sein de l’interprète, comme ceci:

 Lisp foo = new Lisp(); foo.GlobalEnvironment.AddFunction("test", (bool a, int b) => a ? b : "whoops"); foo.Eval(foo.Read("(test #t 5)")); // Should evaluate to (object) 5 

La première chose qui me vint à l’esprit était d’utiliser Func , mais il me faudrait beaucoup de méthodes surchargées pour Func , Func , Func , etc. sur.

Est-il possible en C # d’accepter que des lambdas arbitraires soient appelés ultérieurement par reflection?

Est-il possible en C # d’accepter que des lambdas arbitraires soient appelés ultérieurement par reflection?

Eh bien, vous pouvez écrire une méthode pour prendre un délégué arbitraire:

 public void AddFunction(ssortingng name, Delegate function) 

Cependant, la conversion d’une expression lambda doit se faire en tant que délégué spécifique. Vous devez donc:

 Func function = (a, b) => a ? b : "whoops" foo.GlobalEnvironment.AddFunction("test", function); 

Ou jeté dans l’appel:

 foo.GlobalEnvironment.AddFunction("test", (Func)((a, b) => a ? b : "whoops")); 

Vous pouvez mettre toute la surcharge au même endroit, en gardant AddFunction entièrement général, mais en ayant une classe statique comme celle-ci (un peu comme Tuple ):

 public static class Func { public Func Create(Func function) { return function; } public Func Create(Func function) { return function; } public Func Create(Func function) { return function; } // etc } 

Cette classe existe fondamentalement juste pour la commodité. Vous appelez alors:

 foo.GlobalEnvironment.AddFunction("test", Func.Create((bool a, ssortingng b) => a ? b : "whoops"));