Как получить название переменной, войдя в функцию как в параметр с помощью F#?

Есть ли какой-либо путь в F#, как добраться, название переменной передало в функцию?

Пример:

let velocity = 5
let fn v = v.ParentName
let name = fn velocity // this would return "velocity" as a string

Заранее спасибо

Править:

Почему этот код не работает? Это подобрано как значение, таким образом, я не могу получить "переменное" имя.

type Test() =
  let getName (e:Quotations.Expr) =
    match e with
      | Quotations.Patterns.PropertyGet (_, pi, _) -> pi.Name + " property"
      | Quotations.Patterns.Value(a) -> failwith "Value matched"
      | _ -> failwith "other matched"
  member x.plot v = v |> getName |> printfn "%s"

let o = new Test()

let display () =
  let variable = 5.
  o.plot <@ variable @>

let runTheCode fn = fn()

runTheCode display
6
задан Oldrich Svec 3 May 2010 в 06:46
поделиться

2 ответа

Для завершения ответа Марсело, да, вы можете использовать цитаты для этой задачи:

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

let velocity = 5

let fn (e:Expr) =
  match e with
    | PropertyGet (e, pi, li) -> pi.Name
    | _ -> failwith "not a let-bound value"

let name = fn <@velocity@> 

printfn "%s" name

Как вы можете видеть в коде, F # позволяет ограничивать верхние значения определения (функции или переменные) реализуются как свойства класса.

Я больше не могу найти ссылку, которая показывает, как часть кода F # может быть функционально переписана с помощью C #. Глядя на код, становится очевидно, зачем вам нужен шаблон PropertyGet .

Теперь, если вы хотите также оценить выражение, вам нужно будет установить F # powerpack и ссылку FSharp.PowerPack.Linq в вашем проекте.

Он добавляет метод EvalUntyped в класс Expr ..

open Microsoft.FSharp.Linq.QuotationEvaluation

let velocity = 5

let fn (e:Expr) =
  match e with
    | PropertyGet (eo, pi, li) -> pi.Name, e.EvalUntyped
    | _ -> failwith "not a let-bound value"

let name, value = fn <@velocity@> 

printfn "%s %A" name value

Если вам нужно сделать это для метода экземпляра, вот как я это сделаю:

let velocity = 5

type Foo () =
  member this.Bar (x:int) (y:single) = x * x + int y

let extractCallExprBody expr =
  let rec aux (l, uexpr) =
    match uexpr with
     | Lambda (var, body) -> aux (var::l, body)
     | _ -> uexpr
  aux ([], expr)

let rec fn (e:Expr) =
  match e with
    | PropertyGet (e, pi, li) -> pi.Name
    | Call (e, mi, li) -> mi.Name
    | x -> extractCallExprBody x |> fn
    | _ -> failwith "not a valid pattern"

let name = fn <@velocity@> 
printfn "%s" name

let foo = new Foo()

let methodName = fn <@foo.Bar@>
printfn "%s" methodName

Чтобы вернуться к фрагменту кода, показывающему использование EvalUntyped , вы можете добавить явное параметр типа для Expr и понижающего преобразования (:?> ), если вы хотите / должны сохранить безопасность типов:

let fn (e:Expr<´T>) = //using ´ instead of ' to avoid colorization screw-up
  match e with
    | PropertyGet (eo, pi, li) -> pi.Name, (e.EvalUntyped() :?> ´T)
    | _ -> failwith "not a let-bound value"

let name, value = fn <@velocity@> //value has type int here
printfn "%s %d" name value
11
ответ дан 9 December 2019 в 20:40
поделиться

Вы можете добиться этого с помощью цитат кода:

let name = fn <@ velocity @>

В функцию fn будет передан объект Expr , который необходимо преобразовать в Quotations.Var. (что будет только в том случае, если вы передадите одну переменную) и извлеките член экземпляра Name .

1
ответ дан 9 December 2019 в 20:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: