2015-04-13 3 views
4

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

let funName f: string = 
    // returns the name of f. 

Например, если я прохожу printfn в качестве аргумента funName, он возвращает "printfn".

> funName printfn;; 
val it : string = "printfn" 

EDIT: Я хотел бы написать функцию, которая возвращает doc документацию XML, связанные с данной функцией.

let doc f = // returns the XML documentation of the function `f`. 

Чтобы получить краткую информацию о функции, используя что-то вроде NuDoq, я хотел бы знать имя функции.

+2

Что вы на самом деле пытаетесь для того чтобы достигнуть здесь - в F # с каррированием это может быть сложным. –

+0

Возможно, что-то похожее на [CallerMemberNameAttribute] (http://stackoverflow.com/questions/14117842/is-it-possible-to-use-callermembernameattribute-in-f)? Вероятно, ОП видел это, но я добавлю в качестве примечания (см. Третий комментарий Nikon). – Veksi

ответ

7

Я не могу представить, почему вы хотели бы это сделать, и я не думаю, что есть способ сделать это с отражением, но F# Code Quotations может оказаться вам на полпути.

open Microsoft.FSharp.Quotations 

let rec funName = function 
| Patterns.Call(None, methodInfo, _) -> methodInfo.Name 
| Patterns.Lambda(_, expr) -> funName expr 
| _ -> failwith "Unexpected input" 

let foo() = 42 
funName <@ foo @>  // "foo" 

Но обратите внимание, что определенные предопределенные библиотечные функции имеют расходящееся внутреннее имя.

funName <@ printfn @> // "PrintFormatLine" 
funName <@ id @>  // "Identity" 
+2

В одном случае я регулярно сталкиваюсь с тем, где я использую нечто подобное при реализации '' INotifyPropertyChanged''. Я абсолютно презираю необходимость возвращать строки. –

+1

Какова производительность накладных расходов в F #? – FuleSnabel

2

Обратите внимание, что по состоянию на F # 4.0, типы классов могут автоматически цитировать свои аргументы, упрощая сайт вызова по сравнению с ответом kaefer «s:

open Microsoft.FSharp.Quotations 

type DocumentGetter = 
    static member GetName([<ReflectedDefinition>]x:Expr<_->_>) = 
     match x with 
     | DerivedPatterns.Lambdas(_, Patterns.Call(_,methodInfo,_)) -> 
      methodInfo.Name 

let f x y = x + y 

DocumentGetter.GetName f 
Смежные вопросы