F# 引用 - 遍历由值表示的函数调用 [英] F# Quotations - traversing into function calls represented by a Value

查看:18
本文介绍了F# 引用 - 遍历由值表示的函数调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我花了几个小时试图掌握 F# 引用,但我遇到了一些障碍.我的要求是从可区分的联合类型中取出简单的函数(只是整数、+、-、/、*),并生成一个最终将用于生成 C 代码的表达式树.我知道使用带有直接"功能的引用是可能的.

I've spent a few hours trying to get to grips with F# Quotations, but I've come across a bit of a road block. My requirement is to take simple functions (just integers,+,-,/,*) out of a discriminated union type and generate an expression tree that will eventually be used to generate C code. I know this is possible using Quotations with 'direct' functions.

我的问题是表达式树似乎以值"结尾,我不知道如何遍历该值.

My problem is that the expression tree seems to terminate with a "Value", and I can't figure out how to traverse into that value.

我的问题是在这种情况下这是否真的可能?或者有没有其他值得考虑的方法.

My questions is whether this is actually possible in this situation? or are there any other approaches that are worth considering.

type FuncType = 
| A of (int -> int -> int)
| B
| C

[<ReflectedDefinition>]
let add x y = x + y


let myFunc1 = A (fun x y -> x + y )
let myFunc2 = A add 

let thefunc expr = 
    match expr with
    | A(x) ->
        <@ x @>
    | _ ->
        failwith "fail"

printfn "%A" (thefunc myFunc1) // prints "Value (<fun:myFunc1@14>)"
printfn "%A" (thefunc myFunc2) // prints "Value (<fun:myFunc2@15>)"
printfn "%A" <@ fun x y -> x + y @> // generates usable expression tree

推荐答案

引用表示在语法上引用的 F# 代码.这意味着如果您编写类似 <@ x @> 的内容,则引用将仅包含 Value 大小写,指定您引用了具有指定值的内容.(如果变量是在引用之外定义的,则变量会自动替换为值).

Quotations represent the F# code that was quoted syntactically. This means that if you write something like <@ x @>, the quotation will contain just Value case specifying that you quoted something which has the specified value. (Variables are automatically replaced with values if the variable is defined outside of the quotation).

您只能获取使用 <@ .. @> 显式引用的代码或标记为 ReflectedDefinition 并被引用的函数的引用通过引用中的 name(例如 <@ add @> 但不是例如 let f = add in <@ f @>).

You can only get quotation of code that was explicitly quoted using <@ .. @> or of a function that was marked as ReflectedDefinition and is referred to by name in a quotation (e.g. <@ add @> but not for example let f = add in <@ f @>).

为了能够按照您的代码段的建议进行操作,您还需要在 FuncType 中存储引号(以便您编写的 lambda 函数也被引用并且您可以获得它的主体).类似的东西:

To be able to do what your snippet suggests, you'll need to store quotations in your FuncType too (so that the lambda function that you write is also quoted and you can get its body). Something like:

type FuncType = 
  | A of Expr<int -> int -> int>
  | B | C

[<ReflectedDefinition>]
let add x y = x + y

let myFunc1 = A <@ fun x y -> x + y @>
let myFunc2 = A <@ add @>

let thefunc expr = 
    match expr with
    | A(x) -> x
    | _ -> failwith "fail"

这也适用于标记为 ReflectedDefinition 的函数.要提取函数的主体,您需要添加类似的内容(您需要将函数的参数替换为参数,但这应该会给您一些想法):

This should work for functions marked as ReflectedDefinition too. To extract the body of the function you need to add something like (you'll need to substitute arguments of the function for parameters, but this should give you some idea):

match expr with
| Lambdas(_, body) -> 
    match body with 
    | Call(_, mi, _) when Expr.TryGetReflectedDefinition(mi) <> None ->
      let func = Expr.TryGetReflectedDefinition(mi)
      match func with 
      | Some(Lambdas(_, body)) ->
          // 'body' is the quotation of the body
      | _ -> failwith "Not supported function"
    | _ -> failwith "Not supported function"
| _ -> failwith "Not supported expression"

这篇关于F# 引用 - 遍历由值表示的函数调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