Libreria di classi generiche - bug, descrizione, domande, caratteristiche d'uso e suggerimenti - pagina 20

 
Sergey Dzyublik:

1. Eliminare i comportamenti ambigui:
Se passiamo "INT_MAX - 10" come parametro a CPrimeGenerator::ExpandPrime, il risultato "INT_MAX" sarà restituito.
Se passiamo "INT_MAX - 10" come parametro a CPrimeGenerator::GetPrime, verrà restituito lo stesso risultato: "INT_MAX - 10".

In entrambi i casi, il valore restituito non è un numero primo, il che inganna l'utente.

Sul primo punto:

Non c'è ambiguità qui.

Il metodo GetPrime dovrebbe restituire il numero primo più vicino dall'alto, ma nell'intervallo da INT_MAX - 10 a INT_MAX non ce ne sono, ecco perché viene restituito INT_MAX - 10.

Il metodo ExpandPrime raddoppia prima il valore di input e il metodo GetPrime viene chiamato dal numero ricevuto.

Inoltre, ExpandPrime ha un controllo per l'overrun INT_MAX:

   if((uint)new_size>INT_MAX && INT_MAX>old_size)
      return INT_MAX;
   else
      return GetPrime(new_size);

A mio parere, la logica dietro il comportamento di questi metodi è assolutamente univoca e corretta.


Per quanto riguarda il secondo e il terzo punto:

I cambiamenti che suggerisci sono rilevanti solo per la maggior parte dei problemi di bordo, quando le dimensioni della CHashMap sono molto grandi. Tuttavia, non c'è alcuna garanzia che avranno un impatto positivo sulle prestazioni, quindi è necessario fare studi separati per determinare la correttezza dei cambiamenti che suggerite.

 
Roman Konopelko:

Non c'è ambiguità qui.
Il metodo GetPrime dovrebbe restituire il numero primo più vicino dall'alto, ma non ce ne sono tra INT_MAX - 10 e INT_MAX, quindi viene restituito INT_MAX - 10.
Il metodo ExpandPrime raddoppia prima il valore di input e il metodo GetPrime viene chiamato dal numero ricevuto.
Inoltre, ExpandPrime ha un controllo per l'overrun INT_MAX:
La logica del comportamento di questi metodi è assolutamente univoca e corretta.


1. Le funzioni possono restituire numeri sconosciuti invece di numeri primi.
Come un utente usa questi dati è un suo problema, forse li lancia nel lungo e li passa ulteriormente alle funzioni di supercalcolo, chi se ne frega.
Il fatto è che possiamo restituire qualcosa di diverso da ciò che è dichiarato e atteso dalle funzioni per default.

2. Come possiamo controllare che la chiamata alla funzione abbia restituito un numero primo e non qualcos'altro?
Non potete semplicemente confrontarlo con INT_MAX.
Dovete confrontarlo con l'ultimo numero primo disponibile inferiore a INT_MAX.
Ogni volta che si confronta il risultato delle chiamate di queste funzioni con qualche numero magico per assicurarsi che tutto sia a posto, lo trovo assurdo.

 
Sergey Dzyublik:

1. Le funzioni possono non restituire numeri primi, ma numeri oscuri.
Come l'utente usa questi dati è un suo problema, forse li lancia in long e poi li passa nelle funzioni di supercalcolo, chi se ne frega.
Il fatto è che possiamo restituire qualcosa di diverso da ciò che è dichiarato e atteso dalle funzioni per default.

2. Come possiamo controllare che la chiamata alla funzione abbia restituito un numero primo e non qualcos'altro?
Non potete semplicemente confrontarlo con INT_MAX.
Dovete confrontarlo con l'ultimo numero primo disponibile inferiore a INT_MAX.
Confrontare ogni volta il risultato di ogni chiamata di queste funzioni con qualche numero magico per assicurarsi che tutto sia corretto, mi sembra assurdo.

1. Il tuo caso di ottenere un numero non semplice usando il metodo GetPrime è l'unico che ho incontrato finora. Questo incidente sarà risolto cambiando il controllo quando si generano i numeri primi:

//--- outside of our predefined table
   for(int i=(min|1); i<=INT_MAX; i+=2)
     {
      if(IsPrime(i) && ((i-1)%s_hash_prime!=0))
         return(i);
     }
   return(min);

2. Il metodo CPrimeGenerator::IsPrime è usato per controllare il numero per semplicità

 

Ho provato a passare dalla mia ArrayList alla tua, che è in Generic/ArrayList.mqh

ME non dà nulla dopo ".".

Come posso ottenere il valore? Get() e [] mancano nella classe.

E non tiene conto del fatto che potrebbe esserci un array di puntatori.

E chi crea questa biblioteca?

Ecco la mia versione di ArrayList da Java:

File:
ArrayList.mqh  46 kb
 
Non c'erano modelli di classe quando ho creato questa variante.
 
Roman Konopelko:

Affinché le collezioni generiche funzionino correttamente con oggetti di classe, queste classi devono implementare l'interfaccia IEqualityComparable in cui sono definiti i metodi Equals e HashCode. Significa che l'utente deve impostare i metodi di calcolo dei codici hash e questa è l'unica opzione finora, perché è impossibile implementare questi metodi automaticamente, come è stato fatto in .Net, per esempio, per mezzo di MQL5.

Allora perché il tuo template funziona con qualsiasi tipo, ingannando il programmatore? Se solo le classi ereditate da IEqualityComparable funzionano correttamente, allora dovremmo disabilitare il lavoro con altri tipi a livello di compilatore.

Lasciate che vi ricordi questo codice:

//+------------------------------------------------------------------+
//| Returns a hashcode for custom object.                            |
//+------------------------------------------------------------------+
template<typename T>
int GetHashCode(T value)
  {
//--- try to convert to equality comparable object  
   IEqualityComparable<T>*equtable=dynamic_cast<IEqualityComparable<T>*>(value);
   if(equtable)
     {
      //--- calculate hash by specied method   
      return equtable.HashCode();
     }
   else
     {
      //--- calculate hash from name of object
      return GetHashCode(typename(value));
     }
  }

Credo che questa funzione dovrebbe essere sostituita da questa:

template<typename  T>
int GetHashCode(IEqualityComparable<T> &value)
  {
    return value.HashCode()
  }
 
Alexey Navoykov:

Allora perché il tuo template funziona con qualsiasi tipo, ingannando il programmatore? Se solo le classi ereditate da IEqualityComparable funzionano correttamente, allora dovresti impedire di lavorare con altri tipi a livello di compilatore.

Sarà scomodo lavorare con questo tipo. Gli overload di GetHashCode per i tipi standard mostrano l'interfaccia per ottenere il codice hash.


Ciò che è fastidioso è che è assente.

template<typename T>
interface IEqualityComparable
  {
//--- method for determining equality
   bool              Equals(T & value);
//--- method to calculate hash code   
   int               HashCode(void);
  };


Vale a dire per gli oggetti che si rompono ora.

 
fxsaber:

Questo sarebbe imbarazzante da lavorare. Gli overload di GetHashCode per i tipi standard mostrano l'interfaccia per ottenere il codice hash.

Cosa c'è di comodo ora? Il fatto che passando un enum o un puntatore di una classe che non supporta l'interfaccia in questa funzione, si ottiene solo il nome della classe? ) E soprattutto, il codice funziona e compila come se tutto fosse normale.

 
Alexey Navoykov:

Qual è la comodità ora? Che passando un enum o un puntatore di una classe che non supporta l'interfaccia in questa funzione, si ottiene solo il nome della classe? Fantastico hash ) E soprattutto, il codice funziona, compila come se tutto fosse normale. Questo non è il caso.

Sì, hanno fatto una schifezza. Hanno sconsideratamente copiato e incollato da NetFramework mentre è ovvio che senza supporto per le interfacce a livello di linguaggio non può funzionare adeguatamente. Ricordo il livello dei codici MQ 6-7 anni fa e ora è spazzatura rispetto a quel tempo.

 
Alexey Navoykov:

Cosa c'è di comodo ora? Il fatto che passando un enum o un puntatore di una classe che non supporta l'interfaccia in questa funzione, si ottiene solo il nome della classe? Bello l'hash ) E soprattutto, il codice funziona e compila come se tutto fosse ok. Non è così.

Sono d'accordo, è meglio ottenere subito un errore di compilazione che affrontare la lunga questione del perché non funziona.

Ad essere onesti, non vedo nemmeno perché hanno attaccato un'interfaccia lì. Dopo tutto, avete solo bisogno di sovraccaricare GetHashCode per il tipo richiesto e non di iniziare a creare IEqualityComparable.

Motivazione: