Suggestions pour la syntaxe MQL

 

J'ai décidé de créer un tel sujet, car selon mes observations, le développement de la syntaxe MQL stagne depuis longtemps, je ne vois pas d'amélioration du langage ces dernières années. Je ne sais pas si les développeurs vont travailler sur MQL, mais de nombreuses fonctionnalités sont très manquantes, dont certaines sont absolument nécessaires.

Dans ce fil de discussion, j'ai décidé de dresser une liste de mes principales demandes. Je vais d'abord donner ma liste, peut-être que quelqu'un ajoutera quelque chose d'autre, et ensuite peut-être que les développeurs se joindront à moi et partageront leur vision, ce serait bien.

Cette liste, je la mets par ordre d'importance (comme je la vois), mais pas par ordre de mes priorités personnelles, c'est-à-dire que je mets d'abord les choses les plus fondamentales et indispensables pour la langue. Prendre comme référence les fonctionnalités de C++ et C#


1. Travailler avec les types : typedef, decltype, auto

Il s'agit en fait d'une fonctionnalité de base, du moins les deux premiers spécificateurs. Les opérations de nommage et de saut de type sont créées non seulement pour la commodité, mais aussi pour la fiabilité et la flexibilité du code. Si vous définissez une valeur fixe sur des types concrets de variables utilisées à différents endroits, vous aurez des problèmes lorsque vous devrez changer l'un des types.

Beaucoup d'entre vous connaissent déjà le typedef, mais malheureusement, il s'agit encore d'une souche qui ne fonctionne qu'avec les pointeurs de fonction. Quant au decltype, laissez-moi le clarifier pour ceux qui ne le connaissent pas : il renvoie le type de l'expression qui lui est passée en argument, ce qui permet une certaine flexibilité pour définir des types de variables ou de fonctions basés sur d'autres types :

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

Soit en utilisant le typedef :

typedef int type;
type a= 100;
type b = a;
Ou par exemple dans le cas de types longs et complexes (par exemple ClasseA<ClasseB<ClasseC,ClasseD<ClasseE> >) - ici c'est une aubaine de l'envelopper dans le typedef

En C#, using est utilisé à la place de typedef.

La seule chose possible est la variante croustillante de la définition de type par define, qui pose quelques problèmes.


2. Espaces de noms : namespace

Ce sujet a déjà été abordé récemment. Pour moi, il est vraiment étrange qu'elle n'ait pas encore été implémentée, car c'est une fonctionnalité indispensable du langage. Surtout si l'on considère la tendance à la communauté, à la base de données et au développement de groupe. Dans ce cas, le problème de la correspondance des noms devient très pertinent.

Ils ont cité l'exemple suivant : même lorsque le nom d'une variable locale dans une fonction est identique au nom d'un type défini dans un autre fichier, le compilateur génère une erreur. C'est un scandale.

En général, il n'est pas bon d'avoir tout en une seule pile dans un seul espace.


Sans elle, les typesdéfinis par l'utilisateur sont intrinsèquement incomplets et la flexibilité est fortement réduite.
Supposons que vous ayez créé une structure DATETIME qui stocke l'heure, et que vous vouliez pouvoir l'utiliser comme datetime, en la passant à toutes les fonctions qui acceptent datetime, ainsi qu'en l'utilisant dans des expressions avec datetime.
En général, cela se fait simplement : surchargez le constructeur et l'instruction cast avec le type correspondant, et vous obtenez une compatibilité totale de notre structure avec ce type :

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

Mais en MQL, il est nécessaire de créer une méthode séparée to_datetime() et d'écrire son appel partout. Ou bien l'appel de la fonction cible de DATETIME & type doit être surchargé ce qui n'augmente pas non plus le confort et la flexibilité.


4. Interfaces multiples... Eh bien, il y a déjà eu beaucoup de rumeurs et de discussions à ce sujet (je me souviens qu'il y a trois ans, ils ont écrit dans le service-desk que le travail était en cours), mais ça traîne... Si cela se produit.



5. Lesupport des interfaces pour les structures est nécessaire pour un travail unifié avec la POO. Actuellement, nous devons souvent fabriquer des béquilles.

Cette fonctionnalité pourrait être mise en œuvre de deux manières : soit comme en C# - via l'empaquetage/dépaquetage (boxing), soit de manière plus flexible - en créant un handle dynamique pour la structure liée à un descripteur d'objet dynamique qui contient la structure - ce serait plus efficace, et vous pourriez créer des pointeurs vers des structures et d'autres types de données, ce qui augmenterait la flexibilité.


6. Possibilité de passer les structures par valeur, ce qui est important lors du passage des petites structures (DATETIME de l'exemple ci-dessus), ce qui permettrait des conversions flexibles à la volée d'un type à l'autre, si le constructeur de la structure supporte ce type. Il n'y a pas cette flexibilité lors d'un transfert par référence, bien que si des interfaces pour les structures sont mises en œuvre, cela deviendra moins pertinent.


7. Possibilité de spécifier les paramètres numériques du modèle :

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

Quant au deuxième exemple, dans MQL4, vous pouvez vous en passer, car les fonctions acceptent des tableaux de n'importe quelle dimension. Et dans MQL5, tout est beaucoup plus compliqué avec les tableaux multidimensionnels.


8. Spécialisation des modèles (implémentation séparée pour des types spécifiques).

Exemple de fonction :
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>()); }

Exemple avec une classe :
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();
}



Et ainsi de suite pour les petites choses :


9. La possibilité de couler (explicitement ou implicitement) un tableau de pointeurs vers un tableau de pointeurs de base. Dans les anciennes versions, cela fonctionnait et était très pratique :

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

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

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

Nous devons maintenant recopier le tableau dans un nouveau tableau, puis le recopier à nouveau, un gaspillage d'efforts.

10. Moulage de référence d'objet :(type&)objet

Ceci est nécessaire pour pouvoir passer un objet référencé à une fonction. Dans l'exemple suivant, un objet de la classe B doit être écrit dans un fichier comme un objet de la classe de base A, mais cela ne peut pas être fait maintenant, une fonction intermédiaire doit être créée ou l'objet doit être copié dans un nouvel objet.

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. initialiser les tableaux et les structures non seulement avec des constantes, mais aussi avec des expressions quelconques. Cela réduit et simplifie considérablement le code dans de tels cas :

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


12. Possibilité de convertir explicitement un pointeur en une valeur numérique.

Cela permettrait de trier les tableaux de pointeurs par leurs valeurs afin de trouver rapidement le pointeur nécessaire par une recherche binaire ou en créant une table de hachage. Maintenant, il n'est possible d'obtenir une valeur numérique qu'en la convertissant en une forme textuelle, ce qui tue l'idée entière.

13. Définition des paramètres par défaut des modèles

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;
 

À mon avis, très peu de personnes ont besoin de tout cela.

A en juger par le code dans Kodobase - 95% des utilisateurs utilisent très peu la POO. Et pour les 5% restants de la majorité - toutes ces fonctionnalités sont peu utilisées. Certes, elles sont agréables et peuvent même être utiles, mais toutes ces améliorations ne sont pas vraiment nécessaires, à mon avis.

 
Georgiy Merts:

À mon avis, très peu de personnes ont besoin de tout cela.

A en juger par le code dans Kodobase - 95% des utilisateurs utilisent très mal la POO. Et parmi les 5% restants, la plupart n'utilisent pas beaucoup ces fonctionnalités. Bien sûr, elles sont agréables et peuvent même être utiles, mais à mon avis, toutes ces améliorations ne sont pas vraiment nécessaires.

Oui, je comprends, mais en plus de kodobase il y a Freelance et Market, et là MQ doit être intéressé par la qualité des produits. Et la qualité du langage affecte la qualité et la rapidité du développement et du débogage d'une manière ou d'une autre.

Si l'on parle de pourcentages comme ça, alors pourquoi MQL5 a été créé en premier lieu ? Nous serions toujours assis dans le vieux MQL4 hardcore où la POO ou toute autre chose n'est pas nécessaire... 99% des utilisateurs en sont satisfaits)

Peut-être que les programmeurs normaux ne vont pas vers MQL précisément parce que c'est encore un langage incomplet.

 
Alexey Navoykov:

J'ai décidé de créer un tel sujet, car selon mes observations, le développement de la syntaxe MQL stagne depuis longtemps, aucune amélioration du langage au cours des dernières années. Je ne sais pas si les développeurs vont travailler sur MQL du tout, mais de nombreuses fonctionnalités sont vraiment manquantes, dont certaines sont d'une importance critique.

Dans ce fil de discussion, j'ai décidé de dresser une liste de mes principales demandes. Je vais d'abord donner ma liste, peut-être que quelqu'un ajoutera quelque chose d'autre, et ensuite peut-être que les développeurs se joindront à moi et partageront leur vision, ce serait bien.

J'ai classé cette liste par ordre d'importance (comme je le vois), mais pas dans l'ordre de mes priorités personnelles, c'est-à-dire que j'ai mis en premier les choses les plus fondamentales et indispensables pour la langue. Prendre comme référence les fonctionnalités de C++ et C#


1. Travailler avec les types : typedef, decltype, auto

Il s'agit en fait d'une fonctionnalité de base, du moins les deux premiers spécificateurs. Les opérations de nommage et de saut de type sont conçues non seulement pour la commodité, mais aussi pour la fiabilité et la flexibilité du code. Si vous définissez une valeur fixe sur des types concrets de variables utilisées à différents endroits, vous aurez des problèmes lorsque vous devrez changer l'un des types.

Beaucoup d'entre vous connaissent déjà le typedef, mais malheureusement, il s'agit encore d'une souche qui ne fonctionne qu'avec les pointeurs de fonction. Quant au decltype, laissez-moi le clarifier pour ceux qui ne le connaissent pas : il renvoie le type de l'expression qui lui est passée en argument, ce qui permet une certaine flexibilité pour définir des types de variables ou de fonctions basés sur d'autres types :

Soit en utilisant le typedef :

Ou par exemple dans le cas de types longs et complexes (par exemple ClasseA<ClasseB<ClasseC,ClasseD<ClasseE> >) - ici c'est une bonne idée de l'envelopper dans un typedef

En C#, using est utilisé à la place de typedef.

La seule chose possible est la variante croustillante de la définition de type par define, qui pose quelques problèmes.


2. Espaces de noms : namespace

Ce sujet a déjà été abordé récemment. Pour moi, il est vraiment étrange qu'elle n'ait pas encore été implémentée, car c'est une fonctionnalité indispensable du langage. Surtout si l'on considère la tendance à la communauté, à la base de données et au développement de groupe. Dans ce cas, le problème de la correspondance des noms devient très pertinent.

Ils ont cité l'exemple suivant : même lorsque le nom d'une variable locale dans une fonction est identique au nom d'un type défini dans un autre fichier, le compilateur génère une erreur. C'est un scandale.

En général, il n'est pas bon d'avoir tout en une seule pile dans un seul espace.


Sans elle, les typesdéfinis par l'utilisateur sont intrinsèquement incomplets et la flexibilité est fortement réduite.
Supposons que vous ayez créé une structure DATETIME qui stocke l'heure, et que vous vouliez pouvoir l'utiliser comme datetime, en la passant à toutes les fonctions qui acceptent datetime, ainsi qu'en l'utilisant dans des expressions avec datetime.
En général, cela se fait simplement : surchargez le constructeur et l'instruction cast avec le type correspondant, et vous obtenez une compatibilité totale de notre structure avec ce type :

Mais en MQL, il est nécessaire de créer une méthode séparée to_datetime() et d'écrire son appel partout. Ou bien l'appel de la fonction cible de DATETIME & type doit être surchargé ce qui n'augmente pas non plus le confort et la flexibilité.


4. Interfaces multiples... Eh bien, il y a déjà eu beaucoup de rumeurs et de discussions à ce sujet (je me souviens qu'il y a trois ans, ils ont écrit dans le service-desk que le travail était en cours), mais ça traîne... Si cela se produit.



5. Lesupport des interfaces pour les structures est nécessaire pour un travail unifié avec la POO. Actuellement, nous devons souvent fabriquer des béquilles.

Cette fonctionnalité pourrait être mise en œuvre de deux manières : soit comme en C# - via l'empaquetage/dépaquetage (boxing), soit de manière plus flexible - en créant un handle dynamique pour la structure liée à un descripteur d'objet dynamique qui contient la structure - ce serait plus efficace, et vous pourriez créer des pointeurs vers des structures et d'autres types de données, ce qui augmenterait la flexibilité.


6. Possibilité de passer les structures par valeur, ce qui est important lors du passage des petites structures (DATETIME de l'exemple ci-dessus), ce qui permettrait des conversions flexibles à la volée d'un type à l'autre, si le constructeur de la structure supporte ce type. Lors d'un transfert par référence, cette flexibilité n'existe pas, bien que si des interfaces pour les structures sont implémentées, cela deviendra moins pertinent.


7. Possibilité de spécifier les paramètres numériques du modèle :

Quant au deuxième exemple, dans MQL4, vous pouvez vous en passer, car les fonctions acceptent des tableaux de n'importe quelle dimension. Et dans MQL5, tout est beaucoup plus compliqué avec les tableaux multidimensionnels.


8. Spécialisation des modèles (implémentation séparée pour des types spécifiques).

Exemple de fonction :

Exemple avec une classe :



Et ainsi de suite pour les petites choses :


9. La possibilité de couler (explicitement ou implicitement) un tableau de pointeurs vers un tableau de pointeurs de base. Dans les anciennes versions, cela fonctionnait et était très pratique :

Nous devons maintenant recopier le tableau dans un nouveau tableau, puis le recopier à nouveau, un gaspillage d'efforts.

10. Moulage de référence d'objet :(type&)objet

Ceci est nécessaire pour pouvoir passer un objet référencé à une fonction. Dans l'exemple suivant, un objet de la classe B doit être écrit dans un fichier comme un objet de la classe de base A, mais cela ne peut pas être fait maintenant, une fonction intermédiaire doit être créée ou l'objet doit être copié dans un nouvel objet.


11. initialiser les tableaux et les structures non seulement avec des constantes, mais aussi avec des expressions quelconques. Cela réduit et simplifie considérablement le code dans de tels cas :


12. Possibilité de convertir explicitement un pointeur en une valeur numérique.

Cela permettrait de trier les tableaux de pointeurs par leurs valeurs afin de trouver rapidement le pointeur nécessaire par une recherche binaire ou en créant une table de hachage. Maintenant, il n'est possible d'obtenir une valeur numérique qu'en la convertissant en une forme textuelle, ce qui tue l'idée entière.

13. Définition des paramètres par défaut des modèles

Je soutiens.

 
Georgiy Merts:

À mon avis, un très petit nombre de personnes ont besoin de tout cela.

A en juger par le code dans Kodobase - 95% des utilisateurs utilisent très peu la POO. Et pour les 5% restants - la plus grande partie - toutes ces fonctionnalités sont peu utilisées. Bien sûr, elles sont agréables, et peuvent même être utiles, mais il n'y a pas grand besoin de toutes ces améliorations, à mon avis.

Ce petit nombre de personnes peut écrire des bibliothèques que tout le monde utilisera.

 

14. Permet de passer un objet temporaire si l'argument de la fonction est une référence 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. le mot-clé ami.

Pour certaines classes, vous voulez donner l'accès aux membres privés, à une classe particulière, mais pas à toutes.

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. annuler une variable lors de l'appel explicite du constructeur pour les types intégrés.

Cela s'avère utile pour les modèles.

   double x;         // Не инициализирована
   double y();       // Инициализирована нулём
   double z = 5.0;   // Инициализирована 5.0
 
Ils n'ont même pas de panneaux indicateurs) quoi de plus fondamental)
 
Alexey Navoykov:

J'ai décidé de créer un tel sujet, car selon mes observations, le développement de la syntaxe MQL stagne depuis longtemps, aucune amélioration n'a été apportée au langage au cours des dernières années. Je ne sais pas si les développeurs vont travailler sur MQL du tout, mais de nombreuses fonctionnalités sont vraiment manquantes, certaines d'entre elles sont absolument nécessaires.

Dans ce fil de discussion, j'ai décidé de compiler les principaux souhaits, d'abord je vais donner ma liste, peut-être que quelqu'un ajoutera quelque chose d'autre. Et puis peut-être que les développeurs se connecteront et exprimeront leur vision, ce serait génial.

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

Attendez-vous à un bannissement, la critique des écritures n'est pas autorisée :)

PS : Les améliorations étaient, pas si globales, mais il y avait

 
secret:
Ils n'ont même pas de pointeurs) ce qui pourrait être plus fondamental)

Il n'y en aura pas, la langue est gérée, mais sans GC.

Sharp les a aussi uniquement en mode non sécurisé.

 
Alexey Navoykov:

Oui, je comprends, mais en plus de kodobase il y a Freelance et Market, et là MQ doit être intéressé par la qualité des produits. Et la qualité du langage affecte la qualité et la rapidité du développement et du débogage d'une manière ou d'une autre.

Si l'on parle de pourcentages comme ça, alors pourquoi MQL5 a été créé en premier lieu ? Nous serions toujours assis dans le vieux MQL4 hardcore où la POO ou toute autre chose n'est pas nécessaire... 99% des utilisateurs en sont satisfaits)

Peut-être que les programmeurs normaux ne vont pas vers MQL parce que c'est encore un langage incomplet.

Kodobase n'est pas du tout une poubelle à 95%. Cela fait longtemps que je n'ai pas vu de nouvelles versions de MT5. Renat, je me souviens, a promis quelque chose de global dans la nouvelle version.

 
Alexey Volchanskiy:

PS : Il y a eu des améliorations, pas si globales, mais il y a eu

La dernière chose dont je me souviens était un opérateur de copie implicite permettant de copier des objets dynamiques, mais ce n'est rien, d'autant que beaucoup de temps a passé depuis.