Как вы реализуете comefrom в F #? - PullRequest
2 голосов
/ 24 августа 2011

Я уже привык к F # способу реализации goto потока управления, но я не совсем уверен, как мне справиться с 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 # решил меня разочаровать. Как я могу воспользоваться comefrom в F #?

Ответы [ 3 ]

5 голосов
/ 24 августа 2011

Это довольно близко к желаемому синтаксису.

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 # затруднен.Надеюсь, это должно сократить объем работы.

3 голосов
/ 24 августа 2011

Я думаю, что comefrom соответствует объявлениям функций даже лучше, чем goto.

Если вы делаете что-то вроде goto в F #, то ваша метка соответствует объявлению функции икоманда goto соответствует вызову функции.В случае comefrom, команда comefrom соответствует объявлению функции, а метка соответствует вызову функции.

Используя функции, ваш код выглядит следующим образом ( EDIT: Это то же самое, что уже опубликовал Рамон, но я оставлю здесь ответ, потому что у него есть дополнительное объяснение ):

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 # менее идиоматичным.Невозможно добавить новую синтаксическую конструкцию real , например comefrom, в 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 ()

В качестве альтернативы вы можете определить comefrom компоновщик вычислений и затем использовать следующий синтаксис:

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

(Этот пост в блоге дает очень простой примерпостроителя вычислений, который вы можете адаптировать)

3 голосов
/ 24 августа 2011
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()

?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...