Vorschläge für die MQL-Syntax

 

Ich habe mich entschlossen, ein solches Thema zu erstellen, weil nach meinen Beobachtungen die Entwicklung der MQL-Syntax seit langem stagniert, ich kann keine Verbesserung der Sprache in den letzten Jahren sehen. Ich weiß nicht, ob die Entwickler an MQL arbeiten werden, aber viele der Funktionen fehlen sehr, von denen einige dringend benötigt werden.

In diesem Thread habe ich beschlossen, eine Liste meiner wichtigsten Wünsche zusammenzustellen. Ich werde zuerst meine Liste geben, vielleicht fügt jemand etwas anderes hinzu, und dann werden sich vielleicht die Entwickler anschließen und ihre Visionen mitteilen, das wäre schön.

Diese Liste habe ich nach Wichtigkeit geordnet (wie ich es sehe), aber nicht nach meinen persönlichen Prioritäten, d.h. ich habe die grundlegendsten und unverzichtbarsten Dinge für die Sprache zuerst aufgeführt. Nehmen Sie die Funktionalität von C++ und C# als Maßstab


1. Arbeiten mit Typen: typedef, decltype, auto

Dies ist eigentlich eine Grundfunktionalität, zumindest die ersten beiden Spezifizierer. Benennungs- und Typ-Hopping-Operationen dienen nicht nur der Bequemlichkeit, sondern auch der Zuverlässigkeit und Flexibilität des Codes. Wenn Sie für konkrete Variablentypen, die an verschiedenen Stellen verwendet werden, einen festen Wert festlegen, werden Sie Probleme bekommen, wenn Sie einen der Typen ändern müssen.

Viele von Ihnen sind bereits mit typedef vertraut, aber leider ist es immer noch ein Stumpf, der nur mit Funktionszeigern funktioniert. Was decltype betrifft, so möchte ich es für diejenigen, die damit nicht vertraut sind, klarstellen: Es gibt den Typ des Ausdrucks zurück, der ihm als Argument übergeben wurde, und ermöglicht die flexible Definition von Typen von Variablen oder Funktionen auf der Grundlage anderer Typen:

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

Entweder mit typedef:

typedef int type;
type a= 100;
type b = a;
Oder zum Beispiel im Fall von langen und komplexen Typen (z.B. ClassA< ClassB< ClassC,ClassD<ClassE> >) - hier ist es ein Geschenk des Himmels, sie in typedef zu verpacken

In C# wird using anstelle von typedef verwendet.

Das einzige, was möglich ist, ist die verkrustete Variante der Typdefinition durch define, die mit einigen Problemen behaftet ist.


2. Namespaces: Namensraum

Dieses Thema wurde bereits vor kurzem erörtert. Für mich ist es wirklich seltsam, warum es noch nicht implementiert wurde, denn es ist eine unverzichtbare Funktion der Sprache. Vor allem, wenn man den Trend zu Community, Codobase und Gruppenentwicklung bedenkt. In diesem Fall wird das Problem der Übereinstimmung von Namen sehr relevant.

Als Beispiel wurde angeführt, dass der Compiler selbst dann einen Fehler erzeugt, wenn der Name einer lokalen Variablen innerhalb einer Funktion mit dem Namen eines in einer anderen Datei definierten Typs identisch ist. Das ist ein Skandal.

Außerdem ist es falsch, alles an einem Ort auf einem Stapel zu haben.


Ohne sie sind diebenutzerdefinierten Typen von Natur aus unvollständig und die Flexibilität ist stark eingeschränkt.
Angenommen, Sie haben eine Struktur DATETIME erstellt, die die Zeit speichert, und Sie möchten sie als datetime verwenden können, indem Sie sie an alle Funktionen übergeben, die datetime akzeptieren, und sie in Ausdrücken mit datetime verwenden.
Normalerweise ist dies ganz einfach: Überladen Sie den Konstruktor und die Cast-Anweisung mit dem entsprechenden Typ, und Sie erhalten volle Kompatibilität unserer Struktur mit diesem Typ:

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

Aber in MQL ist es stattdessen notwendig, eine separate Methode to_datetime() zu erstellen und ihren Aufruf überall hinzuschreiben. Oder der Aufruf der Zielfunktion von DATETIME & type muss überladen werden, was den Komfort und die Flexibilität ebenfalls nicht erhöht.


