函数解释器返回Func <double [],double>

时间:2015-11-19 18:19:58

标签: c# parsing math

我使用的是数学函数解释器Jace.NET。以下是如何使用它的一个很好的例子:

            WebView wvTask = (WebView) findViewById(R.id.wvTask);
            wvTask.getSettings().setJavaScriptEnabled(true);
            wvTask.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
            wvTask.getSettings().setLoadWithOverviewMode(true);
            wvTask.getSettings().setUseWideViewPort(true);
            wvTask.getSettings().setBuiltInZoomControls(true);
            wvTask.getSettings().setPluginState(WebSettings.PluginState.ON);
            wvTask.getSettings().setGeolocationEnabled(true);
            wvTask.getSettings().setLoadsImagesAutomatically(true);
            wvTask.setWebChromeClient(new WebChromeClient());
            wvTask.getSettings().setDomStorageEnabled(true);
            wvTask.getSettings().setAppCacheEnabled(true);
            wvTask.getSettings().setDatabaseEnabled(true);
            wvTask.loadUrl(XXX); //here is my URL, tried both https and http - nothing worked. 

但另一个库(我必须使用)需要CalculationEngine engine = new CalculationEngine(); Func<double, double, double> formula = (Func<double, double, double>)engine.Function("x1+2/(3*x2)") .Parameter("x1", DataType.FloatingPoint) .Parameter("x2", DataType.FloatingPoint) .Result(DataType.FloatingPoint) .Build(); 作为输入,而不是Jace可以返回的Func<double[],double>Func<double,double,double>

所以我需要的是一个解释器,它可以创建一个函数,它接受一个double数组作为输入并返回一个值,所以基本上就是这样:

Func<double,double,double,double>

我试图在Jace做这个,但没有运气。有什么想法吗?

1 个答案:

答案 0 :(得分:2)

lambda表达式的一个好处是它们很容易用来创建委托实例,并且可以使用常规方法完成相同类型的参数映射。

例如,如果您有一个API需要调用,并且您传递的是Func<double[], double>,但实际上您拥有的是Func<double, double, double>(例如),您可以执行此操作使用特殊类中的命名方法:

class FuncMapper
{
    private readonly Func<double, double, double> _func;

    public FuncMapper(Func<double, double, double> func)
    {
        _func = func;
    }

    public double M(double[] input)
    {
        return _func(input[0], input[1]);
    }
}

用过:

Func<double[], double> formula = new FuncMapper(jaceFunc).M;

但那相当冗长。使用lambda表达式,您可以使编译器完成大部分工作:

Func<double[], double> formula = array => jaceFunc(array[0], array[1]);

请注意变量捕获是否以及如何发生。 lambda表达式将根据其范围捕获jaceFunc;如果它是一个局部的并且在lambda表达式之后保持不变,那么它在lambda表达式中也将保持不变。但是如果捕获具有更长生命周期的变量并且在调用lambda代理之前修改它,则lambda表达式将使用变量的 modified 值。被捕获的是变量,而不是它的价值。


备注:

  • 您的具体方案涉及动态创建的委托(例如上面的jaceFunc),但当然同样的方法也适用于命名方法。
  • 上面只显示了一个场景,即两个输入参数,而你说你可能有两个以上。你可以像你一样解决这个问题(即使用switch或类似的东西),或者你可以编写一个Expression - 构建方法,该方法基本上可以实现上述方法,但是会考虑被调用的参数个数方法并生成必要的数组元素查找并将它们传递给调用的委托或方法。

    对于少数情况,switch更容易,但如果您需要概括对于不同的参数类型和方法签名变体,从长远来看,基于Expression的方法可能会更有用。