你如何在F#中实现comefrom?

时间:2011-08-24 15:45:58

标签: f# comefrom

我已经习惯了implementing goto控制流的F#方式,但我不太确定如何处理comefrom,la INTERCAL

comefrom是一个非常有用的结构,允许您从标签跳转。以下示例程序使用它来打印洗手的完整说明:

comefrom repeat
Console.Write "Lather"
Console.Write "Rinse"
repeat

comefrom的美妙之处在于你可以在多个地方贴上标签。

comefrom restart
Console.Write "Do you want to restart this program?"
let a = Console.ReadLine()
match a with
| "Y" -> restart
| _   -> Console.Write "Too bad! It will restart whether you like it or not!"
         restart

我尝试了这两个程序,但反复无常的F#编译器决定让我失望。如何利用F#中的comefrom

3 个答案:

答案 0 :(得分:5)

这非常接近您想要的语法。

let comefrom f = 
  let rec g = (fun () -> f g)
  f g

comefrom (fun restart ->
  Console.Write "Do you want to restart this program?"
  let a = Console.ReadLine()
  match a with
  | "Y" -> restart()
  | _   -> Console.Write "Too bad! It will restart whether you like it or not!"
           restart())

一旦你绕过一个函数f,接受一个函数g,它本身被传递给f,它就相对简单了。

将INTERCAL代码迁移到F#很难。这有望减少所涉及的工作。

答案 1 :(得分:3)

let rec restart() =
    Console.Write "Do you want to restart this program?"
    let a = Console.ReadLine()
    match a with
    | "Y" -> restart()
    | _   -> Console.Write "Too bad! It will restart whether you like it or not!"
             restart()

答案 2 :(得分:3)

我认为comefrom对应的函数声明甚至比goto更好。

  

如果您在F#中执行类似goto的操作,那么您的标签对应于函数声明,goto命令对应于函数调用。在comefrom的情况下,comefrom命令对应于函数声明,标签对应于函数调用。

使用函数,您的代码看起来像这样(编辑: 这与Ramon已发布的内容相同,但我会在这里保留答案,因为它有其他解释< / em>的):

let rec restart() =
  Console.Write "Do you want to restart this program?"
  let a = Console.ReadLine()
  match a with
  | "Y" -> restart()
  | _   -> Console.Write "Too bad! It will restart whether you like it or not!"
           restart()

如果您真的想使用类似comefrom命令的语法,请查看下面的选项。但是,我并没有真正看到这一点 - 如果你正在调整一些遗留代码,那么你将不得不将许多其他东西翻译成F#,并且使用一种奇怪的语法只会使F#不那么惯用。无法向F#添加新的真正的语法结构,如comefrom

let rec restart = comefrom (fun () ->
  Console.Write "Do you want to restart this program?"
  // (omitted)
  restart())

// where 'comefrom' is just a trivial wrapper for a function
let comefrom f () = f ()

或者,您可以定义comefrom计算构建器,然后使用以下语法:

let rec restart = comefrom {
  Console.Write "Do you want to restart this program?"
  // (omitted)
  return! restart() }

(这个blog post给出了一个非常简单的计算构建器示例,可以适应)