Я реализовал наивный оценщик некоторых функций.Я только что вошел в мир f #, поэтому он спросит вас, существует ли (и если да, как реализовать) более быстрый оценщик.Я должен получить структуру данных, которая содержит (variableName, (условие + newVariableName)).Эти два поля являются строками.Ниже приведена часть моей версии оценщика:
let env = new Dictionary<_,_>(HashIdentity.Structural)
//eval: expr -> Prop
let rec eval = function
//Val of string -- is a variable name or a string value
| Val e -> if e.Equals("TRUE") then True // True is a Prop type used for BDD Algorithm
elif e.Equals("FALSE") then False // False is a Prop type used for BDD Algorithm
else var e //var of string --- is a Prop type used for BDD Algorithm
| Int i -> var (i.ToString())
| Float e -> var (e.ToString())
| Const c -> var c //Const of string --- is a constant name (ex. "$foo" is a constant)
| Path (e, s) -> var ((eval e).ToString() + "." + s)
| Lookup(s, el) -> var s
| Integer(ex) -> eval ex
| FromTo (e, el) ->var ((eval e).ToString() + (eval el.Head).ToString() + (eval el.Tail.Head).ToString())
| Str(e) -> eval e
| Equality (v, e) -> let evalV = eval v
let evalE = eval e
match evalE with
| Var e ->
let sndKey = "Equality" + evalE.ToString()
if env.ContainsKey (evalV.ToString()) then
if env.[(evalV.ToString())].Equals(sndKey) then
var env.[(evalV.ToString())]
else ~~~ (var env.[(evalV.ToString())])
else
env.Add((evalV.ToString()), (evalV.ToString()) + sndKey)
var ((evalV.ToString()) + sndKey)
| _ as k -> if bddBuilder.Equiv k False then
let sndKey = "Equality" + "False"
if env.ContainsKey (evalV.ToString()) then
if env.[(evalV.ToString())].Equals(sndKey) then
var env.[(evalV.ToString())]
else ~~~ (var env.[(evalV.ToString())])
else
env.Add((evalV.ToString()), (evalV.ToString()) + sndKey)
var ((evalV.ToString()) + sndKey)
else let sndKey = "Equality" + "True"
if env.ContainsKey (evalV.ToString()) then
if env.[(evalV.ToString())].Equals(sndKey) then
var env.[(evalV.ToString())]
else ~~~ (var env.[(evalV.ToString())])
else
env.Add((evalV.ToString()), (evalV.ToString()) + sndKey)
var ((evalV.ToString()) + sndKey)
| Inequality (v, e) -> let evaluatedV = (eval v).ToString()
let evaluatedE = (eval e).ToString()
let sndKey = "Inequality" + evaluatedE
if env.ContainsKey (evaluatedV.ToString()) then
if env.[(evaluatedV.ToString())].Equals(sndKey) then
var env.[(evaluatedV.ToString())]
else ~~~ (var env.[(evaluatedV.ToString())])
else env.Add((evaluatedV.ToString()), (evaluatedV.ToString()) + sndKey)
var ((evaluatedV.ToString()) + sndKey)
| IfThenElse (e1, e2, e3) -> (eval e1 &&& eval e2) ||| ((~~~ (eval e1)) &&& eval e3)
| FindString(e1, e2) -> var ("FS" + (eval e1).ToString() + (eval e2).ToString())
| GreaterThan(e1, e2) -> let evaluatedV = (eval e1).ToString()
let evaluatedE = (eval e2).ToString()
let sndKey = "GreaterThan" + evaluatedE
if env.ContainsKey (evaluatedV.ToString()) then
if env.[(evaluatedV.ToString())].Equals(sndKey) then
var env.[(evaluatedV.ToString())]
else ~~~ (var env.[(evaluatedV.ToString())])
else env.Add((evaluatedV.ToString()), (evaluatedV.ToString()) + sndKey)
var ((evaluatedV.ToString()) + sndKey)
| GreaterThanOrEqual(e1, e2) -> let evaluatedV = (eval e1).ToString()
let evaluatedE = (eval e2).ToString()
let sndKey = "GreaterThanOrEqual" + evaluatedE
if env.ContainsKey (evaluatedV.ToString()) then
if env.[(evaluatedV.ToString())].Equals(sndKey) then
var env.[(evaluatedV.ToString())]
else ~~~ (var env.[(evaluatedV.ToString())])
else env.Add((evaluatedV.ToString()), (evaluatedV.ToString()) + sndKey)
var ((evaluatedV.ToString()) + sndKey)
| Null(e) -> var ("Null" + (eval e).ToString())
| GetToken(e1, e2, e3) -> var ((eval e1).ToString() + (eval e2).ToString())
| Mod(e1, e2) -> var ((eval e1).ToString() + (eval e2).ToString())
| Match(e1, e2) -> let evaluatedV = (eval e1).ToString()
let evaluatedE = (eval e2).ToString()
let sndKey = "Match" + evaluatedE
if env.ContainsKey (evaluatedV.ToString()) then
if env.[(evaluatedV.ToString())].Equals(sndKey) then
var env.[(evaluatedV.ToString())]
else ~~~ (var env.[(evaluatedV.ToString())])
else env.Add((evaluatedV.ToString()), (evaluatedV.ToString()) + sndKey)
var ((evaluatedV.ToString()) + sndKey)
| LessThenOrEqual(e1, e2) -> let evaluatedV = (eval e1).ToString()
let evaluatedE = (eval e2).ToString()
let sndKey = "LessThen" + evaluatedE
if env.ContainsKey (evaluatedV.ToString()) then
if env.[(evaluatedV.ToString())].Equals(sndKey) then
var env.[(evaluatedV.ToString())]
else ~~~ (var env.[(evaluatedV.ToString())])
else env.Add((evaluatedV.ToString()), (evaluatedV.ToString()) + sndKey)
var ((evaluatedV.ToString()) + sndKey)
| LessThen(e1, e2) -> let evaluatedV = (eval e1).ToString()
let evaluatedE = (eval e2).ToString()
let sndKey = "LessThen" + evaluatedE
if env.ContainsKey (evaluatedV.ToString()) then
if env.[(evaluatedV.ToString())].Equals(sndKey) then
var env.[(evaluatedV.ToString())]
else ~~~ (var env.[(evaluatedV.ToString())])
else env.Add((evaluatedV.ToString()), (evaluatedV.ToString()) + sndKey)
var ((evaluatedV.ToString()) + sndKey)
| Length(e) -> var ("Len" + (eval e).ToString())
| Full(e) -> var ("Full" + (eval e).ToString())
| Minus(e1, e2) -> var ((eval e1).ToString() + (eval e2).ToString())
| Times(e1, e2) -> var ((eval e1).ToString() + (eval e2).ToString())
| Plus (e1, e2) -> var ((eval e1).ToString() + (eval e2).ToString())
| Duration(e) -> eval e
| Minutes(e) -> eval e
| Trim(e) -> var ("Tri" + (eval e).ToString())
| Reverse(e) -> var ("Rev" + (eval e).ToString())
| Ast.And (v1, v2) -> eval v1 &&& eval v2
| Ast.Or (v1, v2) -> eval v1 ||| eval v2
| Ast.Not(v1) -> ~~~ (eval v1)
| _ as a-> failwithf "Expression %A not found" a
Редактировать: Этот оценщик используется для проверки логического состояния.В этой версии есть только один словарь, и он более производительный, но как я могу смоделировать такие ситуации, как следующие:
- var1 == "foo1" && var1 == "foo2" ---> Удовлетворительно: false
- var2> = 0 && var2> 0 ---> Удовлетворительно: true
- (var3 == "foo2" && var3! = null) ||var3 == "foo1" -> выполнимо: true