开发者

How do you implement comefrom in F#?

I've begun to be accustomed to the F# way of implementing goto control flow, but I'm not quite sure how I can han开发者_StackOverflow中文版dle comefrom, a la INTERCAL.

comefrom is a very useful construct that allows you to jump from a label. The following example program uses it to print the complete instructions for washing your hands:

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

The beauty of comefrom is that you can put a label in multiple places.

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

I tried both of these programs, but the capricious F# compiler decided to disappoint me. How can I take advantage of comefrom in F#?


This is pretty close to the syntax you want.

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

Once you wrap your head around a function, f, accepting a function, g, which itself is passed to f, it's relatively straightforward.

Migrating INTERCAL code to F# is hard. This hopefully should reduce the work involved.


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

?


I think that comefrom corresponds to function declarations even better than goto.

If you're doing something like goto in F#, then your label corresponds to function declaration and the goto command corresponds to function call. In case of comefrom, the comefrom command corresponds to function declaration and the label corresponds to function call.

Using functions, your code looks like this (EDIT: which is the same thing as what Ramon already posted, but I'll keep the answer here, because it has additional explanation):

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

If you really want to use syntax that resembles comefrom command then take a look at the options below. However, I don't really see the point - if you're adapting some legacy code, then you'll have to translate many other things to F# and using a weird syntax will just make F# less idiomatic. There is no way to add a new real syntactic construct like comefrom to F#.

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

Alternatively, you could define comefrom computation builder and then use the following syntax:

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

(This blog post gives a very simple example of computation builder that you could adapt)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