Bifurcación condicional - "GoTo" Kluge ? - página 4

 

Java tampoco se ejecuta fuera de su máquina virtual, ahí tendrás los mismos problemas, no puedes hacer una dll que se pueda cargar y llamar desde un programa C.

Si te gusta C# entonces también te gustará ObjectPascal (la seguridad de tipos, la rigurosidad, toda la filosofía que hay detrás, excepto lo de la máquina virtual). Después de todo, el diseñador y principal arquitecto de C# es la misma persona que creó Turbo-Pascal y Delphi (ObjectPascal) y eso se nota. En algunos aspectos, C# es como ObjectPascal con una sintaxis de C (fea, pero hoy en día de moda).

Para interactuar directamente con la máquina y con C-APIs (como se necesita para MetaTrader) y seguir utilizando un lenguaje tan potente como C# no hay muchas alternativas a ObjectPascal. Algunos dicen que C++ es igual de potente (y, por supuesto, también se puede utilizar en lugar de OP), pero es evidente que no es tan elegante, tiene muchas inconsistencias y es tan propenso a los errores que sólo los verdaderos expertos pueden dominarlo realmente.

 
7bit:

.... el retorno dentro de una función hará que ésta vuelva al lugar desde el que se llamó a la función.

Esta es la distinción crucial 7bit: Estoy hablando de invocar una función completamente diferente, subrutina o incluso código importado, subrutinas y/o funciones enteras FUERA de la función actual. Un ejemplo conceptual:

Estoy en una función que tiene lugar desde la línea 100 hasta la línea 20, pero quiero invocar algo que cae fuera de ESTE ámbito. Tal vez una función completamente diferente que está en las líneas 50 a 60. <=-Esto no se ajusta a los parámetros y al ejemplo anterior que es lo que estoy preguntando Es un sustituto al 100% del antiguo gosub/return y además la función permite pasar valores y devolver valores.

Puedes tener múltiples declaraciones de retorno dentro de la misma función y también puedes salir de los bucles con break ....

Entendido

Pero me siguen diciendo que puedo moverme dentro del ámbito de una función específica, lo cual entiendo. Pero esto NO es lo que estoy preguntando en absoluto y declarado al principio de todo esto.

En cuanto a las "excepciones", supongo que puedes llamarlas así si lo deseas. Como he dicho, estoy tratando de encontrar un 'trabajo alrededor' para agregar y utilizar la funcionalidad de las funciones tales como: GoTo, GoSub (fuera de la función CURRENT) etc que no existe como una función directamente dentro de MQL4. Por sus respuestas, la mayoría de ustedes saben y entienden estas distinciones de programación, pero no están abordando la pregunta real.

 

FourX:

Estoy en una función que tiene lugar de la línea 100 a la 20, pero quiero invocar algo que cae fuera de ESTE ámbito. Tal vez una función completamente diferente que está en las líneas 50 a 60.
Cree una función separada que contenga el código de las líneas 50 a 60 y luego podrá invocarla desde cualquier otra función en la que se encuentre en cualquier momento.
 

considera esto:

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

¿Qué pasará ahora? Empecemos con main(), explicaré todos los pasos durante la ejecución (los comentarios están en verde, las instrucciones en negro):

  • (estamos en la primera línea de main())
  • empuja la dirección de retorno a la pila (necesita 4 bytes), esta es la dirección donde continuará una vez que la llamada a foo() haya terminado (necesitamos recordar esto para saber más tarde a dónde regresar)
  • saltar a la primera línea de foo()
  • empujar 4 bytes a la pila para hacer sitio a la variable local x
  • empujar 4 bytes a la pila para dejar espacio a la variable local y
  • (nuestra pila tiene ahora 12 bytes de altura)
  • escribir el valor largo 33 en los bytes 0,1,2,3 (contados desde la parte superior de la pila)
  • escribir el valor long 42 en los bytes 4,5,6,7 (contados desde la parte superior de la pila)
  • imprimir el valor long que se encuentra en los bytes 4,5,6,7 (contados desde la parte superior de la pila)
  • sacar 4 bytes de la pila y olvidarlos (y sale del ámbito)
  • saca 4 bytes de la pila y los olvida (x sale del ámbito)
  • salta 4 bytes de la pila, esta es ahora la dirección de donde venimos al llamar a foo(), la dirección de retorno, salta a esta dirección
  • (ahora estamos de vuelta en main() en la siguiente línea, la de bar())
  • empujar la dirección de retorno (4 bytes) a la pila
  • saltar a la primera línea de bar()
  • empujar 4 bytes (variable local x) a la pila
  • (nuestra pila tiene ahora 8 bytes de altura)
  • escribir el valor largo 5 en los bytes 0,1,2,3 (contados desde la parte superior de la pila)
  • saltar a la etiqueta .LABELFOO
  • (ahora observa cuidadosamente cómo todo va horriblemente mal a partir de aquí. Ya sabemos lo que harán todas las líneas siguientes porque lo expliqué arriba, hacen exactamente lo mismo que antes, todas se comportan como si tuvieran los 12 bytes superiores de la pila a su disposición. ¡Pero la pila sólo tiene 8 bytes esta vez! La siguiente línea espera una variable en la posición 4,5,6,7 de la parte superior de la pila, ahora veamos que pasa, aquí viene la línea con el print)
  • imprime el valor largo que se encuentra en los bytes 4,5,6,7 (contados desde la parte superior de la pila)
  • (oops... esto no es nuestra x, es el valor de retorno, la pila sólo tiene 8 bytes de altura esta vez, está imprimiendo un número total sin sentido)
  • saltar 4 bytes de la pila y olvidarlos (esto sería "y sale del ámbito" pero no es y, es en realidad la x de la otra función)
  • quitar 4 bytes de la pila y olvidarlos (esto sería "x sale del ámbito" pero no es x, ¡acabamos de tirar la dirección de retorno!)
  • (¡la pila está vacía ahora!)
  • sacar 4 bytes de la pila para obtener la dirección de retorno -> ¡crash!

¿Puedes verlo? la función foo necesita un marco de pila local de 8 bytes más la dirección de retorno y la función bar sólo 4 bytes más la dirección de retorno. Sus declaraciones de retorno ya tienen esto incorporado por el compilador en tiempo de compilación, sacan diferentes cantidades de bytes de la pila, no puedes usar un retorno para hacer el trabajo del otro, cada uno funciona sólo para la función para la que fue compilado.

Estos viejos lenguajes que tenían GOTO en todo el programa no tenían alcance de variables locales y lo único que había que hacer bien era que el número de GOSUB y RETURN fueran iguales, todos sus retornos sólo hacían saltar la dirección de retorno y nada más, todos los retornos se comportaban exactamente igual. Pero ahora tenemos un montón de "GOSUB "s de diferentes tamaños (cada uno empuja diferentes cantidades en la pila) y también muchos retornos diferentes que saltan diferentes cantidades de la pila. Y tenemos variables locales en la pila. Esto simplemente no puede funcionar, no importa qué cosas locas intentes construir en el compilador.

Teóricamente podrías hacer GOTO dentro de la *misma* función (y algunos lenguajes lo permiten) pero no puedes mostrarme un trozo de código en el que esto conduzca realmente a un código más elegante y más fácil de entender y mantener que una programación estructurada adecuada. Todo lo que haría es producir un lío horrible. Nadie necesita esto, así que no se implementa.

 

Todos sabemos ya que MQL4 no tiene funciones nativas como un GoTo O un 'GoSub -=> ReturnFromGoSub'. No hay discusión sobre eso. Esto se ha convertido en repetidas explicaciones y ejemplos del hecho de que MQL4 no tiene tales funciones nativas. No hay discusión allí. Este hilo no trata de eso y nunca lo ha hecho. ¿Así que podemos dejar de discutir sobre lo que ya sabemos y estamos de acuerdo?

Sabemos que son funciones válidas en otros lenguajes de programación y que pueden ser muy útiles.

El objetivo de esto es averiguar si podemos simularlas y utilizarlas con lo que está disponible en MQL4.

Por ejemplo, una función válida para completar el segundo caso en la primera frase de'GoSub -=> ReturnFromGoSub ' sería Volver al punto del programa en el que se llamó al GoSub y devolver los valores del GoSub al punto de llamada en el programa.

 
FourX:

Por ejemplo, una terminación de función válida del segundo caso en la primera frase de'GoSub -=> ReturnFromGoSub ' sería Volver al punto del programa en el que se llamó a GoSub y devolver los valores de GoSub al punto de llamada en el programa.


Se le ha dicho repetidamente que lo que está describiendo es una Función Personalizada... ¿por qué no puede aceptar eso? por favor dé un ejemplo, con pseudo código, de por qué una Función Personalizada!= Gosub + Return
 

FourX:

'GoSub -=> ReturnFromGoSub ' sería para: Regresar al punto del programa que el GoSub fue llamado y devolver los valores del GoSub al punto de llamada en el programa.

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
Ahí tienes tu GOSUB y RETURN, integrados en el lenguaje mql4, incluso con el paso de argumentos y valores de retorno que ni siquiera era posible en Commodore-BASIC o cualquier otro lenguaje antiguo y lisiado con el que intentas compararlo constantemente. ¿Dónde has estado durante los últimos 30 años?
 

FourX si estás aprendiendo mql4 mientras todavía tienes la mente en BBC Basic piensa en defproc y proc y olvida GoTo y GoSub.

Tuve un BBC micro a principios de los 80 ....ahhhh todavía recuerdo las alegrías de tratar de conseguir que los programas se carguen de su unidad de cinta de cassette :( solíamos escribir programas en BBC Basic

 
SDC:

FourX si estás aprendiendo mql4 mientras todavía tienes la mente en BBC Basic piensa en defproc y proc y olvida GoTo y GoSub.

Tuve un BBC micro a principios de los 80 ....ahhhh todavía recuerdo las alegrías de tratar de conseguir que los programas se carguen de su unidad de cinta de cassette :( solíamos escribir programas en BBC Basic

LOL . . . Tenía un Acorn Electron... cuando hacía calor no leía las cosas de la cinta que había escrito cuando hacía frío y viceversa... esos eran los días. ;-)
 
RaptorUK:
LOL . . . Tenía un Acorn Electron... cuando estaba caliente no leía cosas de la cinta que había escrito cuando estaba fría y viceversa... esos eran los días. ;-)

Sí que eran los días :) girando un destornillador doblado en ese pequeño tornillo por las cabezas de la cinta, mientras que repetidamente golpeando el lado de ella jaja