2009-12-18 8 views
5

В C# Я мог бы создать строковое представление графа объектов довольно легко с помощью деревьев выражений.F # quotations object graph

public static string GetGraph<TModel, T>(TModel model, Expression<Func<TModel, T>> action) where TModel : class 
{ 
      var method = action.Body as MethodCallExpression; 
      var body = method != null ? method.Object != null ? method.Object as MemberExpression : method.Arguments.Any() ? method.Arguments.First() as MemberExpression : null : action.Body as MemberExpression; 
      if (body != null) 
      { 
       string graph = GetObjectGraph(body, typeof(TModel)) 
       return graph; 
      } 
      throw new Exception("Could not create object graph"); 
} 

В F # Я рассматривал Котировки, чтобы попытаться сделать то же самое, и не могу понять это. Я попытался преобразовать цитату в выражение с помощью библиотек PowerPack, но до сих пор не повезло, и информация в Интернете кажется довольно скудной по этой теме.

Если вход:

let result = getGraph myObject <@ myObject.MyProperty @> 

выход должен быть "myObject.myProperty"

+1

Dunno ответ (цитаты не являются моей сильной стороной), но вы хотите, чтобы вы прочитали http://blogs.msdn.com/dsyme/archive/2009/10/23/a-quick-refresh-on- query-support-in-f-power-pack.aspx, которые являются лучшими текущими документами о поддержке Quotation-> Expression в PowerPack. – Brian

ответ

5

Вы можете увидеть, что вы получаете от выражения котировального в FSI сессии:

> let v = "abc" 
> <@ v.Length @>;; 
val it : Expr<int> 
= PropGet (Some (PropGet (None, System.String v, [])), Int32 Length, []) 

> <@ "abc".Length @>;; 
val it : Expr<int> 
= PropGet (Some (Value ("abc")), Int32 Length, []) 

вы можно найти описание всех активных шаблонов, доступных для разбора qoutations, на

руководство \ FSharp.Core \ Microsoft.FSharp.Quotations.Patterns.html

под F # установочного каталога или на msdn site

Существует хорошая книга Криса Смита «Программирование F #» с главой под названием «Котировка» :)

Так, в конце концов, просто попробуйте написать простой парсер:

open Microsoft.FSharp.Quotations 
open Microsoft.FSharp.Quotations.Patterns 
open Microsoft.FSharp.Quotations.DerivedPatterns 

let rec getGraph (expr: Expr) = 
    let parse args = 
    List.fold_left (fun acc v -> acc^(if acc.Length > 0 then "," else "")^getGraph v) "" args 
    let descr s = function 
    | Some v -> "(* instance "^s^"*) "^getGraph v 
    | _ -> "(* static "^s^"*)" 
    match expr with 
    | Int32 i -> string i 
    | String s -> sprintf "\"%s\"" s 
    | Value (o,t) -> sprintf "%A" o 
    | Call (e, methodInfo, av) -> 
    sprintf "%s.%s(%s)" (descr "method" e) methodInfo.Name (parse av) 
    | PropGet(e, methodInfo, av) -> 
    sprintf "%s.%s(%s)" (descr "property" e) methodInfo.Name (parse av) 
    | _ -> failwithf "I'm don't understand such expression's form yet: %A" expr 

PS И, конечно, вам понадобится некоторый код для перевода AST в читаемый человеком формат.

+0

fyi - эти примеры кода устарели не будут компилироваться против F # 2.0+ (List.fold_left теперь List.fold, PropGet теперь является PropertyGet, а строка concat (^) ocaml-типа создает предупреждения. –

3

Я не уверен, что положение вещей было, когда вы задавали этот вопрос, но сегодня вы можете преобразовать F # Котировку к экспрессии с помощью PowerPack, как так:

<@ "asdf".Length @>.ToLinqExpression() 

Кроме того, у меня есть разрабатывает библиотеку Unquote, которая способна декомпилировать многие котировки F # в однострочный синтаксический код без строки. Он может легко обрабатывать простые выражения экземпляра PropertyGet как ваш необходимый вход/выход:

> decompile <@ "asdf".Length @>;; 
val it : string = ""asdf".Length" 

Смотрите мой answer на аналогичный вопрос для получения дополнительной информации или просто посетить домашнюю страницу Unquote в.