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

2

4

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

how can the nameof function used or extended for the following case?

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 "!"

let s = _nameof <@ System.Char.IsControl @> //OK

type A<'a>() = 
    static member MethodWith2Pars(guid:Guid, str:string) = ""
    static member MethodWith2Pars(guid:Guid, ba:byte[]) = ""

let s1 = nameof <@ A<_>.MethodWith2Pars @> //Error  FS0503  A member or object constructor 'MethodWith2Pars' taking 1 arguments is not accessible from this code location. All accessible versions of method 'MethodWith2Pars' take 2 arguments
let s2 = nameof <@ A<_>.MethodWith2Pars : Guid * string -> string @> //Same error

The compiler gives the following error:

Error FS0503 A member or object constructor 'MethodWith2Pars' taking 1 arguments is not accessible from this code location. All accessible versions of method 'MethodWith2Pars' take 2 arguments

Quoit answered 3/12, 2020 at 3:0 Comment(0)
H
6

The answer you linked is a bit outdated. F# 5.0 (released just recently) offers the true nameof feature. See the announcement: https://devblogs.microsoft.com/dotnet/announcing-f-4-7/#nameof

This feature also existed in preview since F# 4.7: https://devblogs.microsoft.com/dotnet/announcing-f-4-7/#nameof

Huckleberry answered 3/12, 2020 at 3:27 Comment(1)
I am aware of that, but it doesn't work in this case. I mean, 'nameof A<_>.MethodWith2Pars' doesn't work with error FS3250: Expression does not have a name. 'nameof A.MethodWith2Pars' fails with a different errorQuoit
E
3

You can write your code like this:

open System

type A() = 
    static member MethodWith2Pars(guid:Guid, str:string) = ""
    static member MethodWith2Pars(guid:Guid, ba:byte[]) = ""

let s1 = nameof (A.MethodWith2Pars : Guid * byte[] -> string)
let s2 = nameof (A.MethodWith2Pars : Guid * string -> string)

The type annotation is needed due to overloading. Not sure why there is a generic type parameter on the class declaration, but it's not used anywhere so I just removed it.

Eran answered 3/12, 2020 at 6:5 Comment(2)
Unfortunately the generic type is required (the code I put here is a simplification of what I have) . Let's suppose that A is instead :: type A<'a>() = static member MethodWith2Pars(guid:Guid, str:string) = "" static member MethodWith2Pars(guid:Guid, ba:byte[]) = A<_>.P static member val P = Unchecked.defaultof<'a> with get, setQuoit
Okay, I see. That would either be a bug or a by-design quirk in the feature, since it resolves a name the same way as other code. If you need to use nameof, I suggest rewriting your code a bit in the interim.Eran

© 2022 - 2024 — McMap. All rights reserved.