2

我已经开始习惯于 F#实现goto控制流的方式,但我不太确定如何处理comefrom比如 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# 编译器决定让我失望。如何comefrom在 F# 中利用?

4

3 回答 3

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# 很困难。这有望减少所涉及的工作。

于 2011-08-24T16:19:50.993 回答
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()

?

于 2011-08-24T15:53:10.963 回答
3

我认为这comefrom对应于函数声明甚至比goto.

如果你在 F# 中做类似的事情goto,那么你的标签对应于函数声明,goto命令对应于函数调用。在 的情况下comefromcomefrom命令对应于函数声明,标签对应于函数调用。

使用函数,您的代码看起来像这样(编辑: 这与 Ramon 已经发布的内容相同,但我将在此处保留答案,因为它有额外的解释):

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() }

(这篇文提供了一个非常简单的计算构建器示例,您可以使用它)

于 2011-08-24T16:01:10.837 回答