在F#中,许多采用序列的函数都将序列作为支持流水线操作的最后一个参数.
在设计API时,我可以遵循这种趋势,就像在这个简单的状态机示例中一样:
type Transition = { CurrentState : string; TriggeringEvent : string; NewState : string } let getNewState currentState triggeringEvent transitions = let isMatch t = t.CurrentState = currentState && t.TriggeringEvent = triggeringEvent match transitions |> Seq.tryFind isMatch with | Some transition -> Some(transition.NewState) | None -> None let myTransitions = [ { CurrentState = "A"; TriggeringEvent = "one"; NewState = "B" }; { CurrentState = "B"; TriggeringEvent = "two"; NewState = "A" } ] let result = myTransitions |> getNewState "A" "one" printfn "%A" result
这里getNewState有签名:
(string -> string -> seq<Transition> -> string option)
它支持流水线操作:
myTransitions |> getNewState "A" "one"
但在某些情况下,序列是不变的,而其他参数则不同.在状态机示例中,对于给定的状态机,转换表(转换)将是固定的.将使用不同的状态和事件多次调用getNewState.如果序列是第一个参数,则调用者可以使用部分应用程序:
let getNewState transitions currentState triggeringEvent = // body same as before let stateMachine = getNewState myTransitions let result1 = stateMachine "A" "one" let result2 = stateMachine "B" "two" printfn "%A" result1 printfn "%A" result2
现在getNewState有签名:
(seq<Transition> -> string -> string -> string option)
和stateMachine签名:
(string -> string -> string option)
解决方法
流水线操作使用部分应用程序,它只是通过首先指定参数然后指定函数来调用函数的另一种方法.
myTransitions |> getNewState“A”“one”
这里首先部分地应用getNewState来获取具有一个param的函数,然后使用myTransitions调用该函数.
有一个函数可以具有不同的参数顺序但函数名仍然保持相同的方法是使用方法重载,即具有静态方法的类型但随后松开隐式部分应用程序,因为方法将参数作为单个元组.
最好坚持使用一个签名,并且调用者可以根据需要轻松创建另一个具有不同参数顺序的函数.例如,在第二个代码示例中,您可以将第一个示例的getNewState用作:
让stateMachine a b = getNewState a b myTransitions
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。