Библиотека Generic классов - ошибки, описание, вопросы, особенности использования и предложения - страница 20

 
Sergey Dzyublik:

1. Устранить неоднозначность поведения:
Если передать "INT_MAX - 10" в качества параметра в CPrimeGenerator::ExpandPrime, то вернется результат "INT_MAX".
Если передать "INT_MAX - 10" в качества параметра в CPrimeGenerator::GetPrime, то вернется тот же результат: "INT_MAX - 10".

Так же в обоих случаях возвращаемое значение не является простым числом, что вводит пользователя в заблуждение.

По первому пункту:

Здесь нет никакой неоднозначности.

Метод GetPrime должен возвращать ближайшее сверху простое число, но на промежутке от INT_MAX - 10 до INT_MAX таковых нет, поэтому и возвращается INT_MAX - 10.

Метод ExpandPrime с начало удваивает входное значение и уже от полученного числа вызывается метод GetPrime.

Плюс к этому в ExpandPrime стоит проверка на выход за пределы INT_MAX:

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

По моему логика поведения этих методов абсолютно однозначная и правильная.


Относительно второго и третьего пункта:

Предложенные вами изменения имеют отношения по большей части только к краевым задачам, когда размеры CHashMap очень большие. При этом нет никаких гарантий, что они будут иметь положительное влияние на производительность, поэтому нужно проводить отдельные исследования для определения корректности предложенных вами изменений.

 
Roman Konopelko:

Здесь нет никакой неоднозначности.
Метод GetPrime должен возвращать ближайшее сверху простое число, но на промежутке от INT_MAX - 10 до INT_MAX таковых нет, поэтому и возвращается INT_MAX - 10.
Метод ExpandPrime с начало удваивает входное значение и уже от полученного числа вызывается метод GetPrime.
Плюс к этому в ExpandPrime стоит проверка на выход за пределы INT_MAX:
По моему логика поведения этих методов абсолютно однозначная и правильная.


1. Функции могут вернуть не простые числа, а непонятно какое числа. 
Как пользователь использует эти данные - это его проблемы, может он их в long кастит и дальше в супервычислительные функции передает, какая разница.
Факт заключается в том, что может возвращаться не то, что заявлено и ожидается по умолчанию от функций.

2. Как проверить, что в результате вызова функции вернулось простое число, а не что попало?
Просто сравнить с INT_MAX не получится.
Нужно сравнивать с последним доступным простым числом меньше INT_MAX.
Каждый раз сравнивать результат вызова этих функций с каким-то магическим числом, что бы убедиться что все работает верно - как по мне, это бред.

 
Sergey Dzyublik:

1. Функции могут вернуть не простые числа, а непонятно какое числа. 
Как пользователь использует эти данные - это его проблемы, может он их в long кастит и дальше в супервычислительные функции передает, какая разница.
Факт заключается в том, что может возвращаться не то, что заявлено и ожидается по умолчанию от функций.

2. Как проверить, что в результате вызова функции вернулось простое число, а не что попало?
Просто сравнить с INT_MAX не получится.
Нужно сравнивать с последним доступным простым числом меньше INT_MAX.
Каждый раз сравнивать результат вызова этих функций с каким-то магическим числом, что бы убедиться что все работает верно - как по мне, это бред.

1. Ваш случай получения методом GetPrime не простого числа, пока что единственный, который я встречал. Данный инцидент будет исправлен путем изменения проверки при генерации простых чисел:

//--- 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. Для проверки числа на простоту реализован метод CPrimeGenerator::IsPrime

 

Попытался перейти со своего ArrayList на ваш, который в Generic/ArrayList.mqh

МЕ после "." ничего не выдаёт.

Как получить значение? Get() и [] отсутствуют в классе.

И не учитывается, что может быть массив указателей.

И кто эту библиотеку создает?

Вот мой вариант ArrayList  из Java:

Файлы:
ArrayList.mqh  46 kb
 
Классовых шаблонов не было, когда я создавал этот вариант.
 
Roman Konopelko:

Для того что бы коллекции Generic работали корректно с объектами классов, эти классы должны реализовывать интерфейс IEqualityComparable, в котором определены методы Equals и HashCode. Т.е. пользователю самому необходимо задавать методы вычисления хэш кодов, и это пока единственный вариант, так как реализовать эти методы автоматически, как это сделано например в .Net, средствами MQL5 не получиться.

Тогда зачем ваш шаблон работает с любыми типами, вводя программиста в заблуждение?  Если корректно работают только классы, наследуемые от IEqualityComparable, значит нужно запретить работу с другими типами на уровне компилятора.

Напомню, речь об этом коде:

//+------------------------------------------------------------------+
//| 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));
     }
  }

Полагаю, эту функцию надо заменить на такую:

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

Тогда зачем ваш шаблон работает с любыми типами, вводя программиста в заблуждение?  Если корректно работают только классы, наследуемые от IEqualityComparable, значит нужно запретить работу с другими типами на уровне компилятора.

С таким неудобно будет работать. По перегрузкам GetHashCode для стандартных типов виден интерфейс получения хэш-кода.


Напрягает отсутствие этого

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


Т.е. для объектов облом сейчас.

 
fxsaber:

С таким неудобно будет работать. По перегрузкам GetHashCode для стандартных типов виден интерфейс получения хэш-кода.

А в чём удобство сейчас?  То что передав в эту функцию enum или указатель класса, не поддерживающего интерфейс, получаешь просто имя класса?  Шикарный хэш )  И главное, код работает, компилируется, как будто всё нормально.   Это не дело.

 
Alexey Navoykov:

А в чём удобство сейчас?  То что передав в эту функцию enum или указатель класса, не поддерживающего интерфейс, получаешь просто имя класса?  Шикарный хэш )  И главное, код работает, компилируется, как будто всё нормально.   Это не дело.

Да, фигню они сделали. Бездумно скопипастели с NetFramework, хотя очевидно же что без поддержки интерфейсов на уровне языка, это не может работать адекватным образом. Помню уровень кодов от MQ 6-7 лет назад и сейча - по сравнению с тем временем сегодня мрак какой-то.

 
Alexey Navoykov:

А в чём удобство сейчас?  То что передав в эту функцию enum или указатель класса, не поддерживающего интерфейс, получаешь просто имя класса?  Шикарный хэш )  И главное, код работает, компилируется, как будто всё нормально.   Это не дело.

Согласен, лучше сразу получить ошибку компиляции, чем долго разбираться, почему же не работает.

Честно говоря, сходу и не видно, зачем там прилепили интерфейс. Ведь напрашивается просто перегрузка GetHashCode для нужного типа, а не начинать городить IEqualityComparable.

Причина обращения: