Suggestions for MQL syntax

 

I decided to create such a topic, because according to my observations, the development of MQL syntax has been stagnating for a long time, I can't see any improvement of the language in recent years. I don't know if the developers are going to work on MQL, but many of the features are very missing, some of which are critically needed.

In this thread I have decided to compile a list of my main requests. I will first give my list, perhaps someone will add something else, and then maybe the developers will join in and share their vision, it would be nice.

This list I put in order of importance (as I see it), but not in order of my personal priorities. I.e. first put the most fundamental and indispensable things for the language. Take C++ and C# functionality as a benchmark


1. Working with types: typedef, decltype, auto

This is actually a basic functionality, at least the first two specifiers. Naming and type hopping operations are created not only for the convenience, but also for code reliability and flexibility. If you set a fixed value on concrete types of variables used in different places, you will have problems when you need to change any of the types.

Many of you are already familiar with typedef, but unfortunately it is still a stump that only works with function pointers. For those who are not familiar with decltype, let me clarify: It returns the type of expression passed to it as an argument, allowing flexibility to define types of certain variables or functions on the basis of types of others:

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

Either using typedef:

typedef int type;
type a= 100;
type b = a;
Or for example in the case of long and complex types (e.g. ClassA< ClassB< ClassC,ClassD<ClassE> >) - here it's a godsend to wrap it in typedef

In C#, using is used instead of typedef.

The only thing possible is the crusty variant of type definition through define which is fraught with some problems.


2. Namespaces: namespace

This topic has already been discussed recently. To me it's really strange why it hasn't been implemented yet, because it's a must-have feature of the language. Especially considering the trend towards community, codobase and group development. In this case, the problem of matching names becomes very relevant.

They cited an example that even when the name of a local variable inside some function is identical to the name of a type defined in another file, the compiler will generate an error. It is an outrage.

In general, it is wrong to have everything in one pile in one space.


Without it, theuser-defined types are inherently incomplete and the flexibility is greatly reduced.
Suppose you have created a structure DATETIME that stores the time, and you want to be able to use it as datetime, passing it to all the functions that accept datetime, as well as using it in expressions with datetime.
Usually this is done simply: overload the constructor and cast statement with the corresponding type, and you get full compatibility of our structure with this type:

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

But in MQL instead it is necessary to create a separate method to_datetime() and to write its call everywhere. Or the call of the target function of DATETIME & type must be overloaded which also does not increase the comfort and flexibility.


4. Multiple interfaces... Well, there've already been a lot of rumors and talks about it (I remember three years ago they wrote in service-desk that the work is in progress), but it's dragging on... If it is going on at all.



5. Support of interfaces for structures is necessary for unified work with OOP. At present, we often have to make crutches.

This functionality could be implemented in two ways: either like in C# - via packaging/unpacking (boxing), or more flexible way - by creating a dynamic handle for the structure linked to a descriptor of dynamic object which contains the structure - it would be more efficient, plus you could create pointers to structures and other data types, which would increase the flexibility.


6. Possibility to pass the structures by value, which is important when passing the small structures (DATETIME from the example above), which would allow flexible conversions on the fly from one type to another, if the constructor of the structure supports this type. When transferring by reference, there is no such flexibility. Although if interfaces for structures are implemented, it will become less relevant.


7. Possibility to specify numerical parameters of the template:

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

As for the second example, in MQL4 you can do without it, because there the functions accept arrays of any dimension. And in MQL5, everything is much more complicated with multidimensional arrays.


8. Specialization of templates (separate implementation for specific types).

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

Example with a class:
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();
}



And so on:


9. The possibility of casting (explicit or implicit) an array of pointers to an array of base pointers. In the old builds this worked, and was very convenient:

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

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

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

Now we have to recopy the array into a new one, and then back again, wasted effort.

10. object reference casting:(type&)object

This is necessary to be able to pass a referenced object to a function. The following example requires an object of class B to be written to a file as an object of base class A, but this cannot be done now, an intermediate function must be created or the object must be copied into a new object.

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. initialize arrays and structures not only with constants, but with any expressions. This significantly reduces and simplifies code in such cases:

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


12. Possibility to explicitly cast a pointer to a numeric value.

It would allow to sort the arrays of pointers by their values in order to quickly find the needed pointer through a binary search or by creating a hash table. Now it's possible to get a numeric value only through conversion to text mode, which kills the whole idea.

13. Setting default template parameters

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;
 

In my opinion, very few people need all this.

Judging by the code in Kodobase - 95% of users use OOP very little. And of the remaining 5% of the greater part - all these features are little used. Certainly, they are pleasant and even can be useful, but there is no great need in all these improvements, in my opinion.

 
Georgiy Merts:

In my opinion, very few people need all this.

Judging by code in Kodobase - 95% of users use OOP very poorly. And of the remaining 5% most of them don't use these features much. Of course, they are pleasant and can even be useful, but there's no great need in all these improvements in my opinion.

Yes, I understand, but in addition to kodobase there are Freelance and Market, and there MQ must be interested in the quality of products. And the quality of the language affects the quality and speed of development and debugging one way or another.

If talking about the percentages like this, then why was MQL5 created in the first place? We would still be sitting in old hardcore MQL4 where OOP or whatever else is not required... 99% of users were happy with it )

Perhaps normal programmers are not going to MQL precisely because it is still an incomplete language.

 
Alexey Navoykov:

I decided to create such a topic, as according to my observations, the development of MQL syntax has been stagnating for a long time, no improvements in the language over the past few years. I don't know if the developers are going to work on MQL further, but many features are very missing, some of which are critically needed.

In this thread I have decided to compile a list of my main requests. I will first give my list, perhaps someone will add something else, and then maybe the developers will join in and share their vision, it would be nice.

This list I put in order of importance (as I see it), but not in order of my personal priorities. I.e. first put the most fundamental and indispensable things for the language. Take C++ and C# functionality as a benchmark


1. Working with types: typedef, decltype, auto

This is actually a basic functionality, at least the first two specifiers. Naming and type hopping operations are created not only for the convenience, but also for code reliability and flexibility. If you set a fixed value on concrete types of variables used in different places, you will have problems when you need to change any of the types.

Many of you here are already familiar with typedef, but unfortunately it is still a stump that only works with function pointers. As for decltype, let me clarify for those who are not familiar with it: it returns the type of expression passed to it as an argument, allowing flexibility to define types of variables or functions based on other types:

Either using typedef:

Or for example in the case of long and complex types (e.g. ClassA< ClassB< ClassC,ClassD<ClassE> >) - here it's a godsend to wrap it in typedef

In C#, using is used instead of typedef.

The only thing possible is the crusty variant of type definition through define which is fraught with some problems.


2. Namespaces: namespace

This topic has already been discussed recently. To me it's really strange why it hasn't been implemented yet, because it's a must-have feature of the language. Especially considering the trend towards community, codobase and group development. In this case, the problem of matching names becomes very relevant.

They cited an example that even when the name of a local variable inside some function is identical to the name of a type defined in another file, the compiler will generate an error. It is an outrage.

Moreover, it is wrong to have everything in one place in one pile.


Without it, theuser-defined types are inherently incomplete and the flexibility is greatly reduced.
Suppose you have created a structure DATETIME that stores the time, and you want to be able to use it as datetime, passing it to all the functions that accept datetime, as well as using it in expressions with datetime.
Usually this is done simply: overload the constructor and cast statement with the corresponding type, and you get full compatibility of our structure with this type:

But in MQL instead it is necessary to create a separate method to_datetime() and to write its call everywhere. Or the call of the target function of DATETIME & type must be overloaded which also does not increase the comfort and flexibility.


4. Multiple interfaces... Well, there've already been a lot of rumors and talks about it (I remember three years ago they wrote in service-desk that the work is in progress), but it's dragging on... If it is going on at all.



