Как по мне, если объект не реализует некий интерфейс или метод, то лучше явно генерировать исключение, чем втихую замалчивать, а потом непонятно сколько искать источник проблем.
В MQL5 нет интерфейсов.
В MQL5 нет исключений.
В итоге, да, получается знатный самострел и явное умалчивание о проблеме с кодом.
По той же причине сравнение некорректное. Как можно сравнивать пользовательский CHashMap и работу с системными функциями для получения торгового окружения?
Пишите дальше неоптимальный код, раз железных аргументов не принимаете.
Пишите дальше неоптимальный код, раз железных аргументов не принимаете.
Какую-то ахинею оба написали, ни грамма не поняв, что HashMap в текущем виде не работает для struct и union.
Уважаемый, если вы что-то покуриваете и не в состоянии внимательно причитать пост собеседника - то это ваши проблемы и лечиться стоит не всем остальным, а исключительно больному. Повторяем: речи о struct и union ни кто не подымал, ваши идеи ни кто не оспаривал по этому поводу....
Речь шла конкретно об этих сроках кода. Из стандартной библиотеки:
//+------------------------------------------------------------------+//| 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 objectreturn GetHashCode(typename(value));
}
}
//+------------------------------------------------------------------+
template<typename T>
int GetHashCode(T &value)
{
return GetHashCode(typename(value));
}
Что вам пытались донести: Хеш используется для ускорения поиска элементов в контейнере. Скорость O(1) - не зависит от количества добавленных элементов в контейнер. Ситуация - пользователь использует в качестве ключа свой собственный класс. 1) Из-за отсутствия множественного наследования интерфейсов (В MQL5 нет интерфейсов) пользователь не может наследоваться от IEqualityComparable; 2) Так же пользователь забывает указать явную спецификацию для шаблонной функции GetHashCode.
Последствия - пользователю ни как не сообщается о том, что он что-то опустил и код удачно выполняется без генерации исключений (В MQL5 нет исключений). Скорость падает от O(1) со средней константой расчета хеша до O(n) с достаточно большой константой на сравнение. Только при большом количестве элементов в контейнере и при трате уймы времени на поиск bottleneck в реализации, пользователю, возможно, удастся найти причину проблем - отсутствие явной спецификация GetHashCode для его класса. Без обид, спасибо.
Уважаемый, если вы что-то покуриваете и не в состоянии внимательно причитать пост собеседника - то это ваши проблемы и лечиться стоит не всем остальным, а исключительно больному.
Варежку, видимо, закрыть трезвенникам не получится
#include <TypeToBytes.mqh> // https://www.mql5.com/ru/code/16280#include <crc64.mqh> // https://www.mql5.com/en/blogs/post/683577template<typename T>
int GetHashCode( T &value )
{
ulong crc = 0;
return((int)crc64(crc, _R(value).Bytes, sizeof(T)));
}
template<typename T>
int GetHashCode( T &value[] )
{
ulong crc = 0;
return((int)crc64(crc, _R(value).Bytes, ArraySize(value) * sizeof(T)));
}
Хотя изначально из ветки не планировалось делать сборник примеров, все-таки чувствую необходимость добавить несколько таких примеров, что бы те кто еще не использует алгоритмы в своей практике, поняли почему это удобно и главное просто.
Довольно часто требуется переводить числовые константы в строковые литералы. Например, коды ошибок лучше дублировать понятной надписью, раскрывающей суть ошибки. Это не очень сложная задача и обычно ее решают через специальную функцию или switch-case или множество if такого плана:
Любое такое решение имеет право на жизнь. Но мы опишем решение, основанное на CHashMap и покажем те преимущества которые оно дает.
Данный алгоритм может выглядит так:
Создаем ассоциативный массив вида <код ошибки - описание ошибки>;
Добавляем в этот словарь возможные коды ошибки и их описание;
Напрямую и без посредников обращаемся к словарю для получения описания ошибки по ее коду
Данный код выглядит следующим образом:
//+------------------------------------------------------------------+//| OrdersID.mq5 |//| Copyright 2017, MetaQuotes Software Corp. |//| http://www.mql5.com |//+------------------------------------------------------------------+#property copyright"Copyright 2017, MetaQuotes Software Corp."#property link"http://www.mql5.com"#property version"1.00"#include <Generic\HashMap.mqh>
inputulong FindTicketOrder = 82479995;
CHashMap<int, string> ErrorDescription;
//+------------------------------------------------------------------+//| Script program start function |//+------------------------------------------------------------------+void AddDescriptionInfo(void)
{
// Добавим коды системных ошибок
ErrorDescription.Add(0, "Операция выполнена успешно");
ErrorDescription.Add(4001, "Неожиданная внутренняя ошибка");
ErrorDescription.Add(4002, "Ошибочный параметр при внутреннем вызове функции клиентского терминала");
ErrorDescription.Add(4003, "Ошибочный параметр при вызове системной функции");
ErrorDescription.Add(4004, "Недостаточно памяти для выполнения системной функции");
// Можно добавлять константные значения вместо чисел
ErrorDescription.Add(ERR_STRUCT_WITHOBJECTS_ORCLASS, "Структура содержит объекты строк и/или динамических массивов и/или структуры с такими объектами и/или классы");
ErrorDescription.Add(ERR_INVALID_ARRAY, "Массив неподходящего типа, неподходящего размера или испорченный объект динамического массива");
ErrorDescription.Add(ERR_ARRAY_RESIZE_ERROR, "Недостаточно памяти для перераспределения массива либо попытка изменения размера статического массива");
//...
}
//+------------------------------------------------------------------+//| Script program start function |//+------------------------------------------------------------------+voidOnStart()
{
AddDescriptionInfo();
string last_error = "";
ErrorDescription.TryGetValue(GetLastError(), last_error);printf("Последняя ошибка: " + last_error);
}
//+------------------------------------------------------------------+
После того, как коды ошибок заполнены, доступ к ним осуществляется всего одной строкой, без использования разных функций. Кроме того, напомню, что в некоторых случаях, этот код будет работать даже быстрее чем несколько десятков if, т.к. адресация к нужной ошибки происходит напрямую, со средней скоростью O(1).
После того, как коды ошибок заполнены, доступ к ним осуществляется всего одной строкой, без использования разных функций.
ErrorToString в любом случае придется писать. Поэтому аргумент, как плюс, слабый.
Кроме того, напомню, что в некоторых случаях, этот код будет работать даже быстрее чем несколько десятков if, т.к. адресация к нужной ошибки происходит напрямую, со средней скоростью O(1).
То мы намертво зашиваем коды ошибок в сам код эксперта. Когда пы заполняем словарь, то мы делаем это динамически, т.е. в момент выполнения программы. Динамический подход нам дает большую гибкость. Например, коды ошибок могут содержаться в специальном файле, например ErrorsCode.txt:
4001;Операция выполнена успешно
4002;Неожиданная внутренняя ошибка
4003;Ошибочный параметр при вызове системной функции
...
В момент запуска программа может считать этот файл и заполнить словарь нужными кодами, а затем пользователю возвращать нужный вариант строки. Таких файлов может быть несколько: один файл на каждый язык. Таки образом, может быть выполнена локализация, когда в зависимости от языка пользователя выводятся коды ошибок на его языке. Более того, пользователь сам может перевести эти коды ошибок на свой родной язык один раз, и программа сама "научиться" выводить нужное сообщение на его языке. Именно так выполняется локальизация большинства программ, когда перевод меню содержится в текстовом файле, а программа загружает его, в зависимости от настроек. Т.е. без какой-либо перекомплиляции программы и изменения ее алгоритма, мы можем существенно влиять на представление ее результатов.
Как по мне, если объект не реализует некий интерфейс или метод, то лучше явно генерировать исключение, чем втихую замалчивать, а потом непонятно сколько искать источник проблем.
В итоге, да, получается знатный самострел и явное умалчивание о проблеме с кодом.
По той же причине сравнение некорректное. Как можно сравнивать пользовательский CHashMap и работу с системными функциями для получения торгового окружения?
Пишите дальше неоптимальный код, раз железных аргументов не принимаете.
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Библиотека Generic классов - ошибки, описание, вопросы, особенности использования и предложения
fxsaber, 2017.12.08 22:46
Для более реального тестерного случая (2000 сделок и 1 000 000 единичных обращений к истории) результат выглядит так
Почти 100 мс экономии на проход! Если, допустим, делаем Оптимизацию на 10 000 полноценных проходов, то Hash-вариант закончится на 15 минут быстрее.
В итоге, да, получается знатный самострел и явное умалчивание о проблеме с кодом.
Пишите дальше неоптимальный код, раз железных аргументов не принимаете.
Какую-то ахинею оба написали, ни грамма не поняв, что HashMap в текущем виде не работает для struct и union.Уважаемый, если вы что-то покуриваете и не в состоянии внимательно причитать пост собеседника - то это ваши проблемы и лечиться стоит не всем остальным, а исключительно больному.
Повторяем: речи о struct и union ни кто не подымал, ваши идеи ни кто не оспаривал по этому поводу....
Речь шла конкретно об этих сроках кода.
Из стандартной библиотеки:
И ваши добавленные:
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Библиотека Generic классов - ошибки, описание, вопросы, особенности использования и предложения
fxsaber, 2017.12.08 21:17
Добавил еще одну перегрузку
Что вам пытались донести:
Хеш используется для ускорения поиска элементов в контейнере. Скорость O(1) - не зависит от количества добавленных элементов в контейнер.
Ситуация - пользователь использует в качестве ключа свой собственный класс.
1) Из-за отсутствия множественного наследования интерфейсов (В MQL5 нет интерфейсов) пользователь не может наследоваться от IEqualityComparable;
2) Так же пользователь забывает указать явную спецификацию для шаблонной функции GetHashCode.
Последствия - пользователю ни как не сообщается о том, что он что-то опустил и код удачно выполняется без генерации исключений (В MQL5 нет исключений).
Скорость падает от O(1) со средней константой расчета хеша до O(n) с достаточно большой константой на сравнение.
Только при большом количестве элементов в контейнере и при трате уймы времени на поиск bottleneck в реализации, пользователю, возможно, удастся найти причину проблем - отсутствие явной спецификация GetHashCode для его класса.
Без обид, спасибо.
Уважаемый, если вы что-то покуриваете и не в состоянии внимательно причитать пост собеседника - то это ваши проблемы и лечиться стоит не всем остальным, а исключительно больному.
Варежку, видимо, закрыть трезвенникам не получится
Хотя изначально из ветки не планировалось делать сборник примеров, все-таки чувствую необходимость добавить несколько таких примеров, что бы те кто еще не использует алгоритмы в своей практике, поняли почему это удобно и главное просто.
Пример 1: Ассоциация ошибки времени выполнения с ее строковым описанием
Довольно часто требуется переводить числовые константы в строковые литералы. Например, коды ошибок лучше дублировать понятной надписью, раскрывающей суть ошибки. Это не очень сложная задача и обычно ее решают через специальную функцию или switch-case или множество if такого плана:
Любое такое решение имеет право на жизнь. Но мы опишем решение, основанное на CHashMap и покажем те преимущества которые оно дает.
Данный алгоритм может выглядит так:
- Создаем ассоциативный массив вида <код ошибки - описание ошибки>;
- Добавляем в этот словарь возможные коды ошибки и их описание;
- Напрямую и без посредников обращаемся к словарю для получения описания ошибки по ее коду
Данный код выглядит следующим образом:После того, как коды ошибок заполнены, доступ к ним осуществляется всего одной строкой, без использования разных функций. Кроме того, напомню, что в некоторых случаях, этот код будет работать даже быстрее чем несколько десятков if, т.к. адресация к нужной ошибки происходит напрямую, со средней скоростью O(1).
После того, как коды ошибок заполнены, доступ к ним осуществляется всего одной строкой, без использования разных функций.
ErrorToString в любом случае придется писать. Поэтому аргумент, как плюс, слабый.
Кроме того, напомню, что в некоторых случаях, этот код будет работать даже быстрее чем несколько десятков if, т.к. адресация к нужной ошибки происходит напрямую, со средней скоростью O(1).
А вот это несомненный плюс.
В предолженном решение через словарь есть несколько плюсов, главный из которых не совсем очевиден с первого взгляда. Когда мы пишем код вроде такого:
То мы намертво зашиваем коды ошибок в сам код эксперта. Когда пы заполняем словарь, то мы делаем это динамически, т.е. в момент выполнения программы. Динамический подход нам дает большую гибкость. Например, коды ошибок могут содержаться в специальном файле, например ErrorsCode.txt:
В момент запуска программа может считать этот файл и заполнить словарь нужными кодами, а затем пользователю возвращать нужный вариант строки. Таких файлов может быть несколько: один файл на каждый язык. Таки образом, может быть выполнена локализация, когда в зависимости от языка пользователя выводятся коды ошибок на его языке. Более того, пользователь сам может перевести эти коды ошибок на свой родной язык один раз, и программа сама "научиться" выводить нужное сообщение на его языке. Именно так выполняется локальизация большинства программ, когда перевод меню содержится в текстовом файле, а программа загружает его, в зависимости от настроек. Т.е. без какой-либо перекомплиляции программы и изменения ее алгоритма, мы можем существенно влиять на представление ее результатов.