W języku C# z .NET 3.5 można do tego celu użyć Expression
; możesz zbudować sparametryzowane wyrażenie, a następnie skompilować je do delegata. Dokładnie to zrobiłem dla aspektu matematycznego Finguistics. Nadal mam kod parsowania użyłem, jeśli chcesz ...
Główną sztuczką, której użyłem było to, aby utrzymać typ delegata znany, użyłem tablicy jako typ wejścia - traktowanie różnych argumentów jako arr [0] , arr 1, arr [2] itd. Oznacza to, że mogę skompilować (na przykład) Func<decimal[], decimal>
(pobiera tablicę z decimal
s, zwraca decimal
).
Po wywołaniu Compile()
, jest to portmonetka tak, jakbyś miał kod, aby zrobić to bezpośrednio.
(edit)
jako krótki przykład użycia Expression
w ten sposób (z twardym kodowane funkcji), patrz poniżej. Analizator składni, który napisałem już obecnie działa jako sprawdzianpredykatu - tj. Aby sprawdzić, czy "? + (2 *? -?) = 22 +?" - ale nie byłoby trudno go zmienić, aby zamiast tego zwrócić wynik (i wprowadzić więcej operacji, takich jak sin
/pow
/etc - prawdopodobnie przez mapowanie ich bezpośrednio do publicznych metod na obiekcie pomocniczym (przez Expression.Call
)).
using System;
using System.Linq.Expressions;
static class Program
{
static void Main()
{
var args = Expression.Parameter(typeof(float[]), "args");
var x = Expression.ArrayIndex(args, Expression.Constant(0));
var y = Expression.ArrayIndex(args, Expression.Constant(1));
var add = Expression.Add(x, y);
var lambda = Expression.Lambda<Func<float[], float>>(add, args);
Func<float[], float> func = lambda.Compile();
Console.WriteLine(func.Call(1, 2));
Console.WriteLine(func.Call(3, 4));
Console.WriteLine(func.Call(5, 6));
}
static T Call<T>(this Func<T[], T> func, params T[] args)
{ // just allows "params" usage...
return func(args);
}
}
Jak złożone jest wyrażenie? Ograniczona do czterech funkcji arytmetycznych lub bardzo ogólnych? – Richard
Może być dość skomplikowany, w tym funkcje o wielu parametrach. – Steve