gpt4 book ai didi

reflection - F# 可变到不可变

转载 作者:行者123 更新时间:2023-12-01 03:00:38 25 4
gpt4 key购买 nike

Gday所有,

我最近一直在涉足一些 F#,我想出了以下从一些 C# 代码移植过来的字符串构建器。只要它传递属性中定义的正则表达式,它就会将对象转换为字符串。对于手头的任务来说,这可能是矫枉过正,但出于学习目的。

目前,BuildString 成员使用可变字符串变量 updatedTemplate。我一直在绞尽脑汁想出一种没有任何可变对象的方法,但无济于事。这让我想到了我的问题。

是否可以在没有任何可变对象的情况下实现 BuildString 成员函数?

干杯,

迈克尔

//The Validation Attribute
type public InputRegexAttribute public (format : string) as this =
inherit Attribute()
member self.Format with get() = format

//The class definition
type public Foo public (firstName, familyName) as this =
[<InputRegex("^[a-zA-Z\s]+$")>]
member self.FirstName with get() = firstName

[<InputRegex("^[a-zA-Z\s]+$")>]
member self.FamilyName with get() = familyName

module ObjectExtensions =
type System.Object with
member this.BuildString template =
let mutable updatedTemplate : string = template
for prop in this.GetType().GetProperties() do
for attribute in prop.GetCustomAttributes(typeof<InputRegexAttribute>,true).Cast<InputRegexAttribute>() do
let regex = new Regex(attribute.Format)
let value = prop.GetValue(this, null).ToString()
if regex.IsMatch(value) then
updatedTemplate <- updatedTemplate.Replace("{" + prop.Name + "}", value)
else
raise (new Exception "Regex Failed")
updatedTemplate

open ObjectExtensions
try
let foo = new Foo("Jane", "Doe")
let out = foo.BuildInputString("Hello {FirstName} {FamilyName}! How Are you?")
printf "%s" out
with | e -> printf "%s" e.Message

最佳答案

我认为您总是可以将“仅具有一种效果(改变局部变量)的序列上的 for 循环”转换为摆脱可变的代码;这是一般转换的示例:

let inputSeq = [1;2;3]

// original mutable
let mutable x = ""
for n in inputSeq do
let nStr = n.ToString()
x <- x + nStr
printfn "result: '%s'" x

// immutable
let result =
inputSeq |> Seq.fold (fun x n ->
// the 'loop' body, which returns
// a new value rather than updating a mutable
let nStr = n.ToString()
x + nStr
) "" // the initial value
printfn "result: '%s'" result

您的特定示例具有嵌套循环,因此这是一个分两步显示相同类型机械变换的示例:
let inputSeq1 = [1;2;3]
let inputSeq2 = ["A";"B"]

let Original() =
let mutable x = ""
for n in inputSeq1 do
for s in inputSeq2 do
let nStr = n.ToString()
x <- x + nStr + s
printfn "result: '%s'" x

let FirstTransformInnerLoopToFold() =
let mutable x = ""
for n in inputSeq1 do
x <- inputSeq2 |> Seq.fold (fun x2 s ->
let nStr = n.ToString()
x2 + nStr + s
) x
printfn "result: '%s'" x

let NextTransformOuterLoopToFold() =
let result =
inputSeq1 |> Seq.fold (fun x3 n ->
inputSeq2 |> Seq.fold (fun x2 s ->
let nStr = n.ToString()
x2 + nStr + s
) x3
) ""
printfn "result: '%s'" result

(在上面的代码中,我使用了名称 'x2' 和 'x3' 来使范围更加明显,但您可以在整个过程中使用名称 'x'。)

尝试对您的示例代码进行相同的转换并发布您自己的答案可能是值得的。这不一定会产生最惯用的代码,但可以作为将 for 循环转换为 Seq.fold 调用的练习。

(也就是说,在这个例子中,整个目标主要是一个学术练习——带有可变代码的代码“很好”。)

关于reflection - F# 可变到不可变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/891549/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com