Using goto code and runtime evaluation

Recently, for the programming class, we were given the task of writing a program in any language, which, given n, will cause all possible violations for an array p of size n, such that p [i]! = I for all i: 0 <= i <n We had to use iterators, for example. yield .

Example: n = 3, [0, 1, 2] is not a disorder, but [2, 0, 1] is also equal to [1, 2, 0].

I came up with a pseudo-code solution that would work, but the problem was that it required power loops (i.e. n nested loops where n is known only at runtime). To do this, I generated n nested loops in the Ruby code in the string, and then eval in the string. My solution worked, however my professor believed that using multiple goto would be a better solution (easier to read, at least) than creating dynamic code.

I got the impression that goto always a bad choice. Why can estimating the runtime of dynamically generated code be worse than goto ? The generated code is clean and simple and seems pretty effective for this problem. The only user input that code generation depends on is n, which is checked to ensure its integer value in advance. This yield only a unique disorder, as it should be.

I do not ask for a solution for my programming, I just want to find out the reasons for using goto to evaluate dynamic code or vice versa.

Edit: to clarify, the assignment involved writing a program using iterators, and the other using recursion, so the iterative version did not have to be effective.

+4
source share
11 answers

This is a really interesting question - I'm not sure there is a definitive answer.

The problem with goto is its use in an unstructured way - goto is a "massive random jump", so in the general case after the jump you don’t know where you came from, from which all kinds of problems arise both from the point of view of debugging and maintainability and - in more formal sense with proof of the "correctness" of the code. Of course, there are languages ​​(I was around that time) where you have no option at what point you are imposing a structure on the code. The bottom line is that its not that GOTO is bad, like the fact that goto is used (and abused), which is bad, and that makes its dangerous construction accessible.

Using code generation and then evaluating the result is smart :) However, smart is not always good, and I suspect that part of the problem with using this as a solution is that it does not actually solve the problem as intended. This may be a "trick" in a sense - at least as far as your professor is concerned - it does not cancel your decision, but it can make it "inelegant." Debugging and maintenance issues also arise regarding code.

A recursive solution β€” all the more so because I vaguely remember how you were taught (about 25 years ago) that you can usually spin recursion into loops β€” would probably be the most elegant.

Definitely an interesting question!

+2
source

Both GOTO and code generation are inelegant solutions to this IMO problem. There is a recursive algorithm, which is probably the correct answer here.

+6
source

Without seeing my code, I tend to profile. If this is a choice between GoTo and dynamic code, I would be inclined to the first. GoTo is not always a bad choice.

+2
source

You can solve almost all problems without using GoTos. In particular, with loops, you can use the break and continue statements to implicitly use gotos, and the standard code is still supported.

n nested loops sound like a bad plan, and I suggest you look at recursive functions instead. Every time you need to do n-loops, you should always think about recursion.

+2
source

Dynamic code does not check compilation time, which means that any errors will be displayed without specifying the time to run. Potentially complicate their search. For ruby, this would mean that syntax errors would not be found by the IDE or the editor, depending on what you are using. This is a plus for choosing goto.

I think I would have to make a decision in this case. I have not seen the code, but I bet that there is a good solution that does not use dynamic code or goto's. goto is not always bad, but if you are thinking about using it, you probably have not reached the best design solutions until this point and probably want to get back to your solution.

+2
source

In one of my college assignments, I had to do something that was relatively similar. My solution was to use a recursive function, pass an array, the size of the array, and the level of nesting as an argument. Then the function calls itself with a nesting level of +1, until the nesting level is equal to the size of the array. No Goto, no code evaluation, only clean code!

