why not all control paths return a value?

 
//+------------------------------------------------------------------+
//|                                                         demo.mq5 |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

int a;
int i;

MqlTradeRequest Request;
MqlTradeResult Result;

MqlRates Rates[];

int Ema40Handle;
double Ema40[];
int Ema15Handle;
double Ema15[];

double PositionSL;

double Close[];
double Open[];
double High[];
double Low[];
int LowestLow;

double EntryPrice;
double SLPrice;
double TPPrice;
double LossRatio;
double ProfitRatio;

bool Bull1;
bool Bull2;
bool Bear1;
bool Bear2;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   Ema40Handle = iMA(_Symbol,PERIOD_CURRENT,40,0,MODE_EMA,PRICE_CLOSE);
   Ema15Handle = iMA(_Symbol,PERIOD_CURRENT,15,0,MODE_EMA,PRICE_CLOSE);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   
  }

void CandleInfo()
  {
   for(i = 0; i < 10 ; i++)
     {
      a = i + 1;
      ArrayResize(Close,10);
      ArrayResize(Open,10);
      ArrayResize(High,10);
      ArrayResize(Low,10);

      ArraySetAsSeries(Close,true);
      ArraySetAsSeries(Open,true);
      ArraySetAsSeries(High,true);
      ArraySetAsSeries(Low,true);

      Close[i] = iClose(_Symbol,PERIOD_CURRENT,a);
      Open[i] = iOpen(_Symbol,PERIOD_CURRENT,a);
      High[i] = iHigh(_Symbol,PERIOD_CURRENT,a);
      Low[i] = iLow(_Symbol,PERIOD_CURRENT,a);
     }
  }


void Ema40()
  {
   ArraySetAsSeries(Ema40,true);
   CopyBuffer(Ema40Handle,0,1,10,Ema40);
  }

void Ema15()
  {
   ArraySetAsSeries(Ema15,true);
   CopyBuffer(Ema15Handle,0,1,10,Ema15);
  }

bool CandleBelowMA40()
  {
   CandleInfo();
   Ema40();
   for(i = ArraySize(Open)-1; i >= 0; i--)
     {
      if(Open[i]>Close[i])
        {
         if(Open[i]>NormalizeDouble(Ema40[i],_Digits))
           {
            return false;
            break;
           }
        }
      else
         if(Close[i]>Open[i])
           {
            if(Close[i]>NormalizeDouble(Ema40[i],_Digits))
              {
               return false;
               break;
              }
           }
     }
  }
//+------------------------------------------------------------------+

the compiler said the function CandleBelowMa40(),

"not all control paths return a value",

why?

 
ziyang2048:

the compiler said the function CandleBelowMa40(),

"not all control paths return a value",

why?

Now, imagine that for whatever reason, when you enter the "CandleBelowMA40" function, i = -1. Maybe you don't expect that to happen, but it might. That means that the "for" loop won't be executed, and you'll get to the end of the function without having a value to return. Also, maybe the flow enters the "for", but what would happen if "Open[i]" is equal to "Close[i]"? You won't enter the "if" nor the "else", am I right? That's what that error means. You have to control all paths, and make sure you ALWAYS return a value if your function is meant to return a value. If you don't expect "i" to be -1, then just put at the end of the function, before the very last bracket

return(true);

...and you should be good.

 
The function returns a bool.
bool CandleBelowMA40()
  {
   CandleInfo();
   Ema40();
   for(i = ArraySize(Open)-1; i >= 0; i--)
     {
      if(Open[i]>Close[i])
        {
         if(Open[i]>NormalizeDouble(Ema40[i],_Digits))
           {
            return false;
            break;   <<<<<<<<<<<<<<<<<<<<<<<<<<< this is never run.
           }
        }
      else
         if(Close[i]>Open[i])
           {
            if(Close[i]>NormalizeDouble(Ema40[i],_Digits))
              {
               return false;
               break; <<<<<<<<<<<<<<<<<<<<<<< this is never run.
              }
           }
     }
<<<<<<<<<<<<<<<<<<< what are you returning here?
  } // CandleBelowMA40
 
Carlos Moreno Gonzalez #:

Now, imagine that for whatever reason, when you enter the "CandleBelowMA40" function, i = -1. Maybe you don't expect that to happen, but it might. That means that the "for" loop won't be executed, and you'll get to the end of the function without having a value to return. Also, maybe the flow enters the "for", but what would happen if "Open[i]" is equal to "Close[i]"? You won't enter the "if" nor the "else", am I right? That's what that error means. You have to control all paths, and make sure you ALWAYS return a value if your function is meant to return a value. If you don't expect "i" to be -1, then just put at the end of the function, before the very last bracket

...and you should be good.

ya I should be good haha

bool CandleBelowMA40()
  {
   CandleInfo();
   Ema40();
   for(i = ArraySize(Open)-1; i >= 0; i--)
     {
      if(Open[i]>=Close[i]) <<<<<<I add this
        {
         if(Open[i]>NormalizeDouble(Ema40[i],_Digits))
           {
            return false;
           }
        }
      else
         if(Close[i]>=Open[i]) <<<<<<I add this
           {
            if(Close[i]>NormalizeDouble(Ema40[i],_Digits))
              {
               return false;
              }
           }
     }
     return(true); <<<<<<This is what you want me to add?
  } 

Sorry for late reply, I have already sleep yesterday, 

so what u told me yesterday is I need to control all path,

so "if" and "else if" condition statement might not be executed,

I still need a return value, and that's why u call me add a return value before the very last bracket,

am I right?


I have another question, for example

bool CandleBelowMA40()
  {
   CandleInfo();
   Ema40();
   for(i = ArraySize(Open)-1; i >= 0; i--)
     {
      if(Open[i]>=Close[i])
        {
         if(Open[i]>NormalizeDouble(Ema40[i],_Digits))
           {
            return false; <<<<<<here
           }
        }
<<<<<the rest of the code from here
      else
         if(Close[i]>=Open[i])
           {
            if(Close[i]>NormalizeDouble(Ema40[i],_Digits))
              {
               return false;
              }
           }

     }
<<<<<to here
  }

lets say it run until here, so it return a false,

and the rest of the code will not be read,

am I right?

 
William Roeder #:
The function returns a bool.
bool CandleBelowMA40()
  {
   CandleInfo();
   Ema40();
   for(i = ArraySize(Open)-1; i >= 0; i--)
     {
      if(Open[i]>=Close[i])
        {
         if(Open[i]>NormalizeDouble(Ema40[i],_Digits))
           {
            return false;
           }
        }
      else
         if(Close[i]>=Open[i])
           {
            if(Close[i]>NormalizeDouble(Ema40[i],_Digits))
              {
               return false;
              }
           }
     }
     return(true); 
  } 

like this?

 
ziyang2048 #:

lets say it run until here, so it return a false,

and the rest of the code will not be read,

am I right?

Yes, you're right. When there's a "return" the rest is not executed. If you have many nested "if" and "for" you might forget a path, so it's always a good idea to return something "generic" before the end of the function - it might be true or false (if your function returns a boolean), whatever harms the least your flow in case it's executed unexpectedly.

 
Carlos Moreno Gonzalez #:

Yes, you're right. When there's a "return" the rest is not executed. If you have many nested "if" and "for" you might forget a path, so it's always a good idea to return something "generic" before the end of the function - it might be true or false (if your function returns a boolean), whatever harms the least your flow in case it's executed unexpectedly.

thanks man.

Reason: