【发布时间】:2013-03-12 01:37:12
【问题描述】:
我一直在和LINQ to Z3 玩耍(不是生产用途)。
我最终以这种语法作为开始:
var i = 123;
var test2 = from t in TheormProver.NewTheorm()
let f = TheormProver.Func<int, bool>()
let a = TheormProver.Int
let g = TheormProver.Func<bool, int>()
where !f(a * 2) && g(f(g(f(4)))) == i * a && a < g(f(a))
select new { f = f.ToString(), g = g.ToString(), a, asd = "Test extra property" };
var solution = test2.Solve(); // Edited in for clarification
// note that test2 is a TheormProver<T> which has a "T Solve()" method defined.
静态的 TheromProver.Int 和 TheormProver.Func 方法/属性当前仅返回一个基本类型(根据它们的名称)。
继续前进,我想创建一种 Variable<T> 类型,其中包含更多信息而不仅仅是一个值。
TL;DR: 我遇到的问题是我希望 f 和 g 变量是我可以添加字段和属性的自定义类型,但是 我仍然希望能够将它们与我在 where 子句中的语法一起使用(即作为方法/Func)。
那么,如何在添加/拥有自己的属性的同时创建可用于方法语法的自定义类型?
请注意,我不在乎调用该方法是否什么都不做,或者不起作用,因为我将操纵 where 子句,因此它们永远不会被调用/执行。
示例:
var test2 = from t in TheormProver.NewTheorm()
let f = TheormProver.Func<int, bool>()
let a = TheormProver.Int
where !f(a * 2) && a > 3 // f is used to create a method call expression
select new { f , a };
var testSolution = test2.Solve();
var fSolution = testSolution.f; // F is its own type with unique properties/fields.
var fConstraints = fSolution.Constraints;
var fSomeProperty = fSolution.SomeProperty;
foreach(var constraint in fConstraints)
{
//.....
}
到目前为止,我已经模拟了一个正在进行的语法的快速示例:
http://liveworkspace.org/code/3Fm6JM$0
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
namespace ConsoleApplication1
{
class TheormProver
{
public static int Int { get { return default(int); } } // Really this would return my Variable<int>
public static Func<T, TResult> Func<T, TResult>() { return default(Func<T, TResult>); } // Really this would return my Variable<Func<T, TResult>>
protected List<Expression> Constraints; // Holds constraints / where clauses that get translated into the Z3 language
//This gets called when we do the first "let" and gets us into the correctly typed world with a generic parameter
public virtual TheormProver<T> Select<T>(Func<TheormProver, T> sel)
{
return new TheormProver<T>(Constraints);
}
}
// This is what the user of the library sees and is returned by a from t in new TheormProver(). T will be the anonymous type from the last let
class TheormProver<T> : TheormProver
{
public TheormProver(List<Expression> Constraints)
{
}
// This gets called on subsequent "let"s, going from the anonymous type with one property "f" to one with 2, "f, g". Chaining this way allows as many lets as we want
public virtual TheormProver<U> Select<U>(Expression<Func<T, U>> sel)
{
return new TheormProver<T, U>(sel, Constraints.ToList());
}
public virtual TheormProver<T> Where(Expression<Func<T, bool>> constraint)
{
var result = (TheormProver<T>)this; // This should be a clone to allow composable queries
result.Constraints.Add(constraint);
return result;
}
public virtual T Solve(out bool foundSolution)
{
// TODO: Call Z3 and get a solution
foundSolution = false;
return default(T);
}
}
internal class TheormProver<T, U> : TheormProver<U>
{
private LambdaExpression Selector;
private TheormProver<T> InternalTheorumProver;
public TheormProver(Expression<Func<T, U>> selector, List<Expression> constraints)
: base(constraints)
{
Selector = selector;
InternalTheorumProver = new TheormProver<T>(constraints);
}
}
class Program
{
static void Main(string[] args)
{
var test = from t in new TheormProver()
let f = TheormProver.Func<int, bool>()
let g = TheormProver.Func<bool, int>()
let a = TheormProver.Int
where g(f(a)) == 0
select new { f, g, a };
bool foundSolution;
var testSolution = test.Solve(out foundSolution);
}
}
}
【问题讨论】:
-
我认为如果你能展示一个你想要达到的目标的例子会很有帮助,即使那不是有效的语法。
-
感谢您的浏览,请参阅我的编辑。
-
为什么不创建一个具有这些属性和函数的类型呢?
let f = new MyType(TheormProver.Func<int, bool>()) ... where !f.Func(a * 2) -
这可以作为替代方案,但理想情况下,我希望 where 子句尽可能简单。我喜欢能够做到
f(g(a), g(123)) = 123等的简单性。 -
我想出的唯一其他选择是将
f保留为Func,但有一个扩展方法,他们将在选择中使用该方法将其转换为我的特殊类型为 select 语句获取正确的返回类型(类似于我当前使用.ToString()的语法)。
标签: c# linq types expression