Example

 function computeDerangement(yourArray, loopLevel, arraySize) { //We check to see if the loop level is the same as the array size //if true, then we have executed exactly n loop if (loopLevel == arraySize) { display(yourArray); //Display being some kind of function that show the array, //you get the idea } else { while(something) { //Here you put the logic that you execute at one level of the loop //Then you call yourself with one more level of nesting computeDerangement(yourArray, loopLevel + 1, arraySize); } } } 

Hope that helps!

I have never used goto in my life, so I'm sure there is always a way to avoid them.

+1
source

The main reason people avoid goto statements is because they can make it harder to understand your program.

Without seeing your code, I think it will be harder to understand than the equivalent program using goto ...

+1
source

The GOTO solution is convenient when modeling a function call. Here's an irregular solution that simply mimics a recursive solution, using the goto stack and label to return to the point at which the function was called.

See the recursive procedure (I posted this as a separate answer) for a comparison.

Strict On Option Explicit On

Module1

 Private Sub printGeneratedList(ByVal generatedList As List(Of Integer)) For Each el In generatedList Console.Write(el & " ") Next Console.WriteLine() End Sub Private Sub generateAux(ByVal i As Integer, ByVal n As Integer, _ ByVal generatedList As List(Of Integer)) Dim stackI As Stack(Of Integer) = New Stack(Of Integer) Dim stackJ As Stack(Of Integer) = New Stack(Of Integer) Dim j As Integer 

StartLabel:

  j = 0 If i >= n Then printGeneratedList(generatedList) If stackI.Count = 0 Then Return Else GoTo ReturnLabel End If End If While j < n If Not j = i Then If Not generatedList.Contains(j) Then generatedList.Add(j) stackI.Push(i) stackJ.Push(j) i = i + 1 GoTo StartLabel 

ReturnLabel:

  i = stackI.Pop() j = stackJ.Pop() generatedList.Remove(j) End If End If j = j + 1 End While If stackI.Count = 0 Then Return Else GoTo ReturnLabel End If End Sub Private Sub generate(ByVal n As Integer) Console.WriteLine("Generating for n = " & n.ToString()) Dim l As List(Of Integer) = New List(Of Integer) If n < 0 Then Throw New Exception("n must be >= 0") End If generateAux(0, n, l) End Sub Sub Main() generate(0) Console.ReadLine() generate(1) Console.ReadLine() generate(2) Console.ReadLine() generate(3) Console.ReadLine() generate(4) Console.ReadLine() End Sub 

End module

+1
source

goto is not clean. but if high performance is required, you sometimes need to break some of these encoding rules ...

If speed is really important, for example, if you want to write a library or code on which you have a big effect, you might consider using goto. you should pay attention that everything is going well.

Comment: in the end, the execution processor does nothing more than simple jumps. Only that the programming language / compiler creates them. use with caution and do not bother with it.

0
source

Both the goto solution and the ideas for generating dynamic code are bad. This is easily solved using a recursive solution, as mentioned by others. You just recursively generate all the permutations (the standard recursive solution) and when the generation is complete (i.e., on the recursion sheet) just skip the return permutations that are not violations.

0
source

A recursive solution - here's an early crop solution. My only question is about enumerations: did he want you to create a counter that on each successful call will generate the next element in the list? This would probably be easiest to implement by creating a lambda version of this program - I always did this in lisp all the time when I wrote query generators that would generate the following answer to a question when executing queries of the interpreter-prolog style.

Strict On Option Explicit On

Module1

 Private Sub printGeneratedList(ByVal generatedList As List(Of Integer)) For Each el In generatedList Console.Write(el & " ") Next Console.WriteLine() End Sub Private Sub generateAux(ByVal i As Integer, ByVal n As Integer, _ ByVal generatedList As List(Of Integer)) If i >= n Then printGeneratedList(generatedList) Return End If For j As Integer = 0 To n - 1 If Not j = i Then If Not generatedList.Contains(j) Then generatedList.Add(j) generateAux(i + 1, n, generatedList) generatedList.Remove(j) End If End If Next End Sub Private Sub generate(ByVal n As Integer) Console.WriteLine("Generating for n = " & n.ToString()) Dim l As List(Of Integer) = New List(Of Integer) If n < 0 Then Throw New Exception("n must be >= 0") End If generateAux(0, n, l) End Sub Sub Main() generate(0) Console.ReadLine() generate(1) Console.ReadLine() generate(2) Console.ReadLine() generate(3) Console.ReadLine() generate(4) Console.ReadLine() End Sub 

End module

0
source

All Articles