четверг, 5 сентября 2013 г.

Про "словари" в Delphi

Навеяно вот этим - http://18delphi.blogspot.ru/2013/09/blog-post_3.html?showComment=1378309406219#c8331945982295222932

Друзья мои!

Давайте всё же пытаться "отделять мух от котлет".

Есть использование "словарей" как СТРУКТУРЫ данных - ключ-значение. А есть - использование "словарей" для передачи "нефиксированного списка "именнованных параметров"".

Это - РАЗНЫЕ вещи.

Это надо - ПОНИМАТЬ.

То, что "именованные параметры" сделаны в Python ЧЕРЕЗ "словари" - я (теперь) - ЗНАЮ.

Не надо мне об этом напоминать.

Но это всего лишь - "совпадение".

Теперь о "словарях" как о СТРУКТУРЕ данных.

Есть такое мнение - http://18delphi.blogspot.ru/2013/09/blog-post_3.html?showComment=1378316009315#c1276656632326196246
"Начиная с версии 2009 (если не ошибаюсь) в Delphi появились обобщённые типы (generics).
Так что, можно сказать, словари есть."

На мой взгляд - generic'и и "словари" - СЛАБО связанные вещи. То есть конечно generic'и это КОНЕЧНО - "удобная почва для реализации словарей". Не спорю.

Как и другие шаблонные решения.

Но - НЕ БОЛЕЕ ТОГО.

Вывод "есть generic'и - значит считай есть словари - В КОРНЕ - неверен".

Generic'и - достаточное, но не НЕОБХОДИМОЕ условие для ВОЗМОЖНОСТИ существования словарей.

Я словарей сделал - "много разных". ЗАДОЛГО ДО появления generic'ов.

(да и вообще ДО Delphi)

Как? Да ПО-РАЗНОМУ, начиная от использования дискриминантов и вариантных типов и кончая "примесями".

Если есть КОНКРЕТНЫЕ вопросы - задавайте, я - ОБЯЗАТЕЛЬНО отвечу.

Сходная тема тут - http://18delphi.blogspot.com/2013/07/2.html (ну и далее - по ссылкам).

Теперь про "переменные списки именованных параметров". Которые НАПРЯМУЮ не являются "словарями". Хотя и МОГУТ быть ими реализованы. И БОЛЕЕ ТОГО - РЕАЛИЗОВАНЫ в Python.

Я в Delphi делаю примерно так (просто как пять копеек):

type
 TNamedParam = record
  rName : String;
  rValue : String;
end;

function Param(aName : String; aValue : String) : TNamedParam;
begin
 Result.rName := aName;
 Result.rValue := aValue;
end;

procedure SomeFuctionWithNamedParams(aParams : array of TNamedParam);
begin
 for l_Index := Loaw(aParams) to High(aParams) do
  ProcessSomeParam(aParams[l_Index]);
end;

SomeFuctionWithNamedParams([
 Param('Size', '10'),
 Param('Height', '100'),
 Param('Width', '200')
]);

всё! НИКАКОЙ МАГИИ.

Не забываем про дискриминанты и overload.

(Про Automation и IDispatch - я СОЗНАТЕЛЬНО умолчал).

http://18delphi.blogspot.ru/2013/09/blog-post_3.html?showComment=1378304020959#c7539045129727196205

Понятно, как я бы переделал бы SetFontProps?

И вообще - я сторонник СТРОГОЙ ТИПИЗАЦИИ.

А не "разбора строк", как это зачастую делается у Embarcadero в FM (интересно кстати?).

И не сторонник "превращать Delphi в Python". Равно как и не сторонник обратного.

------

Я - ЛЮБЛЮ duck-typing и МНОЖЕСТВЕННОЕ наследование, но считаю, что области их применения должны быть СИЛЬНО ограничены.

Равно как и области применения "перегрузки операторов".

Ну это я так - "на будущее"...

1 комментарий:

  1. NameRec:

    «На мой взгляд - generic'и и "словари" - СЛАБО связанные вещи. То есть конечно generic'и это КОНЕЧНО - "удобная почва для реализации словарей". Не спорю.»
    – В моём комментарии имелось ввиду, что механизм обобщённых типов представляет собой естественный путь обеспечения *стандартной* реализации словаря, которая будет содержаться в программном коде в единственном экземпляре, и будет соответствовать принципу 80/20.
    Т.е. 80% (на самом деле, в данном случае больше) потребностей в словарях будет решаться посредством стандартной реализации, остальные 20% (на самом деле — меньше) посредством наследования от базового класса.
    В таком случае, при необходимости в словаре можно будет использовать стандартный класс с требуемой параметризацией. Как это делается в C++, Java, C# и т.п. и чего мне не хватало в Delphi с момента появления шаблонов в стандарте C++.

    Я не собираюсь критиковать технику подмешиваний применительно к реализации словарей (да и других структур данных) в Delphi версии < 2009, но сам выбрал для себя DeCAL для этой цели, а в Delphi версий >= 2009 рекомендовал бы для этой цели механизм обобщённых типов, как понятный всем и встроенный в язык.

    «Понятно, как я бы переделал бы SetFontProps?»
    Да, понятно :-) Тем более, что в похожих ситуациях сам так поступаю приблизительно так же.
    В моём примере я преследовал цель проиллюстрировать, что для задания свойств агрегируемого объекта самым простым решением будет обеспечить соответствующий метод в агрегирующем. Не вдаваясь в детали.
    К слову, в Python для этой цели можно было бы использовать возможности самого языка - определить функцию или метод, например, так:
    {code}
    def assign(self, Left=None, Top=None, Right=None, Bottom=None)
    {/code}
    Ниже приводятся варианты вызова этой функции, все они корректны:
    {code}
    bounds.assign(Left=5, Width=100)
    … … ...
    bounds.assign(Top=0, Height=50)
    … … …
    bounds.assign(5, 0, 100, 50)
    {/code}

    ОтветитьУдалить