OOP issue : idea to break a vicious circle ? - page 3

To add comments, please log in or register
Demos Stogios
218
Demos Stogios  
Alain Verleyen:

The circle I am referring to is the following, if you want to create generic code (in Stepanov sense), you use templates. Then if you want to create dynamic and flexible code (so a code where the minimum "stuff" are hard coded and fixed at compile time, but rather at run time), you will use polymorphism. When you try to combine that you have "problems", templates are static and limit the "polymorphism" of your code.

I could use typed arrays but that's at the opposite of my purpose, and is just moving the problem somewhere else. I talked about vectors, someone proposed dictionary, you arrays, it's all fine.

The problem with your proposal to use an array beside the vector is an other way similar to what I use, you will still have the problem to match your ENUM and mql types. So enumerate and repeat code. Probably what I want to achieve is not doable in mql and I will have to make some compromises.

Thanks for your input.

I have to say that I am not so OOP guy so I may do OOP things in MQL if I have to but I would rather not going C++. That said I can hardly understand what you are saying about polymorphism :) Other than that I believe  my proposal if appropriate  could change a little bit: instead of having a separate array, you could include the said info into you generic class, so you will have it in hand, e.g. in each vector member you will have both the INT - DOUBLE and so on type and also an enum to describe the type of the type

greets

Icham Aidibe
11502
Icham Aidibe  

Yeah in the standard lib, there's more than enough to get the result you expect (a collection of object different in type) and arrayobj is probably the most convenient since you could also collect many of these vectors of differents type with. Easily access it. Easily manage it etc .. 

After ... a new generic the Stepanov way may require some more door opened by the mql devteam to be able to cast the variable type on the fly, but how much necessary is it ? 

As always with Alain it's a high skilled topic.

Alain Verleyen
37528
Alain Verleyen  
Demos Stogios:

I have to say that I am not so OOP guy so I may do OOP things in MQL if I have to but I would rather not going C++. That said I can hardly understand what you are saying about polymorphism :) Other than that I believe  my proposal if appropriate  could change a little bit: instead of having a separate array, you could include the said info into you generic class, so you will have it in hand, e.g. in each vector member you will have both the INT - DOUBLE and so on type and also an enum to describe the type of the type

greets

I have type field in the (real) base class, it doesn't really help for my purpose.

See the answer to this stackoverflow question, it's explain better I can do.

Alain Verleyen
37528
Alain Verleyen  
Icham Aidibe:

Yeah in the standard lib, there's more than enough to get the result you expect (a collection of object different in type) and arrayobj is probably the most convenient since you could also collect many of these vectors of differents type with. Easily access it. Easily manage it etc .. 

After ... a new generic the Stepanov way may require some more door opened by the mql devteam to be able to cast the variable type on the fly, but how much necessary is it ? 

As always with Alain it's a high skilled topic.

As I said several times, whatever the way you like (arrays, dictionary, vectors, standard lib...), the problem is the same, I want to go one step further in the abstraction (generic code). Not only because it's nice, but because I have a real project behind this and it will avoid me a lot of duplicate code and the trouble associated with it. Also because on real projects, in opposite to toy coding, you have to deal with the requirements and the processing speed. When you have to execute on 1 billion times (processing ticks history), it needs to be very efficient and an extra layer (a wrapper class for example) is often not acceptable.

Of course I know with some new features in MQL, it would be easier (possible ?) but I can't rely on them anyway.

Icham Aidibe
11502
Icham Aidibe  
Alain Verleyen:

As I said several times, whatever the way you like (arrays, dictionary, vectors, standard lib...), the problem is the same, I want to go one step further in the abstraction (generic code). Not only because it's nice, but because I have a real project behind this and it will avoid me a lot of duplicate code and the trouble associated with it. Also because on real projects, in opposite to toy coding, you have to deal with the requirements and the processing speed. When you have to execute on 1 billion times (processing ticks history), it needs to be very efficient and an extra layer (a wrapper class for example) is often not acceptable.

Of course I know with some new features in MQL, it would be easier (possible ?) but I can't rely on them anyway.

I understand that Alain. And I'll repeat that it may be possible only if the mql devteam allows to cast variable type on the fly. Be sure that I hope for you & your project that you'll find a way thru.

Alain Verleyen
37528
Alain Verleyen  
nicholi shen:

1. I thought that you, the programmer, was the person responsible for casting your data not me ;) The original posts doesn't provide a minimum verifiable complete example, and it also doesn't also give any examples of exact inputs and desired outputs. You wanted to know how to use a class wrapper to store data of any type (pointers and native types) to a dynamic collection, and those generic requirements have been fulfilled by my snippet. If you don't like that it uses string indexes then how hard is it to subclass or fork and modify for your unpublished needs?

2. My snippet actually compiles and works as expected on all data types (Credit to the developer of CDictionary)

3. I figured you could easily subclass or fork an actual working type-agnostic dynamic collection to do what you need. 

4. I'm not trying to provocate a confrontation. I took time out of my day to answer your question. You didn't bother to read the docs, so I took even more time to post an actual working example. If you need help reading data into it then I'd suggest asking here

You are a troll. You don't even understand the problem.

Don't answer me, don't answer to my topic, play with your toys and stop trolling other's topics.

Icham Aidibe
11502
Icham Aidibe  
nicholi shen:


Who's fault is that, Alain? 

Correct me if I'm wrong, but this is what you said is it not?

  1. I want to manage some variables of basic types (int, double, bool...) in some generic way to avoid repeating code
  2. I want to manage these values in a collection or arrays, vector
  3. And I can initialize my array dynamically
  4. For example, I have a data file with values

To be honest I thought that parsing the string to cast to type was so trivial it didn't warrant any mention, but for the sake of friendship here is how you would do it.

 


      if (type == "INT")
         return this.Set(KEY, (int)value);
      if (type == "DOUBLE")
         return this.Set(KEY, (double)value);
      if (type == "STRING")
         return this.Set(KEY, (string)value);
      return false;
   }
};

I think he's trying to do it without any of those calls and directly by getting the type of the variable from his file to gain in performance. 

Icham Aidibe
11502
Icham Aidibe  
Well anyway. Have a good weekend guys! :)
Amir Yacoby
1304
Amir Yacoby  
Alain Verleyen:
Thanks for your answer. Of course enumerating each type would work, but it's what I want to avoid. You can imagine my real code than to just get or print the value.
With some more thought, maybe this is better, applied the parsing part from @nicholi shen

struct MyMqlParam : MqlParam
  {
private:
   bool              Set(const double parm)  {type=TYPE_DOUBLE;double_value=parm;return true;}
   bool              Set(const int parm)     {type=TYPE_INT;integer_value=parm;return true;}
   bool              Set(const string parm)  {type=TYPE_STRING;string_value=parm;return true;}
public:
   bool              ParseAndSet(const string inp);
   string            Print();
   void              Get(ENUM_DATATYPE &type,string &value);
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool MyMqlParam::ParseAndSet(const string inp)
  {
   string split[];
   int total=StringSplit(inp,';',split);
   if(total!=2)
      return false;
   string itype=split[0];
   string value=split[1];
   if(itype=="INT")
      return this.Set((int)value);
   if(itype=="DOUBLE")
      return this.Set((double)value);
   if(itype=="STRING")
      return this.Set((string)value);
   return false;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void MyMqlParam::Get(ENUM_DATATYPE &type,string &value)
  {
   type=this.type;
   switch(type)
      {
      case TYPE_DOUBLE:
      case TYPE_FLOAT:
         value=double_value;
         break;
      case TYPE_INT:
      case TYPE_UINT:
      case TYPE_LONG:
      case TYPE_ULONG:
      case TYPE_SHORT:
      case TYPE_USHORT:
      case TYPE_CHAR:
      case TYPE_UCHAR:
      case TYPE_DATETIME:
         value=integer_value;
         break;
      case TYPE_STRING:
         value=string_value;
         break;
      default:
         break;
      }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string MyMqlParam::Print(void)
  {
   switch(this.type)
     {
      case TYPE_DOUBLE:
      case TYPE_FLOAT:
         return (DoubleToString(double_value));
         break;
      case TYPE_INT:
      case TYPE_UINT:
      case TYPE_LONG:
      case TYPE_ULONG:
      case TYPE_SHORT:
      case TYPE_USHORT:
      case TYPE_CHAR:
      case TYPE_UCHAR:
      case TYPE_DATETIME:
         return (IntegerToString(integer_value));
         break;
      case TYPE_STRING:
         return (string_value);
         break;
      default:
         return NULL;
         break;
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
   string value;
   ENUM_DATATYPE type;
   string arr[5]={"INT;5","DOUBLE;7.1","STRING;THIS IS NICE","DOUBLE;3.14","INT;9"};
   MyMqlParam parms[5];
   for(int i=0;i<ArraySize(arr);i++)
     {
      parms[i].ParseAndSet(arr[i]);
     }
   for(int i=0;i<ArraySize(arr);i++)
     {
      Print("value of ",i," is ",parms[i].Print());      // Print
      //--- get the value
      parms[i].Get(type,value);
      //--- call different functions based on value
      if(type==TYPE_INT)
         FuncA(StringToInteger(value));
      if(type==TYPE_DOUBLE)
         FuncA(StringToDouble(value));
      if(type==TYPE_STRING)
         FuncA(value);
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void FuncA(const int parm)
  {
   Print("I am int:",parm);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void FuncA(const double parm)
  {
   Print("I am double:",parm);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void FuncA(const string parm)
  {
   Print("I am string:",parm);
  }
Amir Yacoby
1304
Amir Yacoby  

<Deleted section of post>

Just a little observation, as you say, for the sake of friendship: why this personal remarks are needed? Let me also answer, they are not. Maybe this is the ratio behind. It started already in the first code with remarks like: I know your smart enough to.. - embedded in the code / remarks. I only allow myself to say it to you because it's a remark to myself as well, because my style also tends sometimes to be like this. *And also, I don't speak in Alain's name, because maybe I'm totally wrong, but only for me, it did not feel so nice to read those remarks even as an outsider not participating in your conversations.

As for JSON which I am not so familiar with, from your code example it seems that you don't have to serialize the type, if you have something else unique to say about the type (like "pi", "timeframe","time" etc..) - is that correct? In that case, Alain will have to see if that is the case for him, does he know each data item what is it's unique id, or in the case he doesn't have it, he can't use that because if DOUBLE is all that is known and there are more then one DOUBLE then it won't work, am I right? 

To add comments, please log in or register