'Conditional Branching - 'GoTo' Kluge ? - page 4

 

Java is also not running outside of its virtual machine, there you will have the same problems, you cannot make a dll that can be loaded and called from a C program.

If you like C# then you will also like ObjectPascal (the type safety, the strictness, the entire philosophy behind it, except the VM thing). After all the designer and chief architect of C# is the same person who once created Turbo-Pascal and Delphi (ObjectPascal) and it shines through. In some regards C# is like ObjectPascal with (ugly but nowadays hip) C syntax.

For interfacing directly with the machine and with C-APIs (like it is needed for MetaTrader) and still using a language as powerful as C# there are not many alternatives to ObjectPascal. Some say C++ is equally powerful (and can of course also be used instead of OP) but it is clearly not as elegant, has many inconsistencies and is so error prone that only true experts can truly master it.

 
7bit:

.... the return inside a function will make it return to the place the function was called from.

This is the crucial distinction 7bit: I'm talking about invoking a completely different function, subroutine or even imported code, entire sub-routines &/or functions OUTSIDE of the entire current function. A conceptual example:

I'm in a function that takes place from line 100 to line 20, but I want to invoke something that fall outside of THIS scope. Perhaps an entirely different function that is in lines 50 to 60. <=-This doesn't fit the parameters and example above which is what I am asking about It is a 100% substitute of the old gosub/return and additionally the function allows for passing values and returning values.

You CAN have multiple return statements within the same function and you can also break out of loops with break ....

Understood

But I keep getting told about how I can move around within the scope of a specific function, which I understand. But this is NOT what I am asking about at all and stated at the start of all of this.

So as to 'exceptions' then I guess you can call them that if you wish. As I stated, I'm trying to find a 'work around' to add and utilize the functionality of functions such as: GoTo, GoSub (outside of the CURRENT function) etc that does not exist as a function directly within MQL4. By your responses, most of you know of and understand these programming distinctions, but are not addressing the actual question asked.

 

FourX:

I'm in a function that takes place from line 100 to line 20, but I want to invoke something that fall outside of THIS scope. Perhaps an entirely different function that is in lines 50 to 60.
Create a separate function containing the code from lines 50 - 60 then you can invoke it from whichever other function you are in at any time.
 

consider this:

void foo(){
  int x;
  int y;
  y = 33;
  x = 42;
  .LABELFOO
  print(x);
  return;
}

void bar(){
  int x;
  z = 5;
  GOTO .LABELFOO
}

void main(){ //<-- program starts here
  foo();
  bar();
}

Now what will happen? Lets start with main(), I will explain all steps during execution (comments are in green, instructions are black):

  • (we are at the first line in main())
  • push the return address onto the stack (needs 4 bytes), this is the address where it would continue once the call to foo() will be finished (we need to remember this so that we will later know where to return to)
  • jump to the first line of foo()
  • push 4 bytes to the stack to make room for local variable x
  • push 4 bytes to the stack to make room for local variable y
  • (our stack is now 12 bytes high)
  • write the long value 33 to the bytes 0,1,2,3 (counted from the top of the stack)
  • write the long value 42 to the bytes 4,5,6,7 (counted from the top of the stack)
  • print the long value that is found in the bytes 4,5,6,7 (counted from the top of the stack)
  • pop 4 bytes from the stack and forget them (y goes out of scope)
  • pop 4 bytes from the stack and forget them (x goes out of scope)
  • pop 4 bytes from the stack, this is now the address where we came from when calling foo(), the return address, jump to this address
  • (now we are back in main() at the next line, the one with bar())
  • push the return address (4 bytes) to the stack
  • jump to first line of bar()
  • push 4 bytes (local variable x) to the stack
  • (our stack is now 8 bytes high)
  • write the long value 5 to the to the bytes 0,1,2,3 (counted from top of stack)
  • jump to the label .LABELFOO
  • (now carefully observe how it all goes horribly wrong from here on. We already know what all the following lines will do because I explained it above, they do the exact same things as they did before, they all behave as if they had the top 12 bytes of the stack at their disposal. But the stack has only 8 bytes this time! The next line expects a variable in the position 4,5,6,7 from the top of the stack, now lets see what happens, here comes the line with the print)
  • print the long value that is found in the bytes 4,5,6,7 (counted from the top of the stack)
  • (oops? this is not our x, this is the return value, the stack is only 8 bytes high this time, its printing a total nonsense number)
  • pop 4 bytes from the stack and forget them (this would be "y goes out of scope" but its not y, its actually the x from the other function)
  • pop 4 bytes from the stack and forget them (this would be "x goes out of scope" but its not x, we have just thrown away the return address!)
  • (the stack is empty now!)
  • pop 4 bytes from the stack to get the return address -> crash!

Can you see it? the foo function needs a local stack frame of 8 bytes plus return address and the bar function only 4 bytes plus return address. Their return statements have this built in by the compiler at compile time already, they pop different amounts of bytes from the stack, you cannot use one return to do the job of the other, each one works only for the function it was compiled for.

These old languages that had GOTO across the entire program did not have local variable scope and the only thing you had to get right was to match the number of GOSUB and RETURN to be equal, all their returns did only pop the return address and nothing else, all the returns behaved exactly the same. But now we have a lot of differently sized "GOSUB"s (each one pushes different amounts onto the stack) and also many different returns which pop different amounts from the stack. And we have local variables on the stack. This just cannot work, no matter what crazy things you try to build into the compiler.

You could theoretically GOTO within the *same* function (and some languages allow this) but you cannot show me one piece of code where this would actually lead to more elegant and easier to understand and more maintainable code than proper structured programming. All it would do is produce a horrible mess. Nobody needs this, so it is not implemented.

 

We all already know that MQL4 doesn't have such native functions as a GoTo OR a 'GoSub -=> ReturnFromGoSub.' There is no dispute about that. This has now turned into repeated explanations and examples of the fact that MQL4 doesn't have such native functions. No argument there. That isn't what this thread is about and it never was. So can we please stop arguing about what we already know and agree on?

We know that these are valid functions in other programming languages and can be very useful.

The whole point of this is to find out IF we CAN simulate and utilize them with what IS available in MQL4?

For example, a valid function completion of the second case in the first sentence of 'GoSub -=> ReturnFromGoSub' would be to: Return to point of the program that the GoSub was called and return the values from GoSub to the calling point in the program.

 
FourX:

For example, a valid function completion of the second case in the first sentence of 'GoSub -=> ReturnFromGoSub' would be to: Return to point of the program that the GoSub was called and return the values from GoSub to the calling point in the program.


You have repeatedly been told that what you are describing is a Custom Function . . . why can't you accept that ? please give an example, with pseudo code, of why a Custom Function != Gosub + Return
 

FourX:

'GoSub -=> ReturnFromGoSub' would be to: Return to point of the program that the GoSub was called and return the values from GoSub to the calling point in the program.

double subtract_two_numbers(double a, double b){
  Print("will now calculate ", a, " minus ", b);
  return(a - b);                                 // <---- THIS IS YOUR RETURN
}

int start(){                                     // <---- PROGRAM STARTS HERE
  double s;
  double d;

  s = subtract_two_numbers(Ask, Bid);            // <---- THIS IS YOUR GOSUB
  d = subtract_two_numbers(Close[0], Open[0]);   // <---- THIS IS YOUR GOSUB

  Print("the spread is ", s);
  Print("price moved ", d, " since the open");
}                                                // <---- PROGRAM ENDS HERE
There you have your GOSUB and RETURN, built right into the mql4 language, even with passing arguments and return values which was not even possible in Commodore-BASIC or whatever other ancient and crippled language you are constantly trying to compare it to. Where have you been during the last 30 years?
 

FourX if you are learning mql4 while still have your mind is still in BBC Basic think defproc and proc and forget GoTo and GoSub.

I had a BBC micro in the early 80s ....ahhhh i still remember the joys of trying to get programs to load off its cassette tape drive :( we used to write programs in BBC Basic

 
SDC:

FourX if you are learning mql4 while still have your mind is still in BBC Basic think defproc and proc and forget GoTo and GoSub.

I had a BBC micro in the early 80s ....ahhhh i still remember the joys of trying to get programs to load off its cassette tape drive :( we used to write programs in BBC Basic

LOL . . . I had an Acorn Electron . . . when it was hot it wouldn't read stuff off tape I had written when it was cold and visa versa . . . those were the days. ;-)
 
RaptorUK:
LOL . . . I had an Acorn Electron . . . when it was hot it wouldn't read stuff off tape I had written when it was cold and visa versa . . . those were the days. ;-)

Yes they were the days alright :) twisting a bent screwdriver on that little screw by the tape heads while repeately thumping the side of it haha
Reason: