【问题标题】:F# - while woes given tuple conditionF# - 给定元组条件时出现问题
【发布时间】:2008-10-02 08:29:48
【问题描述】:

鉴于以下情况:

#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”转换为序列表达式?

【问题讨论】:

  • 你能描述你试图解决的问题,而不是引用一个不起作用的解决方案吗?

标签: f#


【解决方案1】:

这是一种解决方案,但我个人认为这是滥用 while 构造。

#light
while 
   (let (c,x) = foo()
    if c then print_any !x
    c)
   do ()

【讨论】:

    【解决方案2】:

    我认为另一种解决方案稍微好一些。它将 x 移出 while 的条件子句范围,并将其放入更高范围内可用的引用 y 中。仍然不是最好的(功能性)解决方案,但它确实有效。

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

    我认为您的rec loop 解决方案效果最好,因为它是最实用的解决方案(避免副作用,尽管 foo 使用状态)和最通用的解决方案(它与 foo 同时适用于所有功能)。它的输入时间更长,但是如果您将使用更多像 foo 这样的函数,那么循环比仅用于 foo 的单个最短解决方案更有效率。

    我什至会更多地概括循环,并抽象出你想在“真实”情况下对值执行的操作:

    let loop f a = 
       let rec loop2() = 
          match f() with
          | (true, x) ->
             a x
             loop2()
          | (false, _) -> ()
       loop2()
    
    loop foo print_any
    

    【讨论】:

      【解决方案3】:

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

      在我看来,“foo”的代码很臭。如果按照以下方式将“foo”转换为“bar”是合理的

      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”虽然好一些,但仍然看起来很可疑。 (在“bar”中,我保留了它返回“int ref”而不仅仅是“int”的奇怪方面,就像“foo”所做的那样,但希望那个方面是无意的?)

      我认为“foo”最奇怪的地方是那种从数据类型中不明显的隐含信息(只要 bool 部分为真,你就可以继续调用它),这就是 seq版本更有吸引力。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-07-21
        • 1970-01-01
        • 1970-01-01
        • 2022-11-30
        • 2019-02-28
        • 2011-04-13
        • 2011-09-05
        • 2020-05-10
        相关资源
        最近更新 更多