Sugerencias para la sintaxis MQL

 

Decidí crear este tema, porque según mis observaciones, el desarrollo de la sintaxis de MQL se ha estancado durante mucho tiempo, no puedo ver ninguna mejora del lenguaje en los últimos años. No sé si los desarrolladores van a trabajar en MQL, pero muchas de las características son muy desaparecidas, algunas de las cuales son críticamente necesarias.

En este hilo he decidido recopilar una lista de mis principales peticiones. Primero daré mi lista, quizás alguien añada algo más, y luego quizás los desarrolladores se unan y compartan su visión, estaría bien.

Esta lista la he puesto en orden de importancia (según yo lo veo), pero no en orden de mis prioridades personales. Es decir, primero pongo las cosas más fundamentales e imprescindibles para el idioma. Tome como referencia la funcionalidad de C++ y C#


1. Trabajo con tipos: typedef, decltype, auto

Las operaciones de nombramiento y salto de tipo se crean no sólo por la comodidad, sino también por la fiabilidad y flexibilidad del código. Si se establece un valor fijo en tipos concretos de variables utilizadas en diferentes lugares, se tendrán problemas cuando se necesite cambiar alguno de los tipos.

Muchos de vosotros ya estáis familiarizados con typedef, pero desgraciadamente sigue siendo un tocho que sólo funciona con punteros a funciones. En cuanto a decltype, permíteme que lo aclare para los que no estén familiarizados con él: devuelve el tipo de expresión que se le pasa como argumento, permitiendo flexibilidad para definir tipos de variables o funciones basados en otros tipos:

int a=100;
//...
decltype(a) b= a;

Ya sea usando typedef:

typedef int type;
type a= 100;
type b = a;
O, por ejemplo, en el caso de tipos largos y complejos (por ejemplo, ClassA< ClassB< ClassC,ClassD<ClassE> >) - aquí es un regalo del cielo envolverlo en typedef

En C#, se utiliza using en lugar de typedef.

Lo único posible es la variante crujiente de la definición de tipos a través de define, que está plagada de algunos problemas.


2. Espacios de nombres: namespace

Este tema ya se ha debatido recientemente. Para mí es realmente extraño que no se haya implementado todavía, porque es una característica imprescindible del lenguaje. Sobre todo si se tiene en cuenta la tendencia a la comunidad, la codobase y el desarrollo en grupo. En este caso, el problema de la coincidencia de nombres se vuelve muy relevante.

Citaron un ejemplo de que incluso cuando el nombre de una variable local dentro de alguna función es idéntico al nombre de un tipo definido en otro archivo, el compilador generará un error. Es una barbaridad.

En general, es un error tener todo en una pila en un solo espacio.


Sin ella, los tiposdefinidos por el usuario son intrínsecamente incompletos y la flexibilidad se reduce considerablemente.
Supongamos que has creado una estructura DATETIME que almacena la hora, y quieres poder usarla como datetime, pasándola a todas las funciones que aceptan datetime, así como usándola en expresiones con datetime.
Normalmente esto se hace de forma sencilla: se sobrecarga el constructor y la sentencia cast con el tipo correspondiente, y se obtiene una compatibilidad total de nuestra estructura con este tipo:

struct DATETIME
{
  DATETIME(datetime time) { ... }
  operator datetime() const { return ...; }
};

Pero en MQL en cambio es necesario crear un método separado to_datetime() y escribir su llamada en todas partes. O la llamada de la función de destino de DATETIME & type debe ser sobrecargada, lo que tampoco aumenta la comodidad y la flexibilidad.


4. Múltiples interfaces... Bueno, ya ha habido muchos rumores y conversaciones al respecto (recuerdo que hace tres años escribieron en service-desk que el trabajo está en marcha), pero se está alargando... Si es que se está llevando a cabo.



5. Elsoporte de interfaces para estructuras es necesario para el trabajo unificado con OOP. En la actualidad, a menudo tenemos que hacer muletas.

Esta funcionalidad podría implementarse de dos maneras: como en C# - a través del empaquetado/desempaquetado (boxing), o de manera más flexible - creando un handle dinámico para la estructura vinculado a un descriptor de objeto dinámico que contenga la estructura - sería más eficiente, además de poder crear punteros a estructuras y otros tipos de datos, lo que aumentaría la flexibilidad.


6. Posibilidad de pasar las estructuras por valor, lo que es importante cuando se pasan las estructuras pequeñas (DATETIME del ejemplo anterior), lo que permitiría realizar conversiones flexibles sobre la marcha de un tipo a otro, si el constructor de la estructura soporta este tipo. No existe tal flexibilidad cuando se transfiere por referencia, aunque si se implementan interfaces para estructuras, será menos relevante.


7. Posibilidad de especificar los parámetros numéricos de la plantilla:

template<int N>
struct A
{
  char a[N];
};

A<100> a;
template<int N>
void f(int &arr[][N]) {  }

void start()
{
  int a[][5];
  f(a);
}

En cuanto al segundo ejemplo, en MQL4 se puede prescindir de él, porque allí las funciones aceptan arrays de cualquier dimensión. Y en MQL5, todo es mucho más complicado con las matrices multidimensionales.


8. Especialización de las plantillas (implementación separada para tipos específicos).

Ejemplo de función:
struct A
{
  double _value;
 
  template<typename T>
   T      ToType() { return (T)round(_value); }  
  template<>
   double ToType() { return _value; }
  template<>
   float  ToType() { return (float)_value; }
  template<>
   string ToType() { return DoubleToString(_value, 2); }
};

void f(A& a) { Print(a.ToType<string>()); }

Ejemplo con una clase:
template<typename T>
struct CArrayBase    // Базовый класс массива
{
  T _data[];
  int Size()          { return ArraySize(_data); }
  T operator[](int i) { return _data[i]; }
};

template<typename T>
struct CArray : CArrayBase<T> { };  // Основной класс массива

template<>
struct CArray<double> : CArrayBase<double>  // Специализация класса для массива double
{
  double Sum() { double sum=0;  for (int i=0; i<Size(); i++) sum+=_data[i];  return sum; } 
}; 

template<typename T>
struct CArray<T*> : CArrayBase<T*>  // Специализация класса для массива указателей
{
  void DeleteObjects() { for (int i=0; i<Size(); i++) { delete _data[i]; _data[i]=NULL; } }    
};

void start()
{
  CArray<double> arr1;
  arr1.Sum();  

  class A { };
  
  CArray<A*> arr2;
  arr2.DeleteObjects();
}



Y así en las pequeñas cosas:


9. La posibilidad de fundir (explícita o implícitamente) un array de punteros a un array de punteros base. En las antiguas construcciones esto funcionaba, y era muy conveniente:

interface I { };
class A : I { };

void f(I* &Array[]) {  }

void Main(A* &array[]) { f(array); }

Ahora tenemos que volver a copiar la matriz en una nueva, y luego de nuevo, un esfuerzo desperdiciado.

10. casting de referencias a objetos:(tipo&)objeto

Esto es necesario para poder pasar un objeto referenciado a una función. El siguiente ejemplo requiere que un objeto de la clase B se escriba en un archivo como un objeto de la clase base A, pero esto no se puede hacer ahora, hay que crear una función intermedia o copiar el objeto en un nuevo objeto.

struct A { int a; };

struct B : A { int b; };

B b;

void main()
{
  int h= FileOpen("MyFile",FILE_BIN|FILE_WRITE);
  FileWriteStruct(h, (A&)b);  // '&' - unexpected token
  FileClose(h); 
}


11. inicializar arrays y estructuras no sólo con constantes, sino con cualquier expresión. Esto reduce y simplifica significativamente el código en estos casos:

void f(int a, int b, int c, int d, int e, int f)
{
  int arr[]= { a, b, c, d, e, f };
 //......
}


12. Posibilidad de lanzar explícitamente un puntero a un valor numérico.

Permitiría ordenar las matrices de punteros por sus valores para encontrar rápidamente el puntero necesario a través de una búsqueda binaria o creando una tabla hash. Ahora es posible obtener un valor numérico sólo a través de la conversión a una forma textual, lo que mata toda la idea.

13. Configuración de los parámetros de la plantilla por defecto

template<typename T>
struct DefaultConstructor { static T* New() { return new T; } };

template<typename T, typename TConstructor=DefaultConstructor<T>>
struct A
{
  T* data;
  A() { data= TConstructor::New(); }
 ~A() { delete data; }
};

class B { };

A<B> a;
 

En mi opinión, muy pocas personas necesitan todo esto.

A juzgar por el código de Kodobase, el 95% de los usuarios utilizan muy poco la POO. Y del 5% restante de la mayor parte - todas estas características son poco utilizadas. Ciertamente, son agradables e incluso pueden ser útiles, pero no hay gran necesidad en todas estas mejoras, en mi opinión.

 
Georgiy Merts:

En mi opinión, muy pocas personas necesitan todo esto.

A juzgar por el código de Kodobase, el 95% de los usuarios utilizan la programación orientada a objetos de forma muy deficiente. Y del 5% restante, la mayoría no utiliza mucho estas funciones. Por supuesto, son agradables e incluso pueden ser útiles, pero no hay gran necesidad en todas estas mejoras en mi opinión.

Sí, lo entiendo, pero además de kodobase existen Freelance y Market, y ahí MQ debe interesarse por la calidad de los productos. Y la calidad del lenguaje afecta a la calidad y velocidad de desarrollo y depuración de una u otra manera.

Si se habla de los porcentajes así, entonces ¿por qué se creó MQL5 en primer lugar? Todavía estaríamos sentados en el viejo y duro MQL4 donde la OOP o cualquier otra cosa no es necesaria... El 99% de los usuarios estaban contentos con él )

Tal vez los programadores normales no vayan a MQL precisamente porque todavía es un lenguaje incompleto.

 
Alexey Navoykov:

Decidí crear este tema, ya que según mis observaciones, el desarrollo de la sintaxis de MQL se ha estancado durante mucho tiempo, no hay mejoras en el lenguaje en los últimos años. No sé si los desarrolladores van a trabajar en MQL más, pero muchas características son muy falta, algunos de los cuales son críticamente necesarios.

En este hilo he decidido recopilar una lista de mis principales peticiones. Primero daré mi lista, quizás alguien añada algo más, y luego quizás los desarrolladores se unan y compartan su visión, estaría bien.

Esta lista la he puesto en orden de importancia (según yo lo veo), pero no en orden de mis prioridades personales. Es decir, primero pongo las cosas más fundamentales e imprescindibles para el idioma. Tome como referencia la funcionalidad de C++ y C#


1. Trabajo con tipos: typedef, decltype, auto

Las operaciones de nombramiento y salto de tipo se crean no sólo por la comodidad, sino también por la fiabilidad y flexibilidad del código. Si se establece un valor fijo en tipos concretos de variables utilizadas en diferentes lugares, se tendrán problemas cuando se necesite cambiar alguno de los tipos.

Muchos de vosotros ya estáis familiarizados con typedef, pero desgraciadamente sigue siendo un tocho que sólo funciona con punteros a funciones. En cuanto a decltype, permíteme que lo aclare para los que no estén familiarizados con él: devuelve el tipo de expresión que se le pasa como argumento, permitiendo flexibilidad para definir tipos de variables o funciones basados en otros tipos:

Ya sea usando typedef:

O, por ejemplo, en el caso de tipos largos y complejos (por ejemplo, ClassA< ClassB< ClassC,ClassD<ClassE> >) - aquí es un regalo del cielo envolverlo en typedef

En C#, se utiliza using en lugar de typedef.

Lo único posible es la variante crujiente de la definición de tipos a través de define, que está plagada de algunos problemas.


2. Espacios de nombres: namespace

Este tema ya se ha debatido recientemente. Para mí es realmente extraño que no se haya implementado todavía, porque es una característica imprescindible del lenguaje. Sobre todo si se tiene en cuenta la tendencia a la comunidad, la codobase y el desarrollo en grupo. En este caso, el problema de la coincidencia de nombres se vuelve muy relevante.

Citaron un ejemplo de que incluso cuando el nombre de una variable local dentro de alguna función es idéntico al nombre de un tipo definido en otro archivo, el compilador generará un error. Es una barbaridad.

En general, es un error tener todo en una pila en un solo espacio.


Sin ella, los tiposdefinidos por el usuario son intrínsecamente incompletos y la flexibilidad se reduce considerablemente.
Supongamos que has creado una estructura DATETIME que almacena la hora, y quieres poder usarla como datetime, pasándola a todas las funciones que aceptan datetime, así como usándola en expresiones con datetime.
Normalmente esto se hace de forma sencilla: se sobrecarga el constructor y la sentencia cast con el tipo correspondiente, y se obtiene una compatibilidad total de nuestra estructura con este tipo:

Pero en MQL en cambio es necesario crear un método separado to_datetime() y escribir su llamada en todas partes. O la llamada de la función de destino de DATETIME & type debe ser sobrecargada, lo que tampoco aumenta la comodidad y la flexibilidad.


4. Múltiples interfaces... Bueno, ya ha habido muchos rumores y conversaciones al respecto (recuerdo que hace tres años escribieron en service-desk que el trabajo está en marcha), pero se está alargando... Si es que se está llevando a cabo.



5. Elsoporte de interfaces para estructuras es necesario para el trabajo unificado con OOP. En la actualidad, a menudo tenemos que hacer muletas.

Esta funcionalidad podría implementarse de dos maneras: como en C# - a través del empaquetado/desempaquetado (boxing), o de una manera más flexible - creando un manejador dinámico para la estructura vinculado a un descriptor de objeto dinámico que contenga la estructura - sería más eficiente, además se podrían crear punteros a estructuras y otros tipos de datos, lo que aumentaría la flexibilidad.


6. Posibilidad de pasar las estructuras por valor, lo que es importante cuando se pasan las estructuras pequeñas (DATETIME del ejemplo anterior), lo que permitiría realizar conversiones flexibles sobre la marcha de un tipo a otro, si el constructor de la estructura soporta este tipo. Cuando se transfiere por referencia, no existe esa flexibilidad. Aunque si se implementan interfaces para las estructuras, será menos relevante.


7. Posibilidad de especificar los parámetros numéricos de la plantilla:

En cuanto al segundo ejemplo, en MQL4 se puede prescindir de él, porque allí las funciones aceptan arrays de cualquier dimensión. Y en MQL5, todo es mucho más complicado con las matrices multidimensionales.


8. Especialización de las plantillas (implementación separada para tipos específicos).

Ejemplo de función:

Ejemplo con una clase:



Y así en las pequeñas cosas:


9. La posibilidad de fundir (explícita o implícitamente) un array de punteros a un array de punteros base. En las antiguas construcciones esto funcionaba, y era muy conveniente:

Ahora tenemos que volver a copiar la matriz en una nueva, y luego de nuevo, un esfuerzo desperdiciado.

10. casting de referencias a objetos:(tipo&)objeto

Esto es necesario para poder pasar un objeto referenciado a una función. El siguiente ejemplo requiere que un objeto de la clase B se escriba en un archivo como un objeto de la clase base A, pero esto no se puede hacer ahora, hay que crear una función intermedia o copiar el objeto en un nuevo objeto.


11. inicializar arrays y estructuras no sólo con constantes, sino con cualquier expresión. Esto reduce y simplifica significativamente el código en estos casos:


12. Posibilidad de lanzar explícitamente un puntero a un valor numérico.

Permitiría ordenar las matrices de punteros por sus valores para encontrar rápidamente el puntero necesario a través de una búsqueda binaria o creando una tabla hash. Ahora es posible obtener un valor numérico sólo a través de la conversión a una forma textual, lo que mata toda la idea.

13. Configuración de los parámetros de la plantilla por defecto

Yo apoyo.

 
Georgiy Merts:

En mi opinión, un número muy reducido de personas necesita todo esto.

A juzgar por el código en Kodobase, el 95% de los usuarios utilizan muy poco la POO. Y del 5% restante de la mayor parte - todas estas características son poco utilizadas. Por supuesto, son agradables, e incluso pueden ser útiles, pero no hay gran necesidad de todas estas mejoras, en mi opinión.

Este pequeño número de personas puede escribir bibliotecas que todo el mundo utilizará.

 

14. Permite pasar un objeto temporal si el argumento de la función es una referencia constante.

template< typename Type >
struct complex
{
   Type Re;
   Type Im;
   
   complex() : Re(), Im(){}
   complex( Type re, Type im ) : Re(re), Im(im){}
};

template< typename Type >
void Func( const Type& val )
{
}

void OnStart()
{
   Func( 5.0 );
   
   complex< double > C( 1.0, 5.0 );
   Func( C );
   
   Func( complex< double >( 2.0, 4.0 ) );
}

15. la palabra clave amigo.

Para algunas clases, quiere dar acceso a los miembros privados, a una clase en particular, pero no a todos.

template< typename Type >
class Matrix;

template< typename Type >
class MatrixData
{
   friend class Matrix< Type >;
   
   int mRefCount;
   int mRows;
   int mColumns;
   
   Type mArray[];
   
public:
   MatrixData();
   MatrixData( int rows, int cols );
};

template< typename Type >
class matrix
{
   MatrixData< Type >* mData;
   
public:
        Matrix();
        Matrix( int rows, int cols );
};

16. anular una variable al llamar explícitamente al constructor de los tipos incorporados

Esto resulta muy útil en las plantillas.

   double x;         // Не инициализирована
   double y();       // Инициализирована нулём
   double z = 5.0;   // Инициализирована 5.0
 
Ni siquiera tienen señalización) lo que podría ser más fundamental)
 
Alexey Navoykov:

Decidí crear este tema, porque según mi observación, el desarrollo de la sintaxis de MQL se ha estancado durante mucho tiempo, no se han hecho mejoras en el lenguaje durante los últimos años. No sé si los desarrolladores van a trabajar en MQL en absoluto, pero muchas características son realmente desaparecidas, algunas de ellas son críticamente necesarias.

En este hilo he decidido recopilar los principales deseos, primero daré mi lista, quizás alguien añada algo más. Y luego quizás los desarrolladores se conecten y expresen su visión, sería genial.

************

Espera un baneo, la crítica a las escrituras no está permitida :)

PS: Las mejoras fueron, no tan globales, pero hubo

 
secret:
Ni siquiera tienen punteros) lo que podría ser más fundamental)

No habrá ninguna, el lenguaje se gestiona, aunque sin GC

Sharp también los tiene sólo en modo inseguro.

 
Alexey Navoykov:

Sí, lo entiendo, pero además de kodobase existen Freelance y Market, y ahí MQ debe interesarse por la calidad de los productos. Y la calidad del lenguaje afecta a la calidad y velocidad de desarrollo y depuración de una u otra manera.

Si se habla de los porcentajes así, entonces ¿por qué se creó MQL5 en primer lugar? Todavía estaríamos sentados en el viejo y duro MQL4 donde la OOP o cualquier otra cosa no es necesaria... El 99% de los usuarios estaban contentos con él )

Tal vez los programadores normales no vayan a MQL porque todavía es un lenguaje incompleto.

Kodobase es una basura en un 95%. Hace tiempo que no veo nuevas versiones de MT5. Renat, recuerdo, prometió algo global en la nueva versión.

 
Alexey Volchanskiy:

PS: Hubo mejoras, no tan globales, pero sí

Lo último que recuerdo era un operador de copia implícita que permitía copiar objetos dinámicos, pero eso no es nada, sobre todo porque ha pasado mucho tiempo desde entonces.

Razón de la queja: