Functional programming 提取变量的名称
我们如何在F#中构建一个输出传入变量名称的函数?例如:Functional programming 提取变量的名称,functional-programming,f#,Functional Programming,F#,我们如何在F#中构建一个输出传入变量名称的函数?例如: let someVar1 = "x" getVarname someVar1 //output would be "someVar1" let someVar2 = "y" getVarname someVar2 //output would be "someVar2" let f toString = fun a -> printfn "%s: %d" (toString a) a let x = 1 f getVarname
let someVar1 = "x"
getVarname someVar1 //output would be "someVar1"
let someVar2 = "y"
getVarname someVar2 //output would be "someVar2"
let f toString = fun a -> printfn "%s: %d" (toString a) a
let x = 1
f getVarname x //output would be: "x: 1"
我在C#here()中发现了一个类似的问题,但我无法使它在F#中工作。实现的
名称在F#core中有运算符,但F#5编译器位尚未发布。
当它出现时,您可以使用它来获取符号的名称
let someVar1 = None
let name = nameof someVar1 // name = "someVar1"
现在,我们可能会滥用dynamic运算符来获取垫片,您最终可以用nameof
let name = ()
let (?) _ name = string name
用法:
let someVar1 = None
let name = name?someVar1
它读起来不太糟糕,而且你会有某种程度的自动完成
如果您真的希望能够在调用站点检索本地名称和值,可以使用引号
let printVar = function
| ValueWithName(value, _type, name) -> printfn "%s = %A" name value
| _ -> ()
不过使用起来有点吵
let someVar1 = 12
printVar <@ someVar1 @> //prints someVar1 = 12
让someVar1=12
printVar//打印someVar1=12
实现的名称在F#core中有运算符,但F#5编译器位尚未发布。
当它出现时,您可以使用它来获取符号的名称
let someVar1 = None
let name = nameof someVar1 // name = "someVar1"
现在,我们可能会滥用dynamic运算符来获取垫片,您最终可以用nameof
let name = ()
let (?) _ name = string name
用法:
let someVar1 = None
let name = name?someVar1
它读起来不太糟糕,而且你会有某种程度的自动完成
如果您真的希望能够在调用站点检索本地名称和值,可以使用引号
let printVar = function
| ValueWithName(value, _type, name) -> printfn "%s = %A" name value
| _ -> ()
不过使用起来有点吵
let someVar1 = 12
printVar <@ someVar1 @> //prints someVar1 = 12
让someVar1=12
printVar//打印someVar1=12
如果使用引号和静态方法,则可以使用ReflectedDefinition
属性在F#4中捕获变量的名称。以下示例中的Demo.GetVarName
静态方法返回用作参数的变量名称和值:
open Microsoft.FSharp.Quotations
type Demo =
static member GetVarName([<ReflectedDefinition(true)>] x:Expr<int>) =
match x with
| Patterns.WithValue(_, _, Patterns.ValueWithName(value, _, name)) ->
name, value :?> int
| _ -> failwithf "Argument was not a variable: %A" x
let test ()=
let yadda = 123
Demo.GetVarName(yadda)
test()
如果使用引号和静态方法,则可以使用ReflectedDefinition
属性捕获F#4中变量的名称。以下示例中的Demo.GetVarName
静态方法返回用作参数的变量名称和值:
open Microsoft.FSharp.Quotations
type Demo =
static member GetVarName([<ReflectedDefinition(true)>] x:Expr<int>) =
match x with
| Patterns.WithValue(_, _, Patterns.ValueWithName(value, _, name)) ->
name, value :?> int
| _ -> failwithf "Argument was not a variable: %A" x
let test ()=
let yadda = 123
Demo.GetVarName(yadda)
test()
你试过F#5的名字吗?我听说过这个函数,但我不知道如何在脚本中使用它。尽管我已经打开了Microsoft.FSharp.Core.Operators,但它一直显示错误(“未定义值或构造函数'nameof')。我正在使用Visual Studio Community 2019 16.5.3。您尝试过F#5的名称吗?我听说过这个函数,但我不知道如何在脚本中使用它。尽管我已经打开了Microsoft.FSharp.Core.Operators,但它一直显示错误(“未定义值或构造函数'nameof')。我正在使用Visual Studio Community 2019 16.5.3。非常感谢,Asti!但是假设我们有一个函数f getName=(fun a->printfn“%s:%d”(getName a)a),用户将其调用为f getName x(其中x是在某处定义的变量,等于1)。我希望得到“x:1”作为输出,而不是“a:1”。在这种情况下,我如何使用您的解决方案?使用nameof
也不可能nameof
将绑定到本地符号。谢谢!我编辑了我的问题并添加了上面提供的示例。我添加了一个替代解决方案。非常感谢,Asti!但是假设我们有一个函数f getName=(fun a->printfn“%s:%d”(getName a)a),用户将其调用为f getName x(其中x是在某处定义的变量,等于1)。我希望得到“x:1”作为输出,而不是“a:1”。在这种情况下,我如何使用您的解决方案?使用nameof
也不可能nameof
将绑定到本地符号。谢谢!我编辑了我的问题并添加了我上面提供的示例。我添加了一个替代解决方案。嗨,托马斯。谢谢你的解释!我使用下面的函数尝试了您的完整解决方案(包括PropertyGet):let f=fun a->sprintf“%s:%d”(a |>Demo.GetVarName |>fst)a;设x=1;f x。输出是“arg00:1”。问题是|>
操作符是内联的,因此编译器可能会看到类似(fun arg00->Demo.GetVarName(arg00))的东西。这只适用于直接调用,即Demo.GetVarName(a)
。在进行了您建议的更正后,现在我得到了“a:1”作为输出,而不是“x:1”。是否可以获取“x:1”@FRocha否,这不适用于封装在函数中的代码-它提供直接作为参数传递给Demo.GetVarName
的变量的名称。换句话说,如果你想定义一个方法,比如说Chart.Plot(无论什么)
来获取参数的变量名,你需要按照我的答案中所示的方式来定义它。嗨,Tomas。谢谢你的解释!我使用下面的函数尝试了您的完整解决方案(包括PropertyGet):let f=fun a->sprintf“%s:%d”(a |>Demo.GetVarName |>fst)a;设x=1;f x。输出是“arg00:1”。问题是|>
操作符是内联的,因此编译器可能会看到类似(fun arg00->Demo.GetVarName(arg00))的东西。这只适用于直接调用,即Demo.GetVarName(a)
。在进行了您建议的更正后,现在我得到了“a:1”作为输出,而不是“x:1”。是否可以获取“x:1”@FRocha否,这不适用于封装在函数中的代码-它提供直接作为参数传递给Demo.GetVarName
的变量的名称。换句话说,如果你想定义一个方法,比如说Chart.Plot(无论什么)
来获取参数的变量名,你需要按照我的答案中所示的方式来定义它。