Здравствуйте, T4r4sB, Вы писали: TB>И как же? Я вот не знаю, как формируется WM_LBUTTONDBLCLK.
Да очень просто. При каждом клике запоминается его место и время. И проверяется, что если предыдущий был в течение GetDoubleClickTime и внутри прямоугольника размером SM_CXDOUBLECLK and SM_CYDOUBLECLK относительно нынешнего, то в дополнение к WM_LBUTTONCLICK нужно сгенерировать WM_LBUTTONDBLCLK TB> Это потому, что начинал с Дельфи?
Возможно.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, vsb, Вы писали:
vsb>И в Go до недавнего времени и в Java до 5 версии не было генериков. И ничего — через interface{} / Object прекрасно все алгоритмы писались.
Просто Go не предназначен для алгоритмов. Не предназначен — и всё. И про "прекрасно" на Java можете мне не рассказывать. Там вся прекрасность связана с тем, что "нуачо вы хотели, это же Java. Если хотите перформанс — берите плюсы".
vsb>Я больше скажу — ни в Go, ни в Java у меня не было никакой необходимости писать какие-то обобщённые алгоритмы.
Отож. Ни одному паскалисту и в голову не придёт жаловаться на отсутствие замыканий, ФВП, или там генериков.
А вот у меня во времена оные потребность в коллекциях была. И мы честно пилили хешмапу int->TObject и string->TObject путём копипейста.
vsb>И я даже ещё больше скажу. Крамольную вещь. Те, кто любят писать обобщённые алгоритмы, как правило, тратят время впустую на ментальную гимнастику вместо того, чтобы решать проблемы.
Категорически с вами не согласен. Любители писать обобщённые алгоритмы вкладывают своё время в написание обобщённых алгоритмов.
Благодаря этому потребители потом могут просто взять готовый алгоритм и начать его использовать. Если язык не позволяет написать обобщённый алгоритм, то его никто так и не напишет.
Вот, Khimik до сих пор учится сортировать массивы чисел с плавающей запятой — потому, что в классическом до-дженериковом Delphi нет никакого способа отсортировать такой массив.
vsb>По остальным пунктам в целом согласен, но главная проблема Delphi это то, что её не смогли адекватно развивать. Уж не знаю, кто конкретно был в этом виноват, но если бы за Delphi стоял Microsoft с нормальным финансированием, а не какие-то неизвестные компании, пытающиеся урвать хоть что-то перед очередной перепродажей, если бы тот же Хейлсберг её продолжал развивать, скорей всего с ней всё было бы хорошо.
Основная проблема Delphi — падение спроса, сокращение выручки, банкротство компании. Финал.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
vsb>>По остальным пунктам в целом согласен, но главная проблема Delphi это то, что её не смогли адекватно развивать. Уж не знаю, кто конкретно был в этом виноват, но если бы за Delphi стоял Microsoft с нормальным финансированием, а не какие-то неизвестные компании, пытающиеся урвать хоть что-то перед очередной перепродажей, если бы тот же Хейлсберг её продолжал развивать, скорей всего с ней всё было бы хорошо.
S>Основная проблема Delphi — падение спроса, сокращение выручки, банкротство компании. Финал.
Тут нужно учитывать, что Delphi (бесплатный) был распространён в бывших странах СССР.
Но вот на западе где нужно было ещё и платить, его популярность была не высокой.
Вот Хейлсберг сделал C# практически клоном из Delphi (кроме метаклассов). И его популярность одна из самых высоких, а развитие самое высокое.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Sinclair, Вы писали:
S> R>Это, конечно, глупость несусветная. Особенно про перегрузку операторов (запахло костыльным дженерик-мафом ).
S> При чём тут женерик-маф? Я на Delphi оттрубил своё по полной программе, так что пишу с полной ответственностью.
При том же, причем тут перегрузка операторов для обобщенного алгоритма сортировки
S> Банально никаких коллекций на Delpgi не было, кроме TList.
Не знаю, как и что ты оттрубил, но в Delphi был модуль Contnrs с коллекциями: стек, очередь, хэш-таблицы и др. Он точно был уже в Delphi 5 (возможно и раньше, но проверять лениво).
S> Сделать простую штуку типа "отсортировать список по пользовательскому критерию" — боль, ужас, унижение.
Это, как раз, пример использования процедурного типа. Хорошее решение. В дженериковых версиях все проще:
begin
var l := TList<string>.Create(['3', '2', '1']);
// default
l.Sort;
// custom
l.Sort(TComparer<string>.Construct(
function(const Left, Right : string) : Integer
begin
Result := CompareText(Left, Right);
end));
for var s in l do
WriteLn(s);
end.
S> R>Например, дженерики появились в дельфях всего на три года позже, чем в шарпе.
S> И на 20 лет позже, чем в C++.
Так Delphi и моложе плюсов, почти на двадцать...
S> Ага. Расскажите мне, во сколько строк кода запишется на Object Pascal какая-нибудь банальщина типа "обойти граф, заданный моей объектной моделью, в глубину, отфильтровав по параметру, частично заданному пользователем, и собрать некую агрегатную величину". Ну там — берём AST программы, ищем узлы-референсы, заимпортированные из модуля X, для них считаем сумму условной вычислительной сложности.
S> На более-менее любом современном языке это будет весьма простой генератор/итератор, за которым .filter(...).map(...).reduce(...). S> На Delphi остаётся только пердолиться с "процедурными типами" и/или Visitor Pattern.
На Delphi это делается ничуть не сложнее Энумераторы были еще в D2005.
Здравствуйте, Sinclair, Вы писали: S>Здравствуйте, rudzuk, Вы писали: R>>Это, конечно, глупость несусветная. Особенно про перегрузку операторов (запахло костыльным дженерик-мафом ). S>При чём тут женерик-маф? Я на Delphi оттрубил своё по полной программе, так что пишу с полной ответственностью. S>Банально никаких коллекций на Delpgi не было, кроме TList. S>Сделать простую штуку типа "отсортировать список по пользовательскому критерию" — боль, ужас, унижение.
тут жопа только в бестолковом примере, писанном кем — то не знающим языка.
Нужно применять адекватные классы, в данном случае есть класс TStringList, любимый формоклепателями.
Там сортировка вызывается 1 строчкой.
Это если говорить о додженериковом языке. S>Ага. Расскажите мне, во сколько строк кода запишется на Object Pascal какая-нибудь банальщина типа "обойти граф, заданный моей объектной моделью, в глубину, отфильтровав по параметру, частично заданному пользователем, и собрать некую агрегатную величину". Ну там — берём AST программы, ищем узлы-референсы, заимпортированные из модуля X, для них считаем сумму условной вычислительной сложности.
типа такого (код из нашего комплекса)?
class function TMatchAPI.outside(aNB: TNB; aMode: TOutsideMode): RArray<TNB>;
var
lCEs: RArray<TCE>;
lRules: TCEFetchRules;
begin
Result := RArray<TNB>.init;
if TCEAPI.globalId(aNB) <> '' then
begin
Result.add(aNB);
exit;
end;
lRules.init;
lRules := lRules +
TCERules.reducerExtraTerminals +
function(aTerminal: TCIMTopologyTerminal): TFetchAction
begin
Result := faContinue;
if isBreakObject(aTerminal.Element, aMode) then
Result := faBreakAndFetch;
end;
lRules := lRules +
function (aFrom: TCIMTopologyTerminal; var aTo: RArray<TCIMTopologyTerminal>): Boolean
var
lNewTo: RArray<TCIMTopologyTerminal>;
begin
Result := True;
lNewTo :=
aTo.filter(
function (aT: TCIMTopologyTerminal): Boolean
begin
Result := isBreakObject(aT.Element, aMode);
end
);
if lNewTo.count > 0 then
begin
aTo := lNewTo;
exit;
end;
lNewTo :=
aTo.filter(
function (aT: TCIMTopologyTerminal): Boolean
var
lCandle: TCE;
begin
lCandle := TCEAPI.candleLine(aT.Element);
Result := (lCandle <> nil) and (lCandle.terminalsS.map<TCE>(TCEAPI.connectedCE).count = 1) and isBreakObject(lCandle, aMode);
end
);
if lNewTo.count > 0 then
begin
aTo := lNewTo;
exit;
end;
end;
Result :=
TRStream<TNB>.just(aNB)
.map(TCEAPI.extractReducers)
.map<TCE>(TCEAPI.ce)
.map<TNB>(
procedure (aCE: TCE; var aMap: TProc<TNB>)
begin
TCEAPI.iterateTopology(aCE, lRules)
.map<TNB>(
procedure (aCE: TCE; var aMap: TProc<TNB>)
var
lNB: TNB;
begin
if aCe.IsChildOrEqual(ttcTransformerWinding) then
lNB := TCEAPI.grpFromWinding(aCe as TTransformerWinding)
else
lNB := aCE;
if isNodeObject(aCE) and ((aMode = omNearest) or (TCEAPI.globalId(lNB) <> '')) then
aMap(lNB);
end)
.forEach(aMap);
end
)
.distinct()
.toArray();
end;
Ненавижу такое написание.
1. Не поддается отладке отладчиком.
2. сложно профилировать. сложно найти "бутылочное горлышко" производительности.
3. сложно рефакторить, сложно определяется на каждом этапе какая там структура данных на выходе.
4. нереально повторно использовать код, записать похожие алгоритмы.
5. перегружает компилятор. S>На более-менее любом современном языке это будет весьма простой генератор/итератор, за которым .filter(...).map(...).reduce(...). S>На Delphi остаётся только пердолиться с "процедурными типами" и/или Visitor Pattern. R>> S>Возможно, на современном Delphi ситуация как-то поменялась; в том, который был актуален во времена расцвета его популярности, всё это суровая правда.
S>Тут нужно учитывать, что Delphi (бесплатный) был распространён в бывших странах СССР. S>Но вот на западе где нужно было ещё и платить, его популярность была не высокой. S>Вот Хейлсберг сделал C# практически клоном из Delphi (кроме метаклассов). И его популярность одна из самых высоких, а развитие самое высокое.
да, денежный вопрос тоже имеет значение. Зачем платить за Delphi, когда MS бесплатно подобное раздает
Здравствуйте, swame, Вы писали:
s> тут жопа только в бестолковом примере, писанном кем — то не знающим языка. s> Нужно применять адекватные классы, в данном случае есть класс TStringList, любимый формоклепателями. s> Там сортировка вызывается 1 строчкой.
Неа. Речь шла о пользовательском критерие сортировки, а он может быть любым. Со стринглистом такое не прокатит, если метод сравнения не перекрыть.
...
s> Ненавижу такое написание.
+100500
s> 5. перегружает компилятор.
Проблема компилятора, если корректный код его перегружает Справедливости ради.
Здравствуйте, rudzuk, Вы писали:
R>Неа. Речь шла о пользовательском критерие сортировки, а он может быть любым. Со стринглистом такое не прокатит, если метод сравнения не перекрыть.
Ну и коллекции так-то бывают не только строк.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, rudzuk, Вы писали:
R>Так Delphi и моложе плюсов, почти на двадцать...
На 10. Или на пять, если за начало принять ТурбоПаскаль с ООП и TurboVision
S>class function TMatchAPI.outside(aNB: TNB; aMode: TOutsideMode): RArray<TNB>;
S>var
S> lCEs: RArray<TCE>;
S> lRules: TCEFetchRules;
S>begin
S> Result := RArray<TNB>.init;
S> if TCEAPI.globalId(aNB) <> '' then
S> begin
S> Result.add(aNB);
S> exit;
S> end;
S> lRules.init;
S> lRules := lRules +
S> TCERules.reducerExtraTerminals +
S> function(aTerminal: TCIMTopologyTerminal): TFetchAction
S> begin
S> Result := faContinue;
S> if isBreakObject(aTerminal.Element, aMode) then
S> Result := faBreakAndFetch;
S> end;
S> lRules := lRules +
S> function (aFrom: TCIMTopologyTerminal; var aTo: RArray<TCIMTopologyTerminal>): Boolean
S> var
S> lNewTo: RArray<TCIMTopologyTerminal>;
S> begin
S> Result := True;
S> lNewTo :=
S> aTo.filter(
S> function (aT: TCIMTopologyTerminal): Boolean
S> begin
S> Result := isBreakObject(aT.Element, aMode);
S> end
S> );
S> if lNewTo.count > 0 then
S> begin
S> aTo := lNewTo;
S> exit;
S> end;
S> lNewTo :=
S> aTo.filter(
S> function (aT: TCIMTopologyTerminal): Boolean
S> var
S> lCandle: TCE;
S> begin
S> lCandle := TCEAPI.candleLine(aT.Element);
S> Result := (lCandle <> nil) and (lCandle.terminalsS.map<TCE>(TCEAPI.connectedCE).count = 1) and isBreakObject(lCandle, aMode);
S> end
S> );
S> if lNewTo.count > 0 then
S> begin
S> aTo := lNewTo;
S> exit;
S> end;
S> end;
S> Result :=
S> TRStream<TNB>.just(aNB)
S> .map(TCEAPI.extractReducers)
S> .map<TCE>(TCEAPI.ce)
S> .map<TNB>(
S> procedure (aCE: TCE; var aMap: TProc<TNB>)
S> begin
S> TCEAPI.iterateTopology(aCE, lRules)
S> .map<TNB>(
S> procedure (aCE: TCE; var aMap: TProc<TNB>)
S> var
S> lNB: TNB;
S> begin
S> if aCe.IsChildOrEqual(ttcTransformerWinding) then
S> lNB := TCEAPI.grpFromWinding(aCe as TTransformerWinding)
S> else
S> lNB := aCE;
S> if isNodeObject(aCE) and ((aMode = omNearest) or (TCEAPI.globalId(lNB) <> '')) then
S> aMap(lNB);
S> end)
S> .forEach(aMap);
S> end
S> )
S> .distinct()
S> .toArray();
S>end;
S>
Да, что-то в этом роде. S>Ненавижу такое написание.
Ну, так видно же, что оно противоестественно для языка. S>1. Не поддается отладке отладчиком.
Значит, такой отладчик. На шарпе или там тайпскрипте всё прекрасно поддаётся. S>2. сложно профилировать. сложно найти "бутылочное горлышко" производительности.
Нет ничего сложного. Если профайлер вменяемый, то он покажет, какое из замыканий вызывается чрезмерно часто. Можно будет понять, как перейти от O(N2) к O(N) S>3. сложно рефакторить, сложно определяется на каждом этапе какая там структура данных на выходе.
Рефакторить как раз очень легко. Не очень понятно, что такое "структура данных". Если речь о типе элемента коллекции, то его хорошо видно по сигнатуре функции (и IDE подсказывает, где там что). Если речь про саму коллекцию — так их там и нет, это же ленивые итераторы. Если где-то нужно применить энергичность, то она делается вручную вставкой в конвеер операции типа .ToArray(), .ToList(), ToDictionary(...) или ещё какой-нибудь трансформации, которую можно придумать совершенно отдельно от вашего конкретного конвеера. S>4. нереально повторно использовать код, записать похожие алгоритмы.
Всё ровно наоборот. Если ваш код переписать на нормальный язык, то останется только существенная для понимания часть. А вся логика итерирования будет спрятана под капот.
Впрочем, для эксперимента можете переписать ваш же пример на "традиционный" Паскаль, безо всех этих новомодностей с генериками, .map, .filter и прочим.
Станет ли он дружелюбнее к рефакторингу и/или записи "похожих алгоритмов"? S>5. перегружает компилятор.
Это я оставлю на совести авторов компилятора. Тот же шарп или тайпскрипт компилируют код в функциональном стиле со скоростью мысли — то есть ничуть не медленнее Delphi. S>>На более-менее любом современном языке это будет весьма простой генератор/итератор, за которым .filter(...).map(...).reduce(...). S>>На Delphi остаётся только пердолиться с "процедурными типами" и/или Visitor Pattern. S>>Возможно, на современном Delphi ситуация как-то поменялась; в том, который был актуален во времена расцвета его популярности, всё это суровая правда.
Вижу, что на современном Delphi стало ещё хуже.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, pagid_, Вы писали:
p> R>Так Delphi и моложе плюсов, почти на двадцать...
p> На 10. Или на пять, если за начало принять ТурбоПаскаль с ООП и TurboVision
Точно. Чего-то с модулем вычислений случилось Ну ладно. Заместить шаблоны в паскале можно было включаемыми файлами {$include template.pas} (пример на fpc)
Здравствуйте, Serginio1, Вы писали:
S>Здравствуйте, Khimik, Вы писали:
S>Я бывший дельфист перешел и перешел на C#. С Учетом продвижения Native AOT то это полная замена.
И скоро AOT будет доступен для WinForms/WPF ?? Мы ж о замене дельфи говорим, то есть не про всякие серверы, а про формошлепство
S>>Я бывший дельфист перешел и перешел на C#. С Учетом продвижения Native AOT то это полная замена. J>И скоро AOT будет доступен для WinForms/WPF ?? Мы ж о замене дельфи говорим, то есть не про всякие серверы, а про формошлепство
Ну аналог WPF это MAUI. У него есть поддержка AOT. Проблем конечно с Native AOT много, но потихоньку движется.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, пффф, Вы писали:
П>Дельфи как система — очень хороша была. Тут спору нет. А вот язык, который был взят там за базу — Паскаль — полный отстой. Да, на нём можно тоже что-то делать. Ценой невероятных усилий, по сравнению с плюсами.
C++, наверно, и вправду сильно улучшился, вроде и для проблемы нестрогой типизации появилось решение, не говоря уж о стандарте, хотя казалось когда-то, что не за ним будущее. Но неужели pascal хуже, чем python и javascript, которые нынче почти всё остальное вытеснили, скажем, среди мобильных приложений нужно выискивать проекты, сделанные не на cordova. Pascal хоть статическую строгую типизацию вроде как имеет, а по части синтаксиса вообще извращения нынче в моде, даже в swift наворотили такого, что теперь, видимо, полноценного компилятора не будет.
Здравствуйте, Ilya81, Вы писали:
П>>Дельфи как система — очень хороша была. Тут спору нет. А вот язык, который был взят там за базу — Паскаль — полный отстой. Да, на нём можно тоже что-то делать. Ценой невероятных усилий, по сравнению с плюсами.
I>C++, наверно, и вправду сильно улучшился, вроде и для проблемы нестрогой типизации появилось решение, не говоря уж о стандарте, хотя казалось когда-то, что не за ним будущее. Но неужели pascal хуже, чем python и javascript, которые нынче почти всё остальное вытеснили, скажем, среди мобильных приложений нужно выискивать проекты, сделанные не на cordova. Pascal хоть статическую строгую типизацию вроде как имеет, а по части синтаксиса вообще извращения нынче в моде, даже в swift наворотили такого, что теперь, видимо, полноценного компилятора не будет.
Паскаль многословен. Может, для обучения это и хорошо, но в реальной работе это мешает. А когда я на нем работал, и возможности языка были ниже плинтуса. Сейчас, говорят, какие-то дженерики завезли. Но поезд давно ушел.
И никто не говорит, что python или javascript хороши. Именно поэтому в питон добавили аннотации типов, а для жиэс вообще отдельный тайпскрипт сделали
Здравствуйте, пффф, Вы писали:
П>И никто не говорит, что python или javascript хороши. Именно поэтому в питон добавили аннотации типов, а для жиэс вообще отдельный тайпскрипт сделали
Да уж, typescript — хоть какое-то спасение при взаимодействии с модулями, которые на javascript сделаны. А уж если это web-сраница, то такими будут почти все. Вот уж где самому нужно всё реализоввать — это если захотелось применить webassembly — он, видимо, не приживётся уже никогда.
Здравствуйте, Sinclair, Вы писали:
S>На более-менее любом современном языке это будет весьма простой генератор/итератор, за которым .filter(...).map(...).reduce(...).
Это называется "библиотечная поддержка".
За этими filter/map/reduce кто-то попердолился и скрываются кучи кода.
А уж написать это в строку или в столбик значения не имеет.
Здравствуйте, Sinclair, Вы писали:
S>Просто Go не предназначен для алгоритмов. Не предназначен — и всё.
Это почему же? Для каких-таких "алгоритмов" не предназначен? Я вот вижу у него богатую библиотечную поддержку. Всю жизнь думал, что языки программирования — они все "для алгоритмов".
Здравствуйте, akasoft, Вы писали:
S>>На более-менее любом современном языке это будет весьма простой генератор/итератор, за которым .filter(...).map(...).reduce(...). A>Это называется "библиотечная поддержка". A>За этими filter/map/reduce кто-то попердолился и скрываются кучи кода.
Там ещё скрывается проверка и вывод типов, лямбды и прочие монады.
A>А уж написать это в строку или в столбик значения не имеет.
Теоретически, совершенно верно. А как дело доходит до практики, то ВНЕЗАПНО:
1. Не поддается отладке отладчиком.
2. сложно профилировать. сложно найти "бутылочное горлышко" производительности.
3. сложно рефакторить, сложно определяется на каждом этапе какая там структура данных на выходе.
4. нереально повторно использовать код, записать похожие алгоритмы.
5. перегружает компилятор.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай