代码之家  ›  专栏  ›  技术社区  ›  Torbjörn Gyllebring

F#-当给定元组条件时

f#
  •  -2
  • Torbjörn Gyllebring  · 技术社区  · 17 年前

    鉴于以下情况:

    #light
    //any function returning bool * 'a
    let foo =
        let x = ref 10
        fun () ->
            x := !x - 1
            if !x <> 0 then
                (true, x)
            else
                (false, x)
    
    while let (c,x) = foo() in c do print_any x;//can't access x, but would be convinent.
    
    //this is how I want it to work, without all the typing
    let rec loop f =
        match f() with
        | (true, x) ->
            print_any x
            loop f
        | (false, _) -> ()
    loop foo
    

    或者我应该把“foo”转换成序列表达式吗?

    3 回复  |  直到 17 年前
        1
  •  1
  •   Michiel Borkent    17 年前

    这是一个解决方案,但我个人认为这是对while构建的滥用。

    #light
    while 
       (let (c,x) = foo()
        if c then print_any !x
        c)
       do ()
    
        2
  •  1
  •   Michiel Borkent    17 年前

    另一个在我看来稍微好一点的解决方案。它从while的condition子句范围中获取x,并将其放入引用y中,该引用y在更高的范围中可用。仍然不是最好的(功能性)解决方案,但它可以工作。

    let y = ref 1
    while (let (c,x) = foo()
           y := !x
           c)
           do printf "%i" !y
    

    我想你的 rec loop

    我甚至会进一步概括循环,并抽象出在“真实”情况下您希望对值执行的操作:

    let loop f a = 
       let rec loop2() = 
          match f() with
          | (true, x) ->
             a x
             loop2()
          | (false, _) -> ()
       loop2()
    
    loop foo print_any
    
        3
  •  1
  •   Brian    17 年前

    我喜欢关于如何消费“foo”的其他建议,假设foo是固定的。

    let bar =    
        let x = ref 10    
        seq {
            x := !x - 1        
            while !x <> 0 do
                yield x
                x := !x - 1        
        }
    bar |> Seq.iter print_any
    

    然后我会这样做,但“酒吧”,虽然稍微好一点,仍然显得可疑。(在“bar”中,我保留了一个奇怪的方面,即它返回“intref”,而不是像“foo”那样只返回“int”,但希望这个方面是无意的?)

    我认为关于“foo”的有趣之处在于数据类型中不明显的隐式信息(只要bool部分为真,您可以继续调用它),这使得seq版本更具吸引力。