如何在F#中提前退出/中断/停止数组创建(在本例中为Array2D.initBased
)?
备注: dic
是Dictionary<,>()
,其值是一个对象,其方法名为someMethod
,需要两个int
参数。< / p>
let arr = Array2D.initBased 1 1 width height (fun x y ->
let distinctValues = dic |> Seq.map (fun (KeyValue(k,v)) -> v.someMethod x y) |> Set.ofSeq
match distinctValues.count with
| dic.Count ->
// do something
// exit array creation here, because I do not need arr any more if v.someMethod x y produced distinct values for each dic value
| _ ->
// do something else
答案 0 :(得分:2)
这是一个棘手的问题 - 我认为没有任何功能可以让你轻松地做到这一点。我认为最好的选择可能是定义你自己的高阶函数(使用非常优雅的递归实现)来隐藏行为。
这个想法是定义行为为tryInitBased
的{{1}},但用户提供的函数可以返回选项(表示失败),函数返回选项(成功创建数组或{{1 }}):
initBased
然后,您可以保持代码几乎相同,但将None
替换为/// Attempts to initialize a 2D array using the specified base offsets and lengths.
/// The provided function can return 'None' to indicate a failure - if the initializer
/// fails for any of the location inside the array, the construction is stopped and
/// the function returns 'None'.
let tryInitBased base1 base2 length1 length2 f =
let arr = Array2D.createBased base1 base2 length1 length2 (Unchecked.defaultof<_>)
/// Recursive function that fills a specified 'x' line
/// (returns false as soon as any call to 'f' fails, or true)
let rec fillY x y =
if y < (base2+length2) then
match f x y with
| Some v ->
arr.[x, y] <- v
fillY x (y + 1)
| _ -> false
else true
/// Recursive function that iterates over all 'x' positions
/// and calls 'fillY' to fill individual lines
let rec fillX x =
if x < (base1+length1) then
if fillY x base2 then fillX (x + 1)
else false
else true
if fillX base1 then Some arr else None
并从lambda函数返回initBased
或tryInitBased
。
我还将功能发布到F# snippets,格式更精确。