Is there an equivalent of C#'s nameof(..) in F#?
Asked Answered
F

1

20

I have the following lines of code I want to port from C# to F#:

private const string TypeName = nameof(MyClass);
private const string MemberName = nameof(MyClass.MyMember);

The value of TypeName then is "MyClass" and the value of MemberName then is "MyMember". What do I have to write in F#?

Femur answered 17/1, 2018 at 15:19 Comment(2)
Looks like it is still being implemented - F# RFC FS-1003 - nameof Operator. See also Discussion threadAvalanche
nameof is a preview feature starting with F# 4.7Enarthrosis
A
23

As of F# 4.7, there is a nameof operator:

let months =
    [
        "January"; "February"; "March"; "April";
        "May"; "June"; "July"; "August"; "September";
        "October"; "November"; "December"
    ]

let lookupMonth month =
    if (month > 12 || month < 1) then
        invalidArg (nameof month) ($"Value passed in was %d{month}.")

    months.[month-1]

printfn "%s" (lookupMonth 12)
printfn "%s" (lookupMonth 1)
printfn "%s" (lookupMonth 13)

As mentioned in the comments, a proper nameof operator is work in progress.

In the meantime, you can use F# quotations (similar to C# expression trees) to implement similar functionality - it is a bit uglier and requires some discipline (you need to put actual member access in the quotation), but it at least checks that the member exists and prevents typos:

open Microsoft.FSharp.Quotations

let nameof (q:Expr<_>) = 
  match q with 
  | Patterns.Let(_, _, DerivedPatterns.Lambdas(_, Patterns.Call(_, mi, _))) -> mi.Name
  | Patterns.PropertyGet(_, mi, _) -> mi.Name
  | DerivedPatterns.Lambdas(_, Patterns.Call(_, mi, _)) -> mi.Name
  | _ -> failwith "Unexpected format"

let any<'R> : 'R = failwith "!"

The any definition is just a generic value that you can use to refer to instance members:

nameof <@ any<System.Random>.Next @>
nameof <@ System.Char.IsControl @>
Amory answered 17/1, 2018 at 23:47 Comment(3)
That looks like a genuine approach, but I think I will have to wait for the nameof operator to be implemented because I need the result to be a compile time constant ( want to use it as an argument for a atttribution). Moreover, am I right that I can only get names of members, but not of types?Femur
@Femur - You're right, this is not compile-time constant and you can only get member names (for type names, you'd probably just want typeof<System.Random>.Name, but that's the same as in C# - having nameof would make that nicer!)Amory
@TomasPetricek Please see #65119770Patsy

© 2022 - 2024 — McMap. All rights reserved.