F# fsharp报价表列表->;Expr处理
我能做些什么来让下面的工作正常 我需要创建一个函数来接受Expr列表并返回Expr(Expr list->Epxr)F# fsharp报价表列表->;Expr处理,f#,quotations,F#,Quotations,我能做些什么来让下面的工作正常 我需要创建一个函数来接受Expr列表并返回Expr(Expr list->Epxr) 类型数据对象()= 让data=System.Collections.Generic.Dictionary() 成员this.AddValue propertyIndex value=data.Add(propertyIndex,value) 成员this.GetValue propertyIndex= 将data.TryGetValue属性索引与匹配 |(true,value)
类型数据对象()=
让data=System.Collections.Generic.Dictionary()
成员this.AddValue propertyIndex value=data.Add(propertyIndex,value)
成员this.GetValue propertyIndex=
将data.TryGetValue属性索引与匹配
|(true,value)->value
|(false,824;)->框“未找到属性”
...
(有趣的args->
List.iteri(fun i arg->data.AddValue i)
资料
@@>)
我创建了DataObject类型以在中添加args的值。但不知何故,我无法让代码在不同的args(args.[0]…args.[I])之间迭代。我得到的信息是:
变量“arg”绑定在引号中,但用作拼接表达式的一部分。这是不允许的,因为它可能超出其范围
如果我显式地访问args(args[0]、args[1]、…),解决方案就可以工作,但一旦我尝试添加迭代,我就会遇到问题。因为arg列表的长度是灵活的,所以这对我来说不是一个可行的解决方案
我尝试过不同的方法,但没有成功。有什么解决办法吗
[编辑]
在我的解决方案中添加Tomas的反馈给我带来了以下好处:
type DataObject(values: obj []) =
let propertyMap = new Map<int, obj>(values |> Seq.mapi (fun i value -> (i, value)))
member this.GetValue propertyIndex : obj =
match propertyMap.TryFind propertyIndex with
| Some(value) -> value
| None -> box "property not found"
(fun args ->
let boxedArgs =
args |> List.map (fun arg ->
match arg with
| Quotations.Patterns.Var var ->
if var.Type = typeof<int> then
<@@ (box (%%arg: int)) @@>
else if var.Type = typeof<string> then
<@@ (box (%%arg: string)) @@>
else if var.Type = typeof<System.Guid> then
<@@ (box (%%arg: System.Guid)) @@>
else
failwith ("Aha: " + var.Type.ToString())
| _ -> failwith ("Unknown Expr as parameter"))
<@@ new DataObject(%%(Expr.NewArray(typeof<obj>, boxedArgs))) @@>))
类型数据对象(值:obj[])=
让propertyMap=新映射(值|>Seq.mapi(乐趣i值->(i,值)))
成员this.GetValue propertyIndex:obj=
将propertyMap.TryFind propertyIndex与匹配
|一些(值)->值
|无->框“未找到属性”
(有趣的args->
让boxedArgs=
args |>List.map(有趣的arg->
将arg与
|QUOTES.Patterns.Var->
如果变量类型=类型,则
否则,如果变量类型=类型,则
否则,如果变量类型=类型,则
其他的
failwith(“Aha:+var.Type.ToString())
|->failwith(“未知表达式作为参数”))
))
这很有效!唯一的问题是我想摆脱如果。。。否则将无法获得正确的转换。有什么想法吗?这是个棘手的问题!为了理解代码不起作用的原因,您需要清楚地区分两个级别——在一个级别(meta),您编写引用,在另一个级别(base),您使用数据对象运行一些代码 代码不起作用的原因是,
args
是元级别的表达式列表,您试图在基本级别对其进行迭代。迭代需要在元级别进行
解决这个问题的一种方法是在元级别进行迭代,并生成一个函数列表,这些函数为所有参数调用AddValue
。然后,您可以编写以下函数:
(fun args ->
// Given arguments [a0; a1; ...] Generate a list of functions:
//
// [ fun data -> data.AddValue 0 a0; data ]
// [ fun data -> data.AddValue 1 a1; data ... ]
args
|> List.mapi (fun i arg ->
<@ fun (data:DataObject) -> data.AddValue i (%%arg : string); data @>)
// Compose all the functions just by calling them - note that the above functions
// take DataObject, mutate it and then return it. Given [f0; f1; ...] produce:
//
// ... (f1 (f0 (new DataObject())))
//
|> List.fold (fun dobj fe -> <@ (%fe) (%dobj) @>) <@ new DataObject() @> )
嗨,托马斯。谢谢你的投入,这让我更进一步了。到目前为止,我已经用答案编辑了这个问题。你对if..then结构也有一些想法吗?(参见有问题的编辑)关于编辑,我认为您可以将
if
替换为Expr.compresse(arg,typeof)
——这将为您提供一个表示任何其他表达式arg
装箱的表达式。
(fun args ->
// Given arguments [a0; a1; ...] Generate a list of functions:
//
// [ fun data -> data.AddValue 0 a0; data ]
// [ fun data -> data.AddValue 1 a1; data ... ]
args
|> List.mapi (fun i arg ->
<@ fun (data:DataObject) -> data.AddValue i (%%arg : string); data @>)
// Compose all the functions just by calling them - note that the above functions
// take DataObject, mutate it and then return it. Given [f0; f1; ...] produce:
//
// ... (f1 (f0 (new DataObject())))
//
|> List.fold (fun dobj fe -> <@ (%fe) (%dobj) @>) <@ new DataObject() @> )
<@@ let d = new DataObject()
d.AddValues(%(Expr.NewArray(typeof<obj>, args)))
d @@>