4. Mehrere Schnittstellen: Nun, es gab bereits eine Menge Gerüchte und Gespräche darüber (ich erinnere mich, dass vor drei Jahren im Service-Desk darüber geschrieben wurde, dass daran gearbeitet wird), aber es war ein langer Prozess... Wenn sie überhaupt stattfindet.



5. DieUnterstützung von Schnittstellen für Strukturen ist für ein einheitliches Arbeiten mit OOP notwendig. Zurzeit müssen wir oft Krücken bauen.

Diese Funktionalität könnte auf zwei Arten implementiert werden: entweder wie in C# - über Packen/Entpacken (Boxing), oder flexibler - durch Erstellen eines dynamischen Handles für die Struktur, das mit einem Deskriptor des dynamischen Objekts verknüpft ist, das die Struktur enthält - das wäre effizienter, außerdem könnten Sie Zeiger auf Strukturen und andere Datentypen erstellen, was die Flexibilität erhöhen würde.


6. Möglichkeit, die Strukturen wertmäßig zu übergeben, was bei der Übergabe kleiner Strukturen (DATETIME aus dem obigen Beispiel) wichtig ist, was flexible Konvertierungen von einem Typ in einen anderen ermöglichen würde, wenn der Konstruktor der Struktur diesen Typ unterstützt. Bei der Übertragung per Referenz gibt es diese Flexibilität nicht, aber wenn Schnittstellen für Strukturen implementiert werden, wird dies weniger relevant.


7. Möglichkeit, numerische Parameter der Vorlage anzugeben:

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

Was das zweite Beispiel betrifft, so können Sie in MQL4 darauf verzichten, da die Funktionen dort Arrays beliebiger Dimension akzeptieren. Und in MQL5 ist alles noch viel komplizierter mit mehrdimensionalen Arrays.


8. Spezialisierung von Vorlagen (separate Implementierung für bestimmte Typen).

Beispiel für eine Funktion:
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>()); }

Beispiel mit einer Klasse:
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();
}



Und so geht es mit den kleinen Dingen weiter:


9. Die Möglichkeit des Castings (explizit oder implizit) eines Arrays von Zeigern in ein Array von Basiszeigern. In den alten Builds funktionierte dies und war sehr praktisch:

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

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

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

Jetzt müssen wir das Array in ein neues Array kopieren und dann wieder zurück - vergebliche Mühe.

10. Objektreferenz-Casting:(Typ&)Objekt

Dies ist notwendig, um ein referenziertes Objekt an eine Funktion übergeben zu können. Im folgenden Beispiel muss ein Objekt der Klasse B als Objekt der Basisklasse A in eine Datei geschrieben werden. Dies kann jedoch nicht sofort geschehen, sondern es muss eine Zwischenfunktion erstellt oder das Objekt in ein neues Objekt kopiert werden.

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. Arrays und Strukturen nicht nur mit Konstanten, sondern mit beliebigen Ausdrücken initialisieren. Dies reduziert und vereinfacht den Code in solchen Fällen erheblich:

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


12. Möglichkeit, einen Zeiger explizit auf einen numerischen Wert zu setzen.

Sie würde es ermöglichen, die Arrays von Zeigern nach ihren Werten zu sortieren, um den benötigten Zeiger durch eine binäre Suche oder durch die Erstellung einer Hash-Tabelle schnell zu finden. Jetzt ist es möglich, einen numerischen Wert nur durch Umwandlung in eine Textform zu erhalten, was die ganze Idee zunichte macht.

13. Einstellung von Standardvorlagenparametern

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;
 

Meiner Meinung nach brauchen nur sehr wenige Menschen all dies.

Nach dem Code in Kodobase zu urteilen, verwenden 95% der Benutzer OOP nur sehr wenig. Und von den verbleibenden 5 % der Mehrheit werden alle diese Funktionen kaum genutzt. Sicherlich sind sie angenehm und können sogar nützlich sein, aber meiner Meinung nach gibt es keine große Notwendigkeit für all diese Verbesserungen.

 
Georgiy Merts:

Meiner Meinung nach brauchen nur sehr wenige Menschen all dies.

