
Del básico al intermedio: Array (III)
Introducción
El contenido expuesto aquí tiene un propósito puramente didáctico. En ningún caso debe considerarse una aplicación final, cuyo objetivo no sea el estudio de los conceptos mostrados aquí.
En el artículo anterior Del básico al intermedio: Array (II), expliqué los conceptos básicos sobre cómo utilizar arrays del tipo dinámico y estático. La diferencia entre ambos y los principales cuidados que debemos tener en cuenta al utilizar arrays en nuestras aplicaciones.
Muy bien, el tema aquí seguirá siendo array. Aunque para entender este artículo es necesario haber comprendido el anterior. Además, por supuesto, es necesario entender cómo funcionan el paso por valor y el paso por referencia. Todos estos temas se trataron y demostraron en los artículos anteriores. Si tienes alguna duda o no conoces estos conceptos porque acabas de llegar, te sugiero que, antes de continuar, leas los artículos anteriores. Así podrás seguir lo que se explicará aquí.
Como de costumbre, vamos a iniciar un nuevo tema, para comenzar nuestros estudios y demostraciones.
Uso de arrays en funciones y procedimientos
Uno de los temas que asusta a muchos principiantes es el uso de arrays para pasar valores entre funciones y procedimientos. Voy a ser muy sincero con respecto a una cuestión que involucra tal concepto. La forma en que MQL5 gestiona este tipo de cosas es infinitamente más sencilla que la de otros lenguajes en este mismo aspecto. Lenguajes como C y C++ son extremadamente complejos cuando se utilizan para esto. Esto se debe a que en C y C++ NO EXISTE un array, como sí sucede en MQL5. En su lugar, usamos otra estructura llamada puntero. El problema de los punteros, que los vuelve tan complicados y difíciles de dominar, es que podemos usar una referencia indirecta en algunos casos. Esto, aunque le da mucho poder al programador, también hace que el código sea mucho más complicado de comprender. Aún más cuando el programador tiene poca experiencia en codificación y uso de punteros.
No obstante, aquí en MQL5, las cosas son mucho más fáciles de asimilar y comprender. Empezando por el hecho de que:
Todo array se pasa SIEMPRE por referencia, ya sea a una función o a un procedimiento.
No existe el paso por valor en el caso de utilizar un array como argumento en una función o procedimiento, dentro de MQL5.
Bien, pero ¿no estarás pensando que: si se pasan todos los argumentos de arrays por referencia, sea a una función o a un procedimiento, el código no sería seguro? En realidad, no, querido lector. Por increíble que parezca, usar arrays en MQL5 es mucho más seguro que usar otros tipos de variables. Y aún hay más. Usar arrays en MQL5 es mucho más fácil que utilizar cualquier otro método visto en otros lenguajes. Esto se debe a que, en MQL5, tienes control total sobre lo que puede suceder con un array. Aunque siempre se pase por referencia a una función o procedimiento.
Lo que garantiza este nivel de seguridad y fiabilidad es precisamente un mayor cuidado por parte del programador. Cuando expliqué cómo podemos hacer uso del paso por referencia o del paso por valor, mostré las ventajas y desventajas de cada enfoque. Pero aquí es mucho más simple, ya que la propia declaración, sea de la función o del procedimiento, lo deja muy claro. Existe un segundo detalle y cuidado a tener en cuenta. Y este se refiere al hecho de que:
Todo array declarado como parámetro de una función o procedimiento deberá ser SIEMPRE del tipo dinámico.
Con estos dos conceptos, podrás crear cualquier tipo de implementación en MQL5 que haga uso de arrays. Muchas veces es más práctico y adecuado computar cosas dentro de funciones o procedimientos, en vez de colocar código inline. Observación: para quien desconozca el término «código inline», este se refiere a la situación en la que el programador no utiliza funciones o procedimientos en su aplicación. El programador comienza creando una serie de rutinas una tras otra, como si fuera una gran receta de cocina. A pesar de que este enfoque es infrecuente, puede suceder que resulte efectivo. La característica principal de este tipo de código es la total y completa ausencia de funciones o procedimientos en la implementación realizada.
Está bien, pero volvamos a nuestra cuestión, que es cómo utilizar arrays como parámetros en funciones y procedimientos. A pesar de la aparente simplicidad, no debes confiarte pensando que todo es fácil y sin complicaciones, donde no existe peligro de errores de programación. Porque, de hecho, existen algunos detalles que solo se entienden mejor cuando se ponen en práctica. En teoría todo es muy bonito y magnífico. Es necesario entender y conocer algunos conceptos básicos. Pero, en la práctica, a veces la cosa se complica y muerde fuerte antes de que logremos derrotarla. Así que vamos a ver cómo ocurren realmente las cosas en la práctica. Empezaremos con el código que se muestra a continuación.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. const char Infos[] = {2, 3, 3, 5, 8}; 07. 08. Print("Based on the values:"); 09. ArrayPrint(Infos); 10. PrintFormat("There are %d possibilities.", Possibilities(Infos)); 11. } 12. //+------------------------------------------------------------------+ 13. ushort Possibilities(const uchar &arg[]) 14. { 15. ushort info = 0; 16. 17. for (uchar c = 0; c < arg.Size(); c++) 18. info = (c ? info * arg[c] : arg[c]); 19. 20. return info; 21. } 22. //+------------------------------------------------------------------+
Código 01
Al ejecutar este código 01, tú verás lo que se muestra en la imagen justo debajo.
Imagen 01
Lo que estás viendo en la imagen 01 podría haberse generado de varias formas diferentes. La manera en que se hizo, usando el código 01, es solo con fines didácticos. El objetivo es precisamente explicar lo que está ocurriendo allí y mostrar cómo podemos transferir un array dentro de una función o procedimiento.
Muy bien, entonces veamos qué está ocurriendo aquí. Recordad que me centraré solo en las partes que considero que no se han explicado en ninguno de los artículos anteriores. Así que vayamos con los puntos destacados. Empezando por la línea seis. A pesar de que estamos usando un array estático, esto se hace solo para agilizar el código. Podríamos usar un array dinámico y nada cambiaría en lo que se está haciendo. El objetivo es pasar los valores dentro de la función de la línea trece. Cualquier cosa que ocurra antes de la línea 10, vista en el código 01, no afecta al paso del array. Siempre que hayamos declarado la función como se muestra en la línea trece, por supuesto.
Ahora presta atención a lo que se explicará a continuación, querido lector. Como vimos en los artículos anteriores, cuando se declara un array como constante, este debe inicializarse OBLIGATORIAMENTE en la propia declaración. Esto se hace para evitar errores frente al compilador. Pero observa esta línea trece con atención. Verás que allí estamos declarando un array como constante. Sin embargo, a pesar de esto, el compilador genera el ejecutable. ¿Por qué aquí podemos declarar las cosas así, pero si intentamos hacer esto en la línea seis, no funcionará? El motivo es que, a diferencia de lo que ocurre en la línea seis, aquí el array se está declarando, no como variable, sino como parámetro. Como se mencionó al principio de este tema, todo array debe pasarse como referencia. Y eso es precisamente lo que está ocurriendo aquí.
Tal vez algunos de ustedes, que están comenzando en la programación, se estén imaginando, de manera completamente equivocada, que el array declarado en la línea trece NO ESTÁ siendo declarado como constante por causa del array de la línea seis. Son dos cosas diferentes. Incluso puedes declarar e inicializar el array de la línea seis como totalmente dinámico. Sin embargo, esto no anula lo que se declara en la línea trece, ya que son cosas totalmente diferentes.
Existe otro detalle en este código 01 que, en mi opinión, merece ser destacado nuevamente aquí, aunque ya se ha mencionado anteriormente. La cuestión en sí está relacionada con el valor de prueba de la línea 17. Allí estamos usando arg.Size(). Sin embargo, esto está permitido y es perfectamente aceptado, ya que el resultado es el mismo que si se utilizara la función ArraySize. De cualquier forma, la prueba se haría de la misma manera en ambos casos. Dejo como tarea para casa experimentar con la función ArraySize en lugar de arg.Size(), a fin de entender mejor cómo se implementa el código en la práctica.
Genial, creo que este primer contacto ha sido relativamente agradable y bastante placentero, y te ha dado una idea de cómo deberíamos implementar el código para pasar un array a una función o a un procedimiento. La forma de trabajar y declarar el array como parámetro no cambiaría en absoluto. Solo podría ser diferente el objetivo.
Esta fue la parte fácil. Así que podemos avanzar hacia algo un poco más complicado. Pero para que tú puedas estudiar con calma cada tema, vamos a complicar las cosas en un nuevo tema.
Modificación del array de manera remota
Una de las razones por las que el uso de arrays en funciones y procedimientos puede resultar complicado es precisamente la posibilidad de modificar su contenido de forma remota. Es decir, envías un array a una función o procedimiento, y este se modifica. Este tipo de cosa puede generar problemas bastante confusos y complicados de resolver. Pero como podemos —y en muchos casos haremos— esto, es de extrema importancia que llegues a entender muy bien cómo ocurre. Pero, sobre todo, es fundamental que comprendas por qué ocurre.
A diferencia de los valores discretos, como los tipos char, int, long, double y similares, los lenguajes de programación normalmente NO permiten retornar arrays, salvo en casos especiales en los que el propio lenguaje implementa esta función de alguna forma. Como ocurre con las cadenas en MQL5. Como se mostró en artículos anteriores, una string es, en realidad, un array especial. Por tanto, este es uno de los pocos casos en los que podemos retornar un array desde una función en MQL5. Esto ya nos libra del riesgo y de posibles problemas que podrían surgir en ciertas implementaciones que a veces necesitamos hacer, donde realmente existe la necesidad de retornar un array modificado.
Pero antes de hablar más sobre esto, ya que es algo realmente complicado de entender en códigos reales, necesitamos entender cómo otros lenguajes lidian con este problema. En el caso de C y C++, simplemente lo dejan en manos del programador. En estos dos lenguajes tenemos la posibilidad de modificar el array y de retornar un array completamente nuevo. Pero no te engañes, porque los arrays no se tratan en C y C++ como se tratan aquí en MQL5, no estás menos expuesto a errores. De hecho, estás considerablemente más expuesto a errores aún más complicados de resolver. Por eso C y C++ son tan complicados de dominar. Otros lenguajes como Python y JavaScript simplemente ignoran la existencia de tipos convencionales de datos, crean sus propios métodos para que podamos retornar arrays o incluso modificarlos. Es algo bastante menos común que en otros lenguajes, de este modo, se simplifica un poco la factorización de ciertos tipos de datos. No obstante, el objetivo aquí es hablar de MQL5.
Por lo tanto, empezaremos con algo lo más simple posible. Para ello, utilizaremos el código 01, pero cambiaremos un pequeño detalle. Así, obtenemos lo que se muestra justo abajo.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. char Infos[] = {2, 3, 3, 5, 8}; 07. 08. Print("Based on the values:"); 09. ArrayPrint(Infos); 10. PrintFormat("There are %d possibilities.\nValue after call:", Possibilities(Infos)); 11. ArrayPrint(Infos); 12. } 13. //+------------------------------------------------------------------+ 14. ushort Possibilities(uchar &arg[]) 15. { 16. ushort info = 0; 17. 18. for (uchar c = 0; c < arg.Size(); c++) 19. info = (c ? info * arg[c] : arg[c]); 20. 21. arg[0] += 2; 22. 23. return info; 24. } 25. //+------------------------------------------------------------------+
Código 02
Al ejecutar este código 02, tendremos el siguiente resultado que se muestra justo debajo.
Imagen 02
Fíjate que en esta imagen 02 estoy marcando dos valores en la misma. Esto precisamente para llamarte la atención sobre algo que está ocurriendo aquí. Observa que la diferencia entre este código y el código 01 es justamente el hecho de que ahora la línea de declaración del parámetro recibido por la función en la línea 14 YA NO ES DEL TIPO CONSTANTE. Como resultado, el paso por referencia que siempre ocurre con los arrays permite utilizar la línea 21, donde modificamos el valor de uno de los elementos del array declarado en la línea seis. Como aquí estamos trabajando de manera didáctica y enfocados en explicar ciertos conceptos que pueden aplicarse a MQL5, este cambio es bastante fácil de notar. Sin embargo, en códigos reales, este cambio puede estar muy profundo, y entremezclado con el resto del código, de modo que en algunos momentos dan ganas de rendirse y comenzar a programar todo desde cero, debido al grado de complejidad que puede estar generando.
Por eso, querido lector, te pido a ti, que estás empezando a estudiar programación, o tienes poca experiencia, que practiques estos conceptos que estamos viendo aquí. Solo la práctica te dará la experiencia necesaria para poder lidiar con los problemas que, sin duda, surgirán.
Muy bien, este código 02 es, de hecho, el tipo más simple que existe, es casi banal. Pero la cosa comienza a complicarse cuando nos adentramos aún más en el tema. Así que veamos otro ejemplo, esta vez un poco más complicado. Se muestra justo a continuación.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. char Infos[]; 07. 08. ArrayResize(Infos, 7); 09. ZeroMemory(Infos); 10. 11. Infos[0] = 2; 12. Infos[1] = 3; 13. Infos[2] = 3; 14. Infos[3] = 5; 15. Infos[4] = 8; 16. 17. Print("Based on the values:"); 18. ArrayPrint(Infos); 19. PrintFormat("There are %d possibilities.\nValue after call:", Possibilities(Infos)); 20. ArrayPrint(Infos); 21. 22. ArrayFree(Infos); 23. } 24. //+------------------------------------------------------------------+ 25. ushort Possibilities(uchar &arg[]) 26. { 27. ushort info = 0; 28. 29. for (uchar c = 0; c < arg.Size(); c++) 30. info = (c ? (arg[c] ? info * arg[c] : info) : arg[c]); 31. 32. arg[arg.Size() - 1] = 9; 33. 34. return info; 35. } 36. //+------------------------------------------------------------------+
Código 03
Bien, aquí tenemos en el código 03 algo un poco más complicado, pero no es más complicado debido a la línea 30. Esta línea sigue siendo muy sencilla de comprender. El código 03 es más complicado precisamente porque en la línea 6 estamos declarando un array puramente dinámico, y aquí es donde las cosas comienzan a complicarse de verdad. Aunque este código 03 puede ser comprendido por completo por un principiante que esté estudiando el material mostrado aquí en los artículos, esto avanzando paso a paso, y practicando lo que se ha mostrado. Veamos el resultado de la ejecución de este código, se muestra en la imagen de abajo.
Imagen 03
Una vez más, estoy resaltando cierta información presente en la imagen. Es muy importante comprender debidamente esta información. Así que veamos qué ocurrió aquí. Como en la línea ocho indicamos que el array tendrá siete elementos, y en las líneas once hasta la quince inicializamos algunos de estos elementos, podemos ver que, en la línea 18, el contenido del array contiene algunos ceros, esto es normal, precisamente porque en la línea nueve estamos liberando la memoria donde se asignó el array. Precisamente por esos ceros fue necesario añadir un operador ternario extra, en la línea 30. De lo contrario, el resultado de la función sería igual a cero. Pero ese no es el punto de interés en este caso. El punto de interés es precisamente la línea 32. Observa que allí indicamos que asignaremos un valor a un elemento determinado, en este caso, al último del array.
Pero ¿por qué lo estoy haciendo y en esta secuencia de demostraciones? El motivo es que existe una forma de trabajar con arrays en MQL5, que nos permite hacer algo que de otra manera no sería posible. Esto sin que tú, querido lector, comprendas ciertos conceptos relacionados con el uso de arrays. Al mismo tiempo, sin darte cuenta, comenzarás a ver ciertas cosas suceder aquí, que harán que otras se vuelvan mucho más naturales cuando las veas dentro de poco.
Perfecto. Ahora ya tenemos una buena dosis de complejidad añadida al sistema. Sin embargo, todavía podemos complicarlo más, aunque yo pondría fin al artículo aquí. Así tú, querido lector, puedes practicar lo que se ha mostrado hasta este punto, y, dicho sea de paso, ya hay bastante contenido y muchas cosas bastante complicadas de entender. Pero vamos a hacer un último esfuerzo, para mostrar algo interesante relacionado con lo que se está mostrando aquí. Pero como es algo mucho más complicado, vamos a un nuevo tema.
Inicialización remota
En este momento, te pido lo siguiente, mi querido y estimado lector y amigo: detente, estudia lo visto hasta ahora. Cuando lo hayas comprendido por completo y no queden dudas ni conflictos en tu cabeza, podrás entender los códigos anteriores, entonces sí, ven a lo que se verá en este tema. Porque la cosa empieza a volverse demasiado confusa para ser enfrentada sin una preparación adecuada.
Hasta ahora, hemos aprendido que podemos enviar datos usando arrays. También vimos que podemos modificar datos en un array dentro de otra función o procedimiento. Este tipo de cosas debe realizarse con mucha atención, especialmente cuando se quiere crear una aplicación más elaborada. Luego vimos que podemos trabajar con el array y ajustar en qué lugar modificaremos el valor. Ahora ha llegado el momento de hacer otra cosa, y esto se muestra en el código que se presenta a continuación.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. char Infos[]; 07. 08. InitArray(Infos); 09. 10. Print("Based on the values:"); 11. ArrayPrint(Infos); 12. PrintFormat("There are %d possibilities.\nValue after call:", Possibilities(Infos)); 13. ArrayPrint(Infos); 14. 15. ArrayFree(Infos); 16. } 17. //+------------------------------------------------------------------+ 18. void InitArray(uchar &arg[]) 19. { 20. ArrayResize(arg, 7); 21. ZeroMemory(arg); 22. 23. arg[0] = 2; 24. arg[1] = 3; 25. arg[2] = 3; 26. arg[3] = 5; 27. arg[4] = 8; 28. } 29. //+------------------------------------------------------------------+ 30. ushort Possibilities(uchar &arg[]) 31. { 32. ushort info = 0; 33. 34. for (uchar c = 0; c < arg.Size(); c++) 35. info = (c ? (arg[c] ? info * arg[c] : info) : arg[c]); 36. 37. arg[arg.Size() - 1] = 9; 38. 39. return info; 40. } 41. //+------------------------------------------------------------------+
Código 04
Y ahí lo tienes, querido lector, este es el clímax de lo que se verá en este artículo. Sin embargo, no te dejes engañar por la aparente simplicidad de este código 04, porque, aunque el resultado sea el que vemos justo abajo, es mucho más complicado de lo que parece.
Imagen 04
Se puede observar que el resultado es el mismo que el de la imagen 03, idéntico en todos los sentidos. Sin embargo, en este código 04 estoy mostrando algo que puede complicarse mucho en realidad, pero si se implementa correctamente y de forma adecuada, podrá suprimir diversas cosas, especialmente cosas que algunos programadores experimentados afirman que NO SE PUEDE hacer en MQL5. Todo ello de forma pura y sin utilizar ningún otro recurso que no esté disponible en MQL5.
Fui haciendo estos cambios poco a poco precisamente para que pudieras seguir lo que se está haciendo aquí. Pero, aunque al mirar este código 04 puedas imaginar que es simplemente una modificación de lo que se está haciendo en el código 03, en el fondo este código 04 muestra que podemos hacer algo que no sería posible sin tener ciertos conceptos muy bien asimilados. Uno de estos conceptos —y es el que estamos explorando aquí en el código 04— es precisamente el hecho de que todo array se pasa por referencia. Y, cuando hacemos esto, utilizando conceptos vistos en otros artículos anteriores, podemos hacer, de hecho, algo que muchos considerarían imposible. Es decir, inicializar o modificar arrays fuera del lugar donde se han declarado. Podemos llevar esto a un caso un poco más extremo, sin que esto suponga un aumento del nivel de dificultad demostrado hasta ahora. Para explicar esto, modificamos nuevamente el código 04, pero de una forma muy sutil. Como puedes ver en el código justo debajo.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. char Infos[]; 07. 08. if (ArraySize(Infos)) 09. { 10. Print("Based on the values:"); 11. ArrayPrint(Infos); 12. }else 13. Print("Array has not been initialized yet."); 14. PrintFormat("There are %d possibilities.\nValue after call:", Possibilities(Infos)); 15. ArrayPrint(Infos); 16. 17. ArrayFree(Infos); 18. } 19. //+------------------------------------------------------------------+ 20. void InitArray(uchar &arg[]) 21. { 22. const char init [] = {2, 3, 3, 5, 8}; 23. 24. ArrayCopy(arg, init); 25. } 26. //+------------------------------------------------------------------+ 27. ushort Possibilities(uchar &arg[]) 28. { 29. ushort info = 0; 30. 31. InitArray(arg); 32. 33. for (uchar c = 0; c < arg.Size(); c++) 34. info = (c ? (arg[c] ? info * arg[c] : info) : arg[c]); 35. 36. ArrayResize(arg, arg.Size() + 1); 37. arg[arg.Size() - 1] = 9; 38. 39. return info; 40. } 41. //+------------------------------------------------------------------+
Código 05
Al ejecutar este código 05, te encontrarás con la imagen mostrada justo debajo.
Imagen 05
Ahora bien, seguramente te estarás preguntando: «¿Cómo es esto posible? Esto no tiene ningún sentido». Pero aquí solo estoy jugando un poco con el mismo código desde el principio de este artículo, querido lector. No hay ningún motivo para entrar en pánico ni desesperarse. La diferencia es que, a diferencia de lo que hacen la mayoría, aquí estamos llevando al límite conceptos que se pueden explotar perfectamente dentro de MQL5, aunque, en estos últimos códigos, llevamos la cosa un poco más allá de lo que muchos consiguen percibir, esto se debe a que no utilizan el concepto involucrado en la implementación, sino que solo copian y pegan códigos o fragmentos de código sin entender de hecho por qué ese código funciona. Y ese no es mi deseo. Quiero que, de hecho, mi querido lector comprendas los conceptos involucrados. Si logras alcanzar ese objetivo, ya habrá valido mucho la pena escribir estos artículos y demostrar estas cosas.
Muy bien, como no quiero entrar en detalles que ya pueden hacerse en este artículo, simplemente por el hecho de que se han mostrado estos dos últimos códigos, voy a dedicar el resto del artículo a explicar en detalle uno de estos códigos. En este caso, nos centraremos en el código 05, ya que el código 04 es un poco más sencillo.
Bien, entonces veamos cómo trabaja este código 05. En primer lugar, tenemos en la línea seis la declaración de un array puramente dinámico, que deberá asignarse en algún momento, esto para poder usar la memoria como depósito de información.
Suponiendo que no sepamos si el array de la línea seis fue inicializado, usamos la línea ocho para comprobar si existe algún elemento en el array. Recuerda: Es un array puramente dinámico. Si lo inicializas directamente en la línea seis, esta línea ocho lo detectará. Incluso si se inicializa entre la línea seis y la línea ocho, esta línea ocho también lo detectará. Sin embargo, si la inicialización se hace exactamente en la línea seis, donde se declara el array, surgirán otros problemas aquí. Prueba a hacerlo para comprender qué tipo de problema surgirá. Así practicarás y ganarás experiencia con arrays.
De todos modos, si existe algún elemento en el array, se ejecutarán las líneas 10 y 11, mostrando precisamente que hay elementos en el array. Si no se ha inicializado, se mostrará en el terminal el mensaje de la línea trece.
Ahora viene la parte que hace que todo sea bastante interesante, esto ocurre precisamente en la línea 14, que llama a la función de la línea 27. Observa que, hasta este momento, el array AÚN NO HA SIDO INICIALIZADO. Solo se inicializará en el momento en que se ejecute la línea 31, esto se debe a que es precisamente esta línea la que llama al procedimiento visto en la línea 20. En la línea 24, este procedimiento inicializará el array dinámico creado en la línea 6. Ahora, observa que para hacer esto estamos usando un array estático del tipo ROM, que se ve en la línea 22. Sé que esto parece muy confuso y difícil de entender, pero si miras la función ArrayCopy de la biblioteca estándar, entenderás por qué funciona. Básicamente, esta función copia un array dentro de otro array, y se utiliza en una enorme cantidad de situaciones en aplicaciones reales. Justo después de hacer esto, entraremos en el bucle de la línea 33. En ese momento, realizamos los cálculos para tener una respuesta y volver a la línea 14,
pero antes de volver a la línea 14, usamos la línea 36 para añadir un nuevo elemento al array declarado en la línea 6 y que fue inicializado en la línea 24, que es la parte interesante. Si no inicializas el array, debido a la eliminación de la línea 31 del código, esta función Possibilities retornará un valor igual al de la línea 29, esto se debe a que el bucle de la línea 33 no se ejecutará. Sin embargo, cuando observes el contenido del array declarado en la línea seis, verás que hay un elemento en el array, y este elemento tendrá el valor indicado en la línea 37.
De hecho, es necesario experimentar esto en la práctica para comprender lo que se ha explicado aquí. Así que, como he mencionado, practica y utiliza el contenido del anexo para entender mejor cómo funcionan las cosas.
Consideraciones finales
En este artículo, las cosas se pusieron mucho más divertidas que en los artículos anteriores, esto se debe a que aquí comenzamos a explorar nuevas posibilidades de uso de conceptos explicados desde el primer artículo. Sé que para quien ha llegado hasta aquí sin haber visto los demás artículos, mucho de lo que se ha mostrado puede parecer extremadamente complejo y confuso. Sin embargo, quien ha practicado y estudiado cada uno de los artículos sabe muy bien, que este contenido es bastante interesante. Y este contenido abre diversas posibilidades, entre ellas una que se trató de manera muy superficial en otro artículo más antiguo.
No obstante, en el próximo artículo, haremos que algo ya visto se vuelva tan común en tu día a día, que ni siquiera notarás que te estás convirtiendo en un programador excelente. Con los conceptos correctos y sabiendo cómo aplicarlos, te liberarás de las ataduras en las que muchos siguen atrapados, precisamente por no entender los conceptos ligados a la programación, sino limitarse a copiar y pegar código. Así que diviértete con los archivos del anexo, y nos vemos en el próximo artículo.
Traducción del portugués realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/pt/articles/15473





- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso