F#短路模式匹配

jam*_*o00 5 .net f# functional-programming visual-studio

F#的新手.以下问题可能毫无意义.

// an attempt at Huffman encoder 
let encodeValue x y = function ...

match ((encodeValue left value), (encodeValue right value)) with
    | ((true, encoded), (_, _)) -> (true, encoded + "1")
    | ((_, _), (true, encoded)) -> (true, encoded + "0")
    | ((false, _), (false, _)) -> (false, "")
    | _ -> failwith "Error"
Run Code Online (Sandbox Code Playgroud)

在真实环境中,encodeValue可能非常昂贵.是否有可能(或合理)要求F#先评估encodeValue left value,尝试匹配,然后encodeValue right value在必要时执行?

Ste*_*sen 4

您可以使用惰性值和活动模式很好地模拟短路:

//not sure why function Lazy.force is recognized in VS but not in FSI
//need to use member Force()
let (|Force|) (l:Lazy<_>) =
    l.Force()

let encodeValue x y = function ...

match (encodeValue left value), lazy(encodeValue right value) with
    | (true, encoded), _                    -> (true, encoded + "1")
    | _              , Force(true, encoded) -> (true, encoded + "0")
    | (false, _)     , Force(false, _)      -> (false, "")
    | _                                     -> failwith "Error"
Run Code Online (Sandbox Code Playgroud)

Lazy值被计算 0 或 1 次:如果你从不调用Force()它们,它们将永远不会被计算。当您第一次调用时,系统Force()会计算它们,并为您以后每次调用时保存结果Force()

(|Force|)这是一个完整的活动模式,一个非常简洁的功能,它允许您实现各种自定义模式匹配结构。

请注意,@Brian 指出,您需要_在可能发生短路的惰性值位置使用。如果(true, encoded)匹配,则永远不会强制执行惰性且昂贵的计算。然后,对于每种其他情况,使用(|Force|)活动模式的多个匹配将仅使用第一个事件的结果。

更新

@Daniel 指出 F# 已经有一个活动模式,它的作用正是(|Force|)http ://msdn.microsoft.com/en-us/library/ee340223.aspx

  • @Stephen:[这样的活动模式](http://msdn.microsoft.com/en-us/library/ee340223.aspx)是内置的。 (2认同)