Features of the mql5 language, subtleties and tricks - page 297

 
Maxim Kuznetsov ArrayPrint is inconvenient because it prints the whole array (they can be of epic size). You have to redefine it anyway, reducing the output

There are appropriate inputs there.

 
Maxim Kuznetsov #:

INC_SORT_BY(array,field) - sort the array of structures by the specified field;

It is hardly possible to make it shorter :-)

On the topic of performance.

Forum on trading, automated trading systems and testing trading strategies.

Peculiarities of mql5 language, subtleties and techniques of work

fxsaber, 2022.06.19 16:17

Alert: Bench_Stack = 0, 100 <= Time[Test9.mq5 129 in OnStart: SortOnField_Num::SORT::Sort(Array)] = 34574468 mcs.

Alert: Bench_Stack = 0, 100 <= Time[Test9.mq5 130 in OnStart: SortOnField_Num::SORT2::Sort(Array)] = 10586 mcs.
 
fxsaber #:

I would conversely drop the semicolon at the end of the macro call to emphasise that it's not a function.

Then the code becomes less readable. Its perception is disturbed. Also, when using a loop, you may use break in the macro.
 
Sergey Gridnev #:
Then the code becomes less readable. Its perception is disturbed. Also, when using a loop, you may use break in a macro.

I wonder if the final compiler code with/without do-while is different if break is not used.

 
Maxim Kuznetsov #:

user-user:

INC_SORT_BY(array,field) - sort an array of structures by a given field;

Shorter is hardly possible anymore :-)

Unfortunately your macros are inflexible, 

1. For simple types you have to pass compare function argument.

2. You  cannot sort structure by multiple fields, eg sort trading history by symbol name then by entry date. 
Shorter does not mean best, I don't know who promoted this idea 🤔 

 
Maxim Kuznetsov #:

user-user:

INC_SORT_BY(array,field) - sort an array of structures by a given field;

Shorter is hardly possible anymore :-)

I would modify your macros like to this better implementation:

/// SORTING

template <typename T>
void Swap(T &one,T &two)
{
   T tmp=two;
   two=one;
   one=tmp;
}

// Sort simple arrays int, string,... (ascending order)
#define  SORT(a) do { \
   for(int i=1; i < ArraySize(a); ++i) \
      for(int j=i; j>0 && (a[j]<a[j-1]); j--) { \
         Swap(a[j],a[j-1]); \
      } \
} while(0)

// Sort structures or simple arrays by custom order
#define  SORT_BY(a, less) do { \
   for(int i=1; i < ArraySize(a); ++i) \
      for(int j=i; j>0 && less(a[j],a[j-1]); j--) { \
         Swap(a[j],a[j-1]); \
      } \
} while(0)

////////////////////////////
// TEST
struct rFoo {
   int key;
   double value;
};
bool AscByKey(rFoo &one,rFoo &two) {
   return one.key < two.key;
}
bool AscByValue(rFoo &one,rFoo &two) {
   return one.value < two.value;
}
bool Custom(rFoo &one,rFoo &two) { // ascending by key, then ascending by value
   if(one.key < two.key) return(true);
   if(one.key > two.key) return(false);
   // if equal on key
   if(one.value < two.value) return(true);
   if(one.value > two.value) return(false);
   // all fields are equal
   return(false);
}
rFoo mass[] = {
   {11,0.18},
   {7,7.81},
   {7,1.25},
   {8,0.1},
   {100,5.11},
   {0,3.29},
   {0,1.43}
};


void OnStart()
{
   SORT_BY(mass,AscByKey);
   ArrayPrint(mass);

   SORT_BY(mass,AscByValue);
   ArrayPrint(mass);

   SORT_BY(mass,Custom);
   ArrayPrint(mass);
}
/*
     [key] [value]
 [0]     0 3.29000
 [1]     0 1.43000
 [2]     7 7.81000
 [3]     7 1.25000
 [4]     8 0.10000
 [5]    11 0.18000
 [6]   100 5.11000
     [key] [value]
 [0]     8 0.10000
 [1]    11 0.18000
 [2]     7 1.25000
 [3]     0 1.43000
 [4]     0 3.29000
 [5]   100 5.11000
 [6]     7 7.81000
     [key] [value]
 [0]     0 1.43000
 [1]     0 3.29000
 [2]     7 1.25000
 [3]     7 7.81000
 [4]     8 0.10000
 [5]    11 0.18000
 [6]   100 5.11000
*/

I used a simple "insertion sort" function for its small code size although it is not the fastest sort.

For more speed, you should replace it with QuickSort or a hybrid sort function.

Edit:

you can also use my introsort library for max. performance https://www.mql5.com/en/code/57233

 

Is it possible to define text without quotes and use it as a string? There is an error without inverted commas.

#define  str aaa

int OnInit()
  {
        string new_str = string(str);
        return INIT_SUCCEEDED;
  }
'aaa' - undeclared identifier   
1 errors, 0 warnings           
 
Andrei Iakovlev #:

Is it possible to define text without quotes and use it as a string? There is an error without inverted commas.

This can be done using a stringify operator # inside macro:

#define STR(s) #s

string new_str = STR(Hello MQL);

Print(new_str); // "Hello MQL"

In your example you should use indirection (2nd level macro) to expand 'str" macro to aaa before using # operator:

#define STR(s) #s
#define STR2(s) STR(s)

#define str aaa

string new_str = STR2(str);
Print(new_str); // "aaa"

So, the second form with indirection STR2(s) will be compatible wether "s" parameter is a string constant or another macro.

 
amrali #:

This can be done by using the stringify # operator inside the macro....

Thank you.

 
The STR macro with indirection can be used to debug (print) macro expansion to the logs:


#define STR(s) #s
#define EXPAND_MACRO(m)  Print(STR(m))

// test macro
#define PRINT(A) Print(#A, " = ", A)

void OnStart() {
   EXPAND_MACRO( PRINT(_LastError) );
   EXPAND_MACRO( SORT_BY(mass,AscByKey) );
}

Edit:
SORT_BY macro is defined here