rwallace
rwallace

Reputation: 33395

Short syntax for trace with caller info

I'm looking for a way, in F#, to print a value together with source file and line number; it's intended for semi-interactive debugging, so the syntax needs to be short.

https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/caller-information provides a partial solution. The code on that page can be called like:

Tracer().DoTrace "foo"

and I'm looking for

trace "foo"

But of course, wrapping the above in a trace function will report trace being always the caller, which defeats the purpose.

I tried let inline trace ... but that didn't make any difference.

I would try using a macro if F# had such, but it doesn't.

What's the best way, by modifying the above linked code or otherwise, to obtain trace functionality with the shortest possible caller syntax?

Upvotes: 5

Views: 94

Answers (1)

Brian Berns
Brian Berns

Reputation: 17038

Opening a type exposes all accessible static members of the type, so I think this does what you want:

open System.Runtime.CompilerServices
open System.Runtime.InteropServices

type Tracer() =
    static member trace(message: string,
                [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string,
                [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string,
                [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) =
        printfn $"Message: {message}"
        printfn $"Member name: {memberName}"
        printfn $"Source file path: {path}"
        printfn $"Source line number: {line}"

open type Tracer

[<EntryPoint>]
let main _ =
    trace "foo"
    0

Output is:

Message: foo
Member name: main
Source file path: ...\Program.fs
Source line number: 18

Alternatively, you can automatically open the type if you want, so the caller doesn't have to explicitly open it:

[<AutoOpen>]
type Tracer() =
    static member trace(message: string,
                [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string,
                [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string,
                [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) =
        printfn $"Message: {message}"
        printfn $"Member name: {memberName}"
        printfn $"Source file path: {path}"
        printfn $"Source line number: {line}"

[<EntryPoint>]
let main _ =
    trace "foo"
    0

Upvotes: 8

Related Questions