How do you implement goto in F #?

All my favorite languages ​​have goto command. That is, you can create a label, and then interrupt the program flow to go to the label. One of the most useful applications of this design is to create an infinite loop, for example:

  start: goto start 

Unfortunately, if I understand the compiler errors correctly, I cannot use this syntax in F #. So, since it is not supported at the root, how can I implement the goto command in F #?

Of course, F # is a powerful enough language to implement such a simple function. Other languages, such as Javascript, that do not support goto , can still implement it through the plugin.

In addition, I believe that F #, as one of the languages ​​in the functional programming paradigm, should support a higher level of goto s: where you can pass goto to goto s.

+4
source share
5 answers

A shortcut has much in common with a function: they both act as entry points to some code that needs to be executed. Given this similarity, you can do the following:

 let goto f = f() let test() = let label = (fun () -> //rad code ) //tight code goto label 

One of the minor flaws is folding the entire code to close. I do not know - it does not seem too bad to get something as convenient as goto .

+9
source

Unfortunately, if I understand the compiler errors correctly, I cannot use this syntax in F #. So, since it is not supported on the side, how can I implement the goto command in F #?

As Daniel said, a label and its next block of commands can be translated into a function and its body. Then each goto becomes a function call. You must pass all local variables as arguments, since individual functions have separate scopes, and if necessary, you must add end-to-end calls from one block of commands to the next. However, tail calls are a more general concept.

An example start loop will look like this:

 let rec start () = // .start start() // goto start 

Note that a decent compiler will actually compile this equivalent high-level code back to jump / branch between commands in assembler. The main difference is that the frames of the stack must be reorganized, because you can overlap between completely different environments.

In addition, I believe that F #, as one of the languages ​​in the functional programming paradigm, should be able to support higher-level transitions: where you can pass gotos to gotos.

Yes indeed. You cannot pass labels in other languages, but you can pass functions to F #, both as arguments in function calls and as return values ​​from functions. Other languages, such as Fortran, offer settlement goto as a halfway home.

Please note that asynchronous programming is an important practical application of this method. When you call an asynchronous function, you indicate where it should enter when it exits. For example, when you make a call to start the asynchronous loading of a web page, you give it a function that will be called after the data is available (in fact, the hardware interrupt received when your last data arrives ends up turning off your high -level managed code for working with new data, which is pretty cool). Modern languages ​​provide tools for writing asynchronous reusable code by combining these goto methods with adding code at compile time. In other languages, such as C #, you are screwed up because you want to wrap several asynchronous calls in one try..catch , but you cannot, because they actually extend to many different functions.

+8
source

You can get the GOTO behavior in F # using mutually recursive functions. Call optimization allows you to use this goto nature and doesn't push anything on the stack.

 int parse() { Token tok; reading: tok = gettoken(); if (tok == END) return ACCEPT; shifting: if (shift(tok)) goto reading; reducing: if (reduce(tok)) goto shifting; return ERROR; } 

Here, do_read, do_shift and re_reduce act as labels.

 type Token = END | SOMETHINGELSE type Status = ACCEPT | ERROR let parse gettoken shift reduce () = let rec do_read() = match gettoken() with | END -> ACCEPT | _ as tok -> do_shift tok and do_shift tok = if shift tok then do_read() else do_reduce tok and do_reduce tok = if reduce tok then do_shift tok else ERROR do_read() 

Code Source http://sharp-gamedev.blogspot.com/2011/08/forgotten-control-flow-construct.html

+7
source

One approach that is not mentioned in other answers is to create your own calculation builder. I wrote two articles that implement some imperative functions for F # in the imperative { .. } calculation builder imperative { .. } (read the first and second options first ).

They do not reach the implementation of goto , but they implement continue and break . You could add goto support, but you could only go back to tags that were completed earlier. The following is an example of using continue :

 imperative { for x in 1 .. 10 do if (x % 3 = 0) then do! continue printfn "number = %d" x } 
+4
source

If you look at the source code , you will find that goto.js is implemented as a text code preprocessor. It uses regular expressions to find and replace shortcuts and gotos with matching Javascript constructs.

You can use this approach to extend any language (including, of course, F #). In .NET, you could probably use T4 in a similar way. However, manipulating a language at the text level is usually more of a hack than a proper extension (the author of goto.js says "Seriously. Never use this."). This kind of metaprogramming can often be done instead by connecting to the AST language.

Of course, F # is a powerful enough language to implement such a simple function.

F # really has very poor metaprogramming support. Languages ​​with good metaprogramming capabilities include any Lisp, OCaml (via campl4 ), Haskell (via Template Haskell ), Nemerle , Scala , Boo . Traceur implements the proper metaprogramming capabilities of metadata in JavaScript. But AFAIK there is nothing like that for F # yet.

must support higher access levels

GOTOs are not first-class meanings in any language I know, so the term "higher level GOTO" does not make sense. However, if you are really interested in manipulating the flow in functional languages, you should study the continuation .

+1
source

All Articles