Автоматическое определение имени функции в f # - PullRequest
0 голосов
/ 28 сентября 2018

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

namespace MyModuleNamespace
 module MyModule = 
 let AddTwoNums logger x y =
    logger.Info("MyModuleNamespace.AddTwoNums - Start")
    let res = x+y
    logger.Info("MyModuleNamespace.AddTwoNums - End")
    res

Есть ли способЯ могу автоматически определить, что такое «MyModuleNamespace.AddTwoNums», так как оно очень громоздко и подвержено ошибкам, особенно когда вам приходится переименовывать функции и модули во время рефакторинга кода

Даже если это невозможно, есть ли способЯ могу автоматически определить, что такое AddTwoNums, то есть имя функции?

Ответы [ 3 ]

0 голосов
/ 28 сентября 2018

Вероятно, не то, что вы хотите, но вы можете извлечь его с помощью цитат:

let x<'T> : 'T = Unchecked.defaultof<'T>
<@ AddTwoNums x x x@> 
|> function Microsoft.FSharp.Quotations.Patterns.Call(_,mi,_)-> mi.Name | _ -> "unknown"

Я предполагаю, что вы хотите посмотреть на получение трассировки стека: https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.stacktrace?view=netframework-4.7.2

0 голосов
/ 29 сентября 2018

Если вам не нужно фактическое имя пространства / имени модуля или вы хотите заменить его именем файла, существуют специальные атрибуты, которые инструктируют компилятор предоставлять соответствующие аргументы функции:

open System.Runtime.CompilerServices

type Logger =
    static member Trace(
                        msg: string,
                        [<CallerMemberName>] ?memberName: string,
                        [<CallerFilePath>] ?path: string,
                        [<CallerLineNumberAttribute>] ?line: int) =
        printfn "%s from %s.%s on line %i" msg path.Value memberName.Value line.Value

module Foo =
    let bar() =
        Logger.Trace("hello")

// hello from c:\path\to\Logging.fsx.bar on line 32
Foo.bar()

В MS Docs есть что сказать по поводу Информация о вызывающем абоненте .

Обратите внимание, что при запуске из fsi номер строки является точным только в первый раз.

0 голосов
/ 28 сентября 2018

Есть несколько способов сделать это, и я не уверен, что будет лучшим для вашего сценария.В прошлом я использовал один способ получения информации из трассировки стека:

let stackTrace = StackTrace()
let topFrame = stackTrace.GetFrame(0)
let currentFunction = topFrame.GetMethod()
printfn "%s.%s" currentFunction.DeclaringType.Name currentFunction.Name

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

let inline getCurrentFunction () =
    let stackTrace = StackTrace()
    let topFrame = stackTrace.GetFrame(0)
    let currentFunction = topFrame.GetMethod()
    sprintf "%s.%s" currentFunction.DeclaringType.Name currentFunction.Name
...