F#如何将函数变量传递给成员函数
给定具有多个字段的类型(候选人),可以评分(这里是一个带有_scoreXXX的具体示例)并计算总百分比分数:F#如何将函数变量传递给成员函数,f#,F#,给定具有多个字段的类型(候选人),可以评分(这里是一个带有_scoreXXX的具体示例)并计算总百分比分数: type ScorableCandidate() = let mutable _scoreXXX: int = 0 ; let mutable _percentXXX: float = 0. ; member this.scoreXXX with get() = _scoreXXX and set(v) =
type ScorableCandidate() =
let mutable _scoreXXX: int = 0 ;
let mutable _percentXXX: float = 0. ;
member this.scoreXXX
with get() = _scoreXXX
and set(v) =
_scoreXXX<- v
propertyChanged.Trigger(this, new PropertyChangedEventArgs("scoreXXX"))
member this.percentXXX
with get() = _percentXXX
and set(v) =
_percentXXX <- v
propertyChanged.Trigger(this, new PropertyChangedEventArgs("percentXXX"))
我的一个想法是传入函数以获取访问权限,这对于getter来说很容易做到,但我似乎无法理解setter。我意识到我可以对此进行反思——但我觉得这可能不是最好的方式。。。在这一点上,我处于:
let scoreField (accessF : (ScorableCandidate -> int)) (setF : (float -> unit)) =
let totalScore = List.fold (fun acc (candidate: ScorableCandidate) -> acc + accessF candidate) 0 brokers
let score (candidate: ScorableCandidate) =
setF <| (accessF candidate |> float) / float totalScore * 100.
if totalScore > 0 then
List.iter score <| brokers
scoreField (fun c -> c.scoreXXX) (fun f -> ())
let scoreField(accessF:(ScorableCandidate->int))(setF:(float->unit))=
让totalScore=List.fold(有趣的acc(候选人:ScorableCandidate)->acc+accessF候选人)0
得分(候选人:可评分候选人)=
setF浮动)/浮动总分*100。
如果totalScore>0,则
List.iter分数c.scoreXXX)(乐趣f->())
但我不知道如何(或者是否可能)将setter表示为类型上的lambda函数(可能我可以将instace作为parameter传递给lambda函数并以某种方式调用它)
想法?谢谢
更新发现了这种方法(想法):
为了使API更简单,您可能需要考虑以下选项之一:
scoreField“XXX”
,并且您的方法可以显式地将get\u scoreXXX
和set\u percentXXX
方法的“XXX”转换为MethodInfo
s。这样做的缺点是,它在编译时不检查方法名,并且会伴随反射而带来性能损失scoreField c.scoreXXX,c.percentXXX@>
。这与反射示例的工作原理类似,只是需要进行更多的编译时检查ScorePercent
类可以为分数和百分比设置getter和setter(并发出自己的更改通知)。然后,您可以执行scoreField(func->c.XXX)
,其中XXX
成员的类型为ScorePercent
你在正确的轨道上,但是你的设置器缺少你要设置场的对象。因此
setF
的类型应为:
setF : (ScorableCandidate -> float -> unit)
那么你会像这样使用它:
let score (candidate: ScorableCandidate) =
(setF candidate) <| (accessF candidate |> float) / float totalScore * 100.
因此,如果我理解正确,您需要在一个候选人中存储多个分数(对于各种不同的事情),然后对这些分数进行计算
在这种情况下,我会考虑把<代码>分数>代码>一个单独的类型,供考生使用,然后你可以轻松地添加多个分数。如果您需要使用
IPropertyChange
将分数和百分比作为候选人和通知的直接属性公开,那么您应该能够编写如下内容:
/// Takes a name of this score item (e.g. XXX) and a
/// function to trigger the property changed event
type Score(name:string, triggerChanged) =
let mutable score = 0
let mutable percent = 0.0
member x.Score
with get() = score
and set(v) =
score <- v
triggerChanged("Score" + name)
member x.Percent
with get() = percent
and set(v) =
percent <- v
triggerChanged("Percent" + name)
现在,您的参数化函数只需获取一个函数,该函数接受ScorableCandidate
,并返回一个Score
对象:
let scores f =
let totalScore = List.fold (fun acc (candidate: ScorableCandidate) ->
let so = f candidate // Get 'Score' object
acc + so.Score) 0 brokers
let score (candidate: ScorableCandidate) =
let so = f candidate // Get 'Score' object
so.Percent <- (float so.Score) / float totalScore * 100.0
if totalScore > 0 then
List.iter score <| brokers
这使得调用
Score
函数尽可能容易,而且它也是一种可扩展的解决方案,可以轻松地将其他计算添加到Score
对象中。缺点(例如,与Pavel的直截了当的解决方案相比)是设计Score
类型需要更多的工作(但是,如果只需要在类中直接公开可读属性,那么在ScorableCandidate
中声明新的分数就可以说更容易了,我认为这应该足够了).也许我不清楚,我花了一段时间来决定如何表达这个问题,如果我有误导性,我的应用程序。我希望能够将其参数化,这样scoreXXX只是其中一个选项——那里的逻辑(用于评分)可以分散运行在类的多个属性上,而无需专门为其编码。scoreXXX或scoreYYY或scoreZZZ或scoreXYZ等都是不同的成员,我可能想在…@akaphenom上运行此功能-我编辑了我的答案,为您提供了一些其他选项。谢谢。与Pavel Minaev提供的解决方案相比,使用引号有什么好处?@akaphenom-只是打字稍微少一点。@akaphenom:它写得稍微短一些,尽管它让我知道了如何重写我自己的答案:)选择这个解决方案-因为我只开发了一个原型,这很有效。我认为它们都是有效的方法,正如Tomas提到的,重新设计对象层可能是一个更好的计划,但我受到现有RPC层的限制,这在我这方面是不允许的。谢谢大家
scoreField (fun c -> c.scoreXXX) (fun c f -> c.percentXXX <- f)
/// Takes a name of this score item (e.g. XXX) and a
/// function to trigger the property changed event
type Score(name:string, triggerChanged) =
let mutable score = 0
let mutable percent = 0.0
member x.Score
with get() = score
and set(v) =
score <- v
triggerChanged("Score" + name)
member x.Percent
with get() = percent
and set(v) =
percent <- v
triggerChanged("Percent" + name)
type ScorableCandidate() as this =
// Create trigger function & pass it to Score objects
let trigger n = propertyChanged.Trigger(this, n)
let infoXxx = new Score("Xxx", trigger)
member this.InfoXxx = scoreXxx // Exposes the whole Score object
member this.ScoreXxx = scoreXxx.Score // & individual...
member this.PercentXxx = scoreXxx.Percent // ...properties
let scores f =
let totalScore = List.fold (fun acc (candidate: ScorableCandidate) ->
let so = f candidate // Get 'Score' object
acc + so.Score) 0 brokers
let score (candidate: ScorableCandidate) =
let so = f candidate // Get 'Score' object
so.Percent <- (float so.Score) / float totalScore * 100.0
if totalScore > 0 then
List.iter score <| brokers
scores (fun (c:ScorableCandidate) -> c.InfoXxx)