Interesting take on the PLO - page 8

 
fxsaber:

I write this way because I like it. That said, it gets really bad when debugging.


Even in this expression.

it's hard to figure out who returned what. In more complex ones (I practice it all the time) it's really hard.

If you want to use 2-3... let's assume 5 results of functions execution united by logical operations (or conditional ternary operator) - I've seen it on githab or somewhere else, this code can be handled

But if you have a dozen of these "goodies"... imho, it's not practical

 
Maxim Kuznetsov:

I'm not a mql developer, of course,

but in C switch generates quite efficient binary search and does not cause unnecessary page paging or cache dumping. So yes, it's often better than indirect addressing via arrays and structures.

the developers wrote somewhere and here similar information

found only this:

Forum on trading, automated trading systems and strategy testing

This is the article we've found in MQL5.

Slava, 2011.04.14 09:59

No, unfortunately it will not. For string types only if ... else if ... else

Using integer types in switch speeds up the analyzer's code several times as much as if


 
Igor Makanu:

But if it's a dozen or so... imho, it's not practical.

Small monster.

  static bool VirtualOrderSelect( const TICKET_TYPE Index, const int Select, const int Pool = MODE_TRADES )
  {
    return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.OrderSelect(Index, Select, Pool) :
           #ifdef  VIRTUAL_SNAPSHOT_REFRESHTIME
             VIRTUAL::SnapshotPtr ?
             #ifdef __MQL5__ // Выбор по тикету в MT5 - разнообразный набор вариантов.
               (Select == SELECT_BY_TICKET) ? ::OrderSelect(Index, Select, Pool) && VIRTUAL::SnapshotPtr.CopyOrder()
                                            :
             #endif // #ifdef __MQL5__
                                              ((((Index == INT_MIN) || (Index == INT_MAX)) && (Pool == MODE_TRADES) &&
                                               ::OrderSelect(Index, Select, Pool) &&
                                             #ifdef  VIRTUAL_SNAPSHOT_WITHOUT_HISTORY
                                               VIRTUAL::SnapshotPtr.CopyOrder(true))
                                             #else // #ifdef VIRTUAL_SNAPSHOT_WITHOUT_HISTORY
                                               VIRTUAL::SnapshotPtr.CopyOrder())
                                             #endif // #ifdef VIRTUAL_SNAPSHOT_WITHOUT_HISTORY #else
                                               || VIRTUAL::SnapshotPtr.OrderSelect(Index, Select, Pool))
                                  :
           #endif // #ifdef VIRTUAL_SNAPSHOT_REFRESHTIME
           #ifdef __MQL5__
             #ifdef __MT4ORDERS__
               ::OrderSelect(Index, Select, Pool)
             #else // __MT4ORDERS__
               false
             #endif // __MT4ORDERS__
           #else // __MQL5__
             ::OrderSelect(Index, Select, Pool)
           #endif // __MQL5__
           );
  }

Logical operations allow you to write succinctly when using different settings via macros. But it's a horror, of course.

 
fxsaber:

logical operations allow for concise writing when using various settings via macros. But it's a horror, of course.

Your example from "the end justifies the means"

my question was about a very different and incomprehensible style

 
fxsaber:

The little monster.

You can't look a gift horse in the mouth. But here are a couple more examples of other people's code, which gave me a few unforgettable dozens of minutes of debugging. Perhaps someone will recognise their own code.

      Res = (!FillingMode || (Type >= ORDER_FILLING_RETURN) || ((FillingMode & (Type + 1)) != Type + 1)) ?
            (((ExeMode == SYMBOL_TRADE_EXECUTION_EXCHANGE) || (ExeMode == SYMBOL_TRADE_EXECUTION_INSTANT)) ?
             ORDER_FILLING_RETURN : ((FillingMode == SYMBOL_FILLING_IOC) ? ORDER_FILLING_IOC : ORDER_FILLING_FOK)) :
            (ENUM_ORDER_TYPE_FILLING)Type;
    return((arrow_color == INT_MAX) ? (MT4ORDERS::NewOrderCheck() ? 0 : -1) :
           ((((int)arrow_color != INT_MIN) || MT4ORDERS::NewOrderCheck()) &&
            MT4ORDERS::OrderSend(MT4ORDERS::LastTradeRequest, MT4ORDERS::LastTradeResult) ?
            (MT4ORDERS::IsHedging ? (long)MT4ORDERS::LastTradeResult.order : // PositionID == Result.order - особенность MT5-Hedge
             ((MT4ORDERS::LastTradeRequest.action == TRADE_ACTION_DEAL) ?
              (MT4ORDERS::IsTester ? (_B2(::PositionSelect(MT4ORDERS::LastTradeRequest.symbol)) ? PositionGetInteger(POSITION_TICKET) : 0) :
                                      // HistoryDealSelect в MT4ORDERS::OrderSend
                                      ::HistoryDealGetInteger(MT4ORDERS::LastTradeResult.deal, DEAL_POSITION_ID)) :
              (long)MT4ORDERS::LastTradeResult.order)) : -1));

I don't know if it was easy to write it that way but it's unreal to debug it, all the more to read it. And I don't see any objective reasons for writing it that way.

 
traveller00:

And I don't see any objective reasons for writing it that way.

They are subjective, of course. I don't like unnecessary variables and multiple returns. For some reason, I believe that EX5 will be shorter and executed faster without them.

 
fxsaber:

They are subjective, of course. I don't like unnecessary variables and multiple returns. For some reason I believe that EX5 will be shorter and faster without them.

By the way, this confidence that the code will be shorter and faster is not justified.

here it is

bool a=A();
bool b=B();
//....много промежуточных результатов
bool x=X();
bool Res=a||b||x ;
return Res;

and this

return A()||B()||X();

I'm sure it will be the same in speed (and maybe in size of code and memory used).

It's just the second variant is faster to write and everybody writes it and then, when it is necessary to add/complicate something, they leave the second variant but bloated to a difficult-to-read one.

You should periodically perform refactoring in this respect and you won't have troubles.

 
Aleksey Mavrin:

Do refactoring periodically in this respect and there will be no problem.

Only for those who have a lot of free time or are objectively so pressed that there is nowhere to go without it.

When there is a lot of return, the code will 100% be different.
 
fxsaber:

Only for those who have a lot of free time or are objectively so pressed that there is nowhere to go without it.

ZS When there is a lot of return, the code will 100% be different.

I understand, but partly agree, I just think everyone has experienced relatively long bugfixing times, which would be found faster if the code was "perfectly ready" for debugging.

It's unclear what eats up more time - longer writing "usable" code or debugging and finding bugs, it's always different I guess.

 
fxsaber:

When there's a lot of return, the code will be 100% different.

C++ VS2019 under debugger

source code:

bool a(int v) { return(v > 0); }
bool b(int v) { return(v < 0); }
bool c(int v) { return(v == 0);}

bool tst1(int v1, int v2, int v3)
{
        if (a(v1)) return(true);
        if (b(v2)) return(true);
        if (c(v3)) return(true);
        return(false);
}

bool tst2(int v1, int v2, int v3)
{
        return(a(v1) && b(v2) && c(v3));
}

int main()
{
        int x = 1, y=2, z=3;
        bool result1 = tst1(x, y, z);
        bool result2 = tst2(x, y, z);
}

asm debugger

bool tst1(int v1, int v2, int v3)
{
        if (a(v1)) return(true);
000 E1918  mov         eax,dword ptr [v1]  
000 E191B  push        eax  
000 E191C  call        a (0 E137Ah)  
000 E1921  add         esp,4  
000 E1924  movzx       ecx,al  
000 E1927  test        ecx,ecx  
000 E1929  je          tst1+3 Fh (0 E192Fh)  
000 E192B  mov         al,1  
000 E192D  jmp         tst1+6 Fh (0 E195Fh)  
        if (b(v2)) return(true);
000 E192F  mov         eax,dword ptr [v2]  
000 E1932  push        eax  
000 E1933  call        b (0 E13ACh)  
000 E1938  add         esp,4  
000 E193B  movzx       ecx,al  
000 E193E  test        ecx,ecx  
000 E1940  je          tst1+56 h (0 E1946h)  
000 E1942  mov         al,1  
000 E1944  jmp         tst1+6 Fh (0 E195Fh)  
        if (c(v3)) return(true);
000 E1946  mov         eax,dword ptr [v3]  
000 E1949  push        eax  
000 E194A  call        c (0 E11B8h)  
000 E194F  add         esp,4  
000 E1952  movzx       ecx,al  
000 E1955  test        ecx,ecx  
000 E1957  je          tst1+6 Dh (0 E195Dh)  
000 E1959  mov         al,1  
000 E195B  jmp         tst1+6 Fh (0 E195Fh)  
        return(false);
000 E195D  xor         al,al  
}


bool tst2(int v1, int v2, int v3)
{
        return(a(v1) && b(v2) && c(v3));
000 E19C8  mov         eax,dword ptr [v1]  
000 E19CB  push        eax  
000 E19CC  call        a (0 E137Ah)  
000 E19D1  add         esp,4  
000 E19D4  movzx       ecx,al  
000 E19D7  test        ecx,ecx  
000 E19D9  je          tst2+6 Dh (0 E1A0Dh)  
000 E19DB  mov         edx,dword ptr [v2]  
000 E19DE  push        edx  
000 E19DF  call        b (0 E13ACh)  
000 E19E4  add         esp,4  
000 E19E7  movzx       eax,al  
000 E19EA  test        eax,eax  
000 E19EC  je          tst2+6 Dh (0 E1A0Dh)  
000 E19EE  mov         ecx,dword ptr [v3]  
000 E19F1  push        ecx  
000 E19F2  call        c (0 E11B8h)  
000 E19F7  add         esp,4  
000 E19FA  movzx       edx,al  
000 E19FD  test        edx,edx  
000 E19FF  je          tst2+6 Dh (0 E1A0Dh)  
000 E1A01  mov         dword ptr [ebp-0 C4h],1  
000 E1A0B  jmp         tst2+77 h (0 E1A17h)  
000 E1A0D  mov         dword ptr [ebp-0 C4h],0  
000 E1A17  mov         al,byte ptr [ebp-0 C4h]  
}



reduced by commands one call just in 2 columns not to count:

ts1:                                                    tst2:
000 E1918  mov         eax,dword ptr [v1]                000 E19C8  mov         eax,dword ptr [v1]
000 E191B  push        eax                               000 E19CB  push        eax  
000 E191C  call        a (0 E137Ah)                       000 E19CC  call        a (0 E137Ah)  
000 E1921  add         esp,4                             000 E19D1  add         esp,4  
000 E1924  movzx       ecx,al                            000 E19D4  movzx       ecx,al  
000 E1927  test        ecx,ecx                           000 E19D7  test        ecx,ecx  
000 E1929  je          tst1+3 Fh (0 E192Fh)                000 E19D9  je          tst2+6 Dh (0 E1A0Dh)  
000 E192B  mov         al,1                              000 E19DB  mov         edx,dword ptr [v2]  
000 E192D  jmp         tst1+6 Fh (0 E195Fh)                000 E19DE  push        edx 


as you can see here and the commands almost repeat each other, it's clear that in the first test you need to add some more return

with 99% confidence, I think that at the processor level these codes will run at the same speed up to a clock - in the processor optimization, paralleling and who knows what else works at the level of micro-commands

Reason: