For example, if you have an expression like this:
Expression<Func<int, int>> fn = x => x * x;
Is there anything that will traverse the expression tree and generate this?
"function(x) { return x * x; }"
The concordance (c) statistic is the most commonly used statistic which measures discrimination. For binary outcomes, the c-statistic represents the area under the receiver operating characteristic curve (which is constructed by plotting the false positive rate against the true positive rate of the test data set).
E.g., if we were using GPA to predict test scores, a coefficient of 10 for GPA would mean that for every one-point increase in GPA we expect a 10-point increase on the test. Technically, the logistic regression coefficient means the same thing: as GPA goes up by 1, the log odds of being accepted go up by 1.051109.
It's probably not easy, but yes, it's absolutely feasible. ORMs like Entity Framework or Linq to SQL do it to translate Linq queries into SQL, but you can actually generate anything you want from the expression tree...
You should implement an ExpressionVisitor
to analyse and transform the expression.
EDIT: here's a very basic implementation that works for your example:
Expression<Func<int, int>> fn = x => x * x; var visitor = new JsExpressionVisitor(); visitor.Visit(fn); Console.WriteLine(visitor.JavaScriptCode); ... class JsExpressionVisitor : ExpressionVisitor { private readonly StringBuilder _builder; public JsExpressionVisitor() { _builder = new StringBuilder(); } public string JavaScriptCode { get { return _builder.ToString(); } } public override Expression Visit(Expression node) { _builder.Clear(); return base.Visit(node); } protected override Expression VisitParameter(ParameterExpression node) { _builder.Append(node.Name); base.VisitParameter(node); return node; } protected override Expression VisitBinary(BinaryExpression node) { base.Visit(node.Left); _builder.Append(GetOperator(node.NodeType)); base.Visit(node.Right); return node; } protected override Expression VisitLambda<T>(Expression<T> node) { _builder.Append("function("); for (int i = 0; i < node.Parameters.Count; i++) { if (i > 0) _builder.Append(", "); _builder.Append(node.Parameters[i].Name); } _builder.Append(") {"); if (node.Body.Type != typeof(void)) { _builder.Append("return "); } base.Visit(node.Body); _builder.Append("; }"); return node; } private static string GetOperator(ExpressionType nodeType) { switch (nodeType) { case ExpressionType.Add: return " + "; case ExpressionType.Multiply: return " * "; case ExpressionType.Subtract: return " - "; case ExpressionType.Divide: return " / "; case ExpressionType.Assign: return " = "; case ExpressionType.Equal: return " == "; case ExpressionType.NotEqual: return " != "; // TODO: Add other operators... } throw new NotImplementedException("Operator not implemented"); } }
It only handles lambdas with a single instruction, but anyway the C# compiler can't generate an expression tree for a block lambda.
There's still a lot of work to do of course, this is a very minimal implementation... you probably need to add method calls (VisitMethodCall
), property and field access (VisitMember
), etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With