5. Support of interfaces for structures is necessary for unified work with OOP. At present, we often have to make crutches.

This functionality could be implemented in two ways: either like in C# - via packaging/unpacking (boxing), or more flexible way - by creating a dynamic handle for the structure linked to a descriptor of dynamic object which contains the structure - it would be more efficient, plus you could create pointers to structures and other data types, which would increase the flexibility.


6. Possibility to pass the structures by value, which is important when passing the small structures (DATETIME from the example above), which would allow flexible conversions on the fly from one type to another, if the constructor of the structure supports this type. There is no such flexibility when transferring by reference, although if interfaces for structures are implemented, it will become less relevant.


7. Possibility to specify numerical parameters of the template:

As for the second example, in MQL4 you can do without it, because there the functions accept arrays of any dimension. And in MQL5, everything is much more complicated with multidimensional arrays.


8. Specialization of templates (separate implementation for specific types).

Function example:

Example with a class:



And so on the little things:


9. The possibility of casting (explicit or implicit) an array of pointers to an array of base pointers. In the old builds this worked, and was very convenient:

Now we have to recopy the array into a new one, and then back again, wasted effort.

10. object reference casting:(type&)object

This is necessary to be able to pass a referenced object to a function. The following example requires an object of class B to be written to a file as an object of base class A, but this cannot be done now, an intermediate function must be created or the object must be copied into a new object.


11. initialize arrays and structures not only with constants, but with any expressions. This significantly reduces and simplifies code in such cases:


12. Possibility to explicitly cast a pointer to a numeric value.

It would allow to sort the arrays of pointers by their values in order to quickly find the needed pointer through a binary search or by creating a hash table. Now it's possible to get a numeric value only through conversion to a textual form, which kills the whole idea.

13. Setting default template parameters

I support.

 
Georgiy Merts:

In my opinion, a very small number of people need all this.

Judging by code in Kodobase - 95% of users use OOP very little. And of the remaining 5% of the greater part - all these features are little used. Of course, they are nice, and can even be useful, but there is no great need for all these improvements, in my opinion.

This small number of people can write libraries that everyone will use.

 

14. Allow to pass a temporary object if the function argument is a constant reference.

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. the keyword friend.

For some classes, want to give access to private members, to a particular class, but not to all.

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. to null a variable when explicitly calling the constructor for built-in types

This comes in handy in templates.

   double x;         // Не инициализирована
   double y();       // Инициализирована нулём
   double z = 5.0;   // Инициализирована 5.0
 
They don't even have signposts) what could be more fundamental)
 
Alexey Navoykov:

I decided to create such a topic, because according to my observation MQL syntax development has been stagnating for a long time, no improvements in the language were made during the last years. I don't know if developers are going to work on MQL at all, but many features are really missing, some of them are critically needed.

In this thread I decided to compile the main wishes, first I will give my list, maybe someone will add something else. And then maybe the developers will connect and express their vision, it would be great.

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

Expect a ban, criticism of the scriptures is not allowed :)

PS: Improvements were, not so global, but there were

 
secret:
They don't even have pointers) what could be more fundamental)

There won't be any, the language is managed, albeit without GC

Sharp also has them only in unsafe mode.

 
Alexey Navoykov:

Yes, I understand, but in addition to kodobase there are Freelance and Market, and there MQ must be interested in the quality of products. And the quality of the language affects the quality and speed of development and debugging one way or another.

If talking about the percentages like this, then why was MQL5 created in the first place? We would still be sitting in old hardcore MQL4 where OOP or any other things are not required... 99% of users were happy with it )

Maybe normal programmers are not going to MQL because it is still an incomplete language.

Kodobase is 95% rubbish at all. I have not seen new versions of MT5 for a long time. Renat, I remember, promised something global in the new release.

 
Alexey Volchanskiy:

PS: There were improvements, not so global, but there were

The last thing I remember was an implicit copy operator allowing to copy dynamic objects, but that's nothing, especially as a lot of time has passed since then.