Nach dem Code in Kodobase zu urteilen, verwenden 95 % der Benutzer OOP sehr schlecht. Und von den verbleibenden 5 % nutzen die meisten diese Funktionen nicht oft. Natürlich sind sie angenehm und können sogar nützlich sein, aber meiner Meinung nach gibt es keinen großen Bedarf für all diese Verbesserungen.

Ja, ich verstehe, aber neben kodobase gibt es Freelance und Market, und dort muss MQ an der Qualität der Produkte interessiert sein. Und die Qualität der Sprache wirkt sich auf die Qualität und die Geschwindigkeit der Entwicklung und der Fehlersuche auf die eine oder andere Weise aus.

Wenn man so über die Prozentsätze spricht, warum wurde dann überhaupt MQL5 geschaffen? Wir würden immer noch im alten Hardcore-MQL4 sitzen, wo OOP oder andere Dinge nicht erforderlich sind... 99 % der Nutzer waren damit zufrieden.)

Vielleicht gehen normale Programmierer gerade deshalb nicht zu MQL, weil es noch eine unvollständige Sprache ist.

 
Alexey Navoykov:

Ich habe mich entschlossen, ein solches Thema zu erstellen, da nach meinen Beobachtungen die Entwicklung der MQL-Syntax seit langem stagniert und es in den letzten Jahren keine Verbesserungen in der Sprache gegeben hat. Ich weiß nicht, ob die Entwickler weiter an MQL arbeiten werden, aber viele Funktionen fehlen, von denen einige dringend benötigt werden.

In diesem Thread habe ich beschlossen, eine Liste meiner wichtigsten Wünsche zusammenzustellen. Ich werde zuerst meine Liste geben, vielleicht fügt jemand etwas anderes hinzu, und dann werden sich vielleicht die Entwickler anschließen und ihre Visionen mitteilen, das wäre schön.

Diese Liste habe ich nach Wichtigkeit geordnet (wie ich es sehe), aber nicht nach meinen persönlichen Prioritäten, d.h. ich habe die grundlegendsten und unverzichtbarsten Dinge für die Sprache zuerst aufgeführt. Nehmen Sie die Funktionalität von C++ und C# als Maßstab


1. Arbeiten mit Typen: typedef, decltype, auto

Dies ist eigentlich eine Grundfunktionalität, zumindest die ersten beiden Spezifizierer. Benennungs- und Typ-Hopping-Operationen dienen nicht nur der Bequemlichkeit, sondern auch der Zuverlässigkeit und Flexibilität des Codes. Wenn Sie für konkrete Variablentypen, die an verschiedenen Stellen verwendet werden, einen festen Wert festlegen, werden Sie Probleme bekommen, wenn Sie einen der Typen ändern müssen.

Viele von Ihnen sind bereits mit typedef vertraut, aber leider ist es immer noch ein Stumpf, der nur mit Funktionszeigern funktioniert. Was decltype betrifft, möchte ich es für diejenigen, die damit nicht vertraut sind, klarstellen: Es gibt den Typ des Ausdrucks zurück, der ihm als Argument übergeben wurde, und ermöglicht so die flexible Definition von Typen von Variablen oder Funktionen auf der Grundlage anderer Typen:

Entweder mit typedef:

Oder zum Beispiel im Fall von langen und komplexen Typen (z.B. ClassA< ClassB< ClassC,ClassD<ClassE> >) - hier ist es ein Geschenk des Himmels, sie in typedef zu verpacken

In C# wird using anstelle von typedef verwendet.

Das einzige, was möglich ist, ist die verkrustete Variante der Typdefinition durch define, die mit einigen Problemen behaftet ist.


2. Namespaces: Namensraum

Dieses Thema wurde bereits vor kurzem erörtert. Für mich ist es wirklich seltsam, warum es noch nicht implementiert wurde, denn es ist eine unverzichtbare Funktion der Sprache. Vor allem, wenn man den Trend zu Community, Codobase und Gruppenentwicklung bedenkt. In diesem Fall wird das Problem der Übereinstimmung von Namen sehr relevant.

Als Beispiel wurde angeführt, dass der Compiler selbst dann einen Fehler erzeugt, wenn der Name einer lokalen Variablen innerhalb einer Funktion mit dem Namen eines in einer anderen Datei definierten Typs identisch ist. Das ist ein Skandal.

Im Allgemeinen ist es falsch, alles auf einem Haufen an einem Ort zu haben.


Ohne sie sind diebenutzerdefinierten Typen von Natur aus unvollständig und die Flexibilität ist stark eingeschränkt.
Angenommen, Sie haben eine Struktur DATETIME erstellt, die die Zeit speichert, und Sie möchten sie als datetime verwenden können, indem Sie sie an alle Funktionen übergeben, die datetime akzeptieren, und sie in Ausdrücken mit datetime verwenden.
Normalerweise ist dies ganz einfach: Überladen Sie den Konstruktor und die Cast-Anweisung mit dem entsprechenden Typ, und Sie erhalten volle Kompatibilität unserer Struktur mit diesem Typ:

Aber in MQL ist es stattdessen notwendig, eine separate Methode to_datetime() zu erstellen und ihren Aufruf überall hinzuschreiben. Oder der Aufruf der Zielfunktion von DATETIME & type muss überladen werden, was den Komfort und die Flexibilität ebenfalls nicht erhöht.


4. Mehrere Schnittstellen... Nun, es gab bereits eine Menge Gerüchte und Gespräche darüber (ich erinnere mich, dass sie vor drei Jahren im Service-Desk schrieben, dass die Arbeiten im Gange sind), aber es zieht sich hin... Wenn sie überhaupt stattfindet.



5. DieUnterstützung von Schnittstellen für Strukturen ist für ein einheitliches Arbeiten mit OOP notwendig. Zurzeit müssen wir oft Krücken bauen.

Diese Funktionalität könnte auf zwei Arten implementiert werden: entweder wie in C# - über Packen/Entpacken (Boxing), oder flexibler - durch Erstellen eines dynamischen Handles für die Struktur, das mit einem Deskriptor des dynamischen Objekts verknüpft ist, das die Struktur enthält - das wäre effizienter, außerdem könnten Sie Zeiger auf Strukturen und andere Datentypen erstellen, was die Flexibilität erhöhen würde.


6. Möglichkeit, die Strukturen wertmäßig zu übergeben, was bei der Übergabe kleiner Strukturen (DATETIME aus dem obigen Beispiel) wichtig ist, was flexible Konvertierungen von einem Typ in einen anderen ermöglichen würde, wenn der Konstruktor der Struktur diesen Typ unterstützt. Bei der Übertragung per Referenz gibt es diese Flexibilität nicht, aber wenn Schnittstellen für Strukturen implementiert werden, wird dies weniger relevant.


7. Möglichkeit, numerische Parameter der Vorlage anzugeben:

Was das zweite Beispiel betrifft, so können Sie in MQL4 darauf verzichten, da die Funktionen dort Arrays beliebiger Dimension akzeptieren. Und in MQL5 ist alles noch viel komplizierter mit mehrdimensionalen Arrays.


8. Spezialisierung von Vorlagen (separate Implementierung für bestimmte Typen).

Beispiel für eine Funktion:

Beispiel mit einer Klasse:



Und so weiter:


9. Die Möglichkeit des Castings (explizit oder implizit) eines Arrays von Zeigern in ein Array von Basiszeigern. In den alten Builds funktionierte dies und war sehr praktisch:

Jetzt müssen wir das Array in ein neues Array kopieren und dann wieder zurück - vergebliche Mühe.

10. Objektreferenz Casting:(Typ&)Objekt

Dies ist notwendig, um ein referenziertes Objekt an eine Funktion übergeben zu können. Im folgenden Beispiel muss ein Objekt der Klasse B als Objekt der Basisklasse A in eine Datei geschrieben werden. Dies kann jedoch nicht sofort geschehen, sondern es muss eine Zwischenfunktion erstellt oder das Objekt in ein neues Objekt kopiert werden.


11. Arrays und Strukturen nicht nur mit Konstanten, sondern mit beliebigen Ausdrücken initialisieren. Dies reduziert und vereinfacht den Code in solchen Fällen erheblich:


12. Möglichkeit, einen Zeiger explizit auf einen numerischen Wert zu setzen.

Sie würde es ermöglichen, die Arrays von Zeigern nach ihren Werten zu sortieren, um den benötigten Zeiger durch eine binäre Suche oder durch die Erstellung einer Hash-Tabelle schnell zu finden. Jetzt ist es möglich, einen numerischen Wert nur durch Umwandlung in eine Textform zu erhalten, was die ganze Idee zunichte macht.

13. Einstellung von Standardvorlagenparametern

Ich unterstütze.

 
Georgiy Merts:

Meiner Meinung nach brauchen nur sehr wenige Menschen all dies.

Nach dem Code in Kodobase zu urteilen, verwenden 95% der Benutzer OOP nur sehr wenig. Und von den verbleibenden 5 % des überwiegenden Teils werden alle diese Funktionen kaum genutzt. Natürlich sind sie nett und können sogar nützlich sein, aber meiner Meinung nach besteht kein großer Bedarf an all diesen Verbesserungen.

Diese kleine Anzahl von Leuten kann Bibliotheken schreiben, die von allen genutzt werden.

 

14. Erlaubt die Übergabe eines temporären Objekts, wenn das Funktionsargument eine konstante Referenz ist.

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. das Stichwort Freund.

Für einige Klassen möchten Sie einer bestimmten Klasse, aber nicht allen, Zugang zu privaten Mitgliedern gewähren.

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. eine Variable beim expliziten Aufruf des Konstruktors für eingebaute Typen auf Null zu setzen

Dies ist bei Vorlagen sehr nützlich.

   double x;         // Не инициализирована
   double y();       // Инициализирована нулём
   double z = 5.0;   // Инициализирована 5.0
 
Sie haben nicht einmal Wegweiser - was könnte grundlegender sein?)
 
Alexey Navoykov:

Ich habe mich entschlossen, ein solches Thema zu erstellen, weil meiner Beobachtung nach die Entwicklung der MQL-Syntax seit langem stagniert und in den letzten Jahren keine Verbesserungen an der Sprache vorgenommen wurden. Ich weiß nicht, ob die Entwickler überhaupt an MQL arbeiten werden, aber viele Funktionen fehlen wirklich, einige davon werden dringend benötigt.

In diesem Thread habe ich beschlossen, die wichtigsten Wünsche zusammenzutragen, zuerst werde ich meine Liste aufführen, vielleicht fügt jemand noch etwas hinzu. Und dann werden sich vielleicht die Entwickler zusammenschließen und ihre Visionen äußern, das wäre großartig.

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

Rechnen Sie mit einem Verbot, Kritik an den Schriften ist nicht erlaubt :)

PS: Es gab Verbesserungen, nicht so global, aber es gab

 
secret:
Sie haben nicht einmal Zeiger), was noch grundlegender sein könnte)

Es wird keine geben, die Sprache wird verwaltet, wenn auch ohne GC

Sharp hat sie auch nur im unsicheren Modus.

 
Alexey Navoykov:

Ja, ich verstehe, aber neben kodobase gibt es Freelance und Market, und dort muss MQ an der Qualität der Produkte interessiert sein. Und die Qualität der Sprache wirkt sich auf die Qualität und die Geschwindigkeit der Entwicklung und der Fehlersuche auf die eine oder andere Weise aus.

Wenn man so über die Prozentsätze spricht, warum wurde dann überhaupt MQL5 geschaffen? Wir würden immer noch im alten Hardcore-MQL4 sitzen, wo OOP oder andere Dinge nicht erforderlich sind... 99 % der Nutzer waren damit zufrieden.)

Vielleicht gehen normale Programmierer nicht zu MQL, weil es noch eine unvollständige Sprache ist.

Kodobase ist zu 95 % Unsinn. Neue Versionen von MT5 habe ich schon lange nicht mehr gesehen. Renat hat, wenn ich mich recht erinnere, etwas Globales für die neue Version versprochen.

 
Alexey Volchanskiy:

PS: Es gab Verbesserungen, nicht so global, aber es gab

Das letzte, woran ich mich erinnere, war ein impliziter Kopieroperator, der das Kopieren von dynamischen Objekten ermöglichte, aber das ist nichts, zumal seither viel Zeit vergangen ist.

Grund der Beschwerde: