Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c#

f#

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#?

like image 935
David Avatar asked Jan 17 '18 15:01

David


People also ask

What is the alternative to class for C?

The closest thing you can get is a struct . There is a feature in C intended to facilitate a sort of pseudo-inheritance, but it doesn't come close to an actual object-oriented class system.

Are there Generics in C?

It allows efficient development without the need to incorporate or switch to C++ or languages with builtin template systems, if desired. Using generics and templates in C can also make programs more type safe, and prevent improper access of memory.

Is there a class in C?

C mostly uses functional/structural programming instead of implementing Object Oriented Programming as in languages like C++ , Java , Python etc. which use classes .

What is macro in C?

A macro is a piece of code in a program that is replaced by the value of the macro. Macro is defined by #define directive. Whenever a macro name is encountered by the compiler, it replaces the name with the definition of the macro. Macro definitions need not be terminated by a semi-colon(;).


1 Answers

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 @>
like image 136
Tomas Petricek Avatar answered Oct 25 '22 06:10

Tomas Petricek