Вышла новая версия компилятора FreePascal

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Re: Вышла новая версия компилятора FreePascal

Сообщение alexs » 25.12.2015 15:53:57

kazalex писал(а):Тебе показали закат солнца вручную, то есть ручной захват контекста. Что там непонятного и причём тут делегирование?

Вообще то в ООП это называется делегирование.
Это аналог калбэка из обычного мира с сохранением контекста объекта.
Это не единственный способ. Но даже он нагляднее - чем то что предлагают оппоненты
kazalex писал(а):т.к. в случае изменившегося контекста ты запаришься свои колбеки рефакторить.

С точностью наоборот. Ловить это размазню по коду???
Люди специально процедурное программирование придумали, чтобы текст легче читался. А тут предлагается простыни писать. И вызов идёт куска из середины.

Как мне кажется, тут уже и говорить бесполезно. Надо просто запрещать.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4064
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Вышла новая версия компилятора FreePascal

Сообщение Дож » 25.12.2015 15:58:20

Лекс Айрин писал(а):Дож, колбек, как я понимаю, это обычное присваивание адресной переменной (указателю) адреса функции для ее дальнейшего использования...

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

В моём примере были параметры A1, A2, A3. От этих трёх параметров зависит что печатает колбек. Мыслимо себе представить, что в программе создано два колбека с одним и тем же кодом, но работающие по-разному в зависимости от разных значений аргументов.

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

Лекс Айрин писал(а):почему бы не делать так, как это делают все нормальные программисты? Обычным взятием адреса?

Код: Выделить всё
//Процедура обработки оконных сообщений
Function WindowProc(wnd:HWND; Msg : Dword; Wparam:Wparam; Lparam: Lparam): Lresult; stdcall; //
// заменил integer на DWord и все заработало)))
begin
  case msg of
    wm_destroy, wm_close : postquitmessage(0); //Событие закрытия или удаления окна 
  else
    Result := DefWindowProc(wnd, msg, wparam, lparam);
  end;
end;

//Процедура регистрации класса основного окна
Procedure RegWinClass;
Var
  wc: WNDCLASS;
  err: dword;

Begin
  ...
  wc.lpfnWndProc:=@WindowProc;
  ....



Здесь нет передачи клиентских параметров. (В моём примере были A1, A2, A3.) Разумеется, в случае, когда параметры не нужны, не требуется городить сложные коллбеки.

Для полноты сравнительного анализа Ваш пример следует дополнить реализацией своей структуры, хранящей параметры коллбэка A1, A2, A3, её инициализацей в правильном месте, вызовами SetWindowLongPtr(hWnd, GWLP_USERDATA, ...) и GetWindowLongPtr(hWnd, GWLP_USERDATA) с опасным приведением Pointer'а в указатель на свою структуру, и деинициализацией этой структуры в правильном месте.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Вышла новая версия компилятора FreePascal

Сообщение Лекс Айрин » 25.12.2015 16:09:09

Дож писал(а):В данном контексте речь идёт о таких колбеках, которые параметризованы некоторыми аргументами, влияющими на их работу.

Это уже придирка. Есть переменные процедуры и переменные функции... здесь уже компилятор следит за допустимостью присваиваний. в одном из примеров вы их как раз и использовали. Я просто написал пример реального кода. А расширить все это элементарно.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Вышла новая версия компилятора FreePascal

Сообщение Дож » 25.12.2015 16:10:56

Это уже придирка. Есть переменные процедуры и переменные функции... здесь уже компилятор следит за допустимостью присваиваний. в одном из примеров вы их как раз и использовали. Я просто написал пример реального кода. А расширить все это элементарно.

Это не придирка, а вся суть, без которой дискурса вокруг замыканий и ссылок на локальные функции не было бы.

Добавлено спустя 14 минут 34 секунды:
alexs писал(а):
kazalex писал(а):Тебе показали закат солнца вручную, то есть ручной захват контекста. Что там непонятного и причём тут делегирование?

Вообще то в ООП это называется делегирование.


То, что Вы называете тут «делегированием» я реализовал в качестве второго варианта viewtopic.php?f=1&t=10762&start=135#p92131

Хотя нет, подождите, мне нужно ещё немного шлифануть…
Код: Выделить всё
procedure SomeFunc;
var
  A1: LongInt;
  A2: AnsiString;
  A3: BalBlaBla;
  // Что это за класс? Надо лезть в описание класса
  MyCallbackWrapper: TMyCallbackWrapper;
begin
  // Что делает конструктор?
  // Где будет вызван деструктор?
  // Однозначно надо сходить в то места, где класс реализован
  try
    RunAlgo(TMyCallbackWrapper.Create(A1, A2, A3)); // Передаём коллбэк
  except
    Writeln('Мы обосрались где-то в глубинах абстрактных конструкций :''(');
  end;
end;

...

// Лезем в описание класса, видим:
type
TMyCallbackWrapper = class(TInterfacedObject, IDelegate) // <-- Бог мой, что такое IDelegate? Ещё что-от лезть смотреть
private
  FA1: LongInt;
  FA2: AnsiString;
  FA3: BalBlaBla;
public
  constructor Create(A1: LongInt; A2: AnsiString; A3: Blablabla);
  procedure Callback;
end;
// Супер — прочли 10 механически написанных строк

...

type
// О, я нашёл IDelegate! Что же он из себя представляет?
IDelegate = interface
  procedure Callback;
end;
// Ну, охренеть теперь

...

// Смотрим дальше — конструктор
constructor TMyCallbackWrapper.Create(A1: LongInt; A2: AnsiString; A3: Blablabla);
begin
  FA1 := A1;
  FA2 := A2;
  FA3 := A3;
  // Сюрпрайз! Прочтено ещё 6 механически написанных строк
end;

...

procedure TMyCallbackWrapper.Callback;
begin
  Writeln(FA1, ' ', FA2, ' ', FA3); // <-- Всё ради одной вот этой строки
end;


Русский термин «делегирование» не полностью соответствует английскому слову «delegate», правильнее говорить «делегат».
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Вышла новая версия компилятора FreePascal

Сообщение kazalex » 25.12.2015 16:32:18

alexs писал(а):Вообще то в ООП это называется делегирование.

Вообще-то делегирование в ООП это немного о другом и неразрывно связано с агрегированием.

alexs писал(а):Это не единственный способ. Но даже он нагляднее - чем то что предлагают оппоненты

Конечно не единственный, можно ещё локальный контекст притащить в объект, как мне уже однажды предлагали :roll:

alexs писал(а):Люди специально процедурное программирование придумали, чтобы текст легче читался. А тут предлагается простыни писать

Процедурное программирование решает совсем другие задачи, а простыни прекрасно существуют и без анонимных методов. При использовании анонимных методов читаемость кода, как раз таки, улучшается, а вместе с тем ещё и уменьшается количество обезьяньей работы, требующейся для обслуживания идеологии.
Последний раз редактировалось kazalex 25.12.2015 16:35:07, всего редактировалось 1 раз.
kazalex
постоялец
 
Сообщения: 296
Зарегистрирован: 01.06.2012 14:54:10

Re: Вышла новая версия компилятора FreePascal

Сообщение alexs » 25.12.2015 16:33:03

Дож писал(а):RunAlgo(TMyCallbackWrapper.Create(A1, A2, A3)); // Передаём коллбэк

В этой форме - это не колбэк, а манипуляции с объектом.
Я вообще не понял - зачем для такой простой вещи, как обратный вызов - надо городить объект? Нужны вам переменные - так сделайте их глобальными, разместите на куче. Но объект зачем?

И ещё - за такое обращение с динамической памятью руки отрывать надо.
Есть правило - где ты память попросил, там её и освободи.

Не переносите плохой стиль написания ПО с других (менее удачных языков) в паскаль.
Всё что вы пишите - очень сильно попахивает явой и JS. Не учитесь плохому. Учитесь хорошему.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4064
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Вышла новая версия компилятора FreePascal

Сообщение Лекс Айрин » 25.12.2015 16:34:56

Дож, то есть, не получается по нормальному, значит надо городить все подряд, лишь бы получилось подогнать результат?

По крайней мере, этот вывод напрашивается... если это будет делаться ТАК, ...

Код: Выделить всё
Callback := procedrue; // Записываем в переменную процедуру
    begin
      Writeln(A1, ' ', A2, ' ', A3); // Сразу видим что эта процедура делает
    end;
  RunAlgo(Callback);

то лучше я изучу бейсик... или лисп. Где вы видите параметрирование колбека? лично я не нашел... пойду поищу...
судя по всему, Вы не только опечатались в слове procedure, но и опустили параметры в присваивании самого колбека.... иначе непонятно откуда взялись переменные внутри... плюс, присваивание переменным в функции, которая должна жить долго, локальных значений, которые "исчезнут" как только процедура завершится. То есть, гарантировано падение программы.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Вышла новая версия компилятора FreePascal

Сообщение kazalex » 25.12.2015 16:39:10

alexs писал(а):Я вообще не понял - зачем для такой простой вещи, как обратный вызов - надо городить объект?

Я сразу в топике сказал, что всё невосприятие новых возможностей это от непонимания. Повторяю ещё раз - объект требуется для захвата контекста!

alexs писал(а):Нужны вам переменные - так сделайте их глобальными, разместите на куче.

Глобальные переменные??? И эти люди [s]запрещают мне ковыряться в носу[/s] рассуждают о правильном пути :roll:
kazalex
постоялец
 
Сообщения: 296
Зарегистрирован: 01.06.2012 14:54:10

Re: Вышла новая версия компилятора FreePascal

Сообщение alexs » 25.12.2015 17:17:12

kazalex писал(а):Глобальные переменные???

А у вас получится написать программу без глобальных переменных?
И в чём криминал? Просто надо быть аккуратным при использовании потоков.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4064
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Вышла новая версия компилятора FreePascal

Сообщение kazalex » 25.12.2015 17:36:11

alexs писал(а):А у вас получится написать программу без глобальных переменных?

Мы ведь говорим не о глобальных переменных вообще, а в контексте обсуждаемого вопроса. Кстати говоря, с появлением вложенных типов и деклараций, можно и вовсе отказаться от глобальных переменных в коде.

alexs писал(а):И в чём криминал?

Как минимум в нарушении инкапсуляции. Потом, если колбеков не один и не два и все они могут быть параметризированы различными значениями это будет не просто криминал...
kazalex
постоялец
 
Сообщения: 296
Зарегистрирован: 01.06.2012 14:54:10

Re: Вышла новая версия компилятора FreePascal

Сообщение Лекс Айрин » 25.12.2015 17:45:12

kazalex писал(а):можно и вовсе отказаться от глобальных переменных в коде.

бред. Как минимум, одна глобальная переменная в программе всегда будет -- сам объект.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Вышла новая версия компилятора FreePascal

Сообщение kazalex » 25.12.2015 17:50:12

Лекс Айрин писал(а):бред. Как минимум, одна глобальная переменная в программе всегда будет -- сам объект

Кто понимает смысл вложенных деклараций, для того не бред.
kazalex
постоялец
 
Сообщения: 296
Зарегистрирован: 01.06.2012 14:54:10

Re: Вышла новая версия компилятора FreePascal

Сообщение Дож » 25.12.2015 17:53:14

alexs писал(а):
Дож писал(а):RunAlgo(TMyCallbackWrapper.Create(A1, A2, A3)); // Передаём коллбэк

В этой форме - это не колбэк, а манипуляции с объектом.

Это многое меняет, конечно.

Я вообще не понял - зачем для такой простой вещи, как обратный вызов - надо городить объект?

Затем, что сейчас в паскале нет хороших и правильных альтернатив этому.

Нужны вам переменные - так сделайте их глобальными, разместите на куче. Но объект зачем?

Глобальные переменные — это не решение на все случаи.
viewtopic.php?f=1&t=10762&start=45#p91706
viewtopic.php?f=1&t=10762&start=45#p91707

И ещё - за такое обращение с динамической памятью руки отрывать надо.
Есть правило - где ты память попросил, там её и освободи.

Как Вы мне предлагаете освободить память интерфейсного объекта? Давайте вместе сделаем код лучше!

Не переносите плохой стиль написания ПО с других (менее удачных языков) в паскаль.
Всё что вы пишите - очень сильно попахивает явой и JS. Не учитесь плохому. Учитесь хорошему.

Хорошее — в студию! Буду учиться.

Лекс Айрин писал(а):Дож, то есть, не получается по нормальному, значит надо городить все подряд, лишь бы получилось подогнать результат?

Если задача поставлена, то нужно решать задачу. Как правило, возникает несколько вариантов решений. У каждого варианта решения нужно оценить плюсы и минусы, определить приоритеты, всё взвесить и, в конце концов, совершить выбор. Бывает так, что разные люди делают разный выбор, а однозначно правильного выбора нет.

Для анализа читабельности разных подходов к написанию кода нужно 1) поставить задачу 2) написать код разными способами по каждому из подходов 3) прочесть 4) оценить что читалось легче.

Вы взяли задачу «написание простейшего коллбека в WinApi», реализовали одним (единственным возможным в реальности, так как WinApi фиксировано) способом, и теперь утверждаете, что это что-то доказывает по параметру «читабельности» и «правильности» во всех остальных ситуациях. Нет, не доказывает, даже близко нет.

Аргументацию «по-нормальному», «нормальные программисты делают так», «это извращение», «в Java есть лямбды, поэтому не надо нам такого», «в C# вот нормальные прогеры юзают делегаты» и прочие оставьте для разговоров с пацанчиками на районе.

Лекс Айрин писал(а):Где вы видите параметрирование колбека? лично я не нашел... пойду поищу...

Как действуют анонимные фукнции или замыкание — определяется семантикой компилятора. Искать следует в документации на используемый компилятор. В нашем воображаемом компиляторе паскаля с поддержкой замыканий компилятор видит локальные переменные A1, A2, A3 («контекст»), генерирует для хранения их копий структуру, копирует в эту структуру значения этих переменных («захват контекста») в момент порождения нового замыкания, и заботится об освобождении этой структуры.

То, что компиляторе сгенерировал весь этот код за нас, — это благо, освободившее нас от т.н. «обезьяней работы» (см. второй мой пример).

Лекс Айрин писал(а):плюс, присваивание переменным в функции, которая должна жить долго, локальных значений, которые "исчезнут" как только процедура завершится. То есть, гарантировано падение программы.

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

Лекс Айрин писал(а):
kazalex писал(а):можно и вовсе отказаться от глобальных переменных в коде.

бред. Как минимум, одна глобальная переменная в программе всегда будет -- сам объект.

Без комментариев:
Код: Выделить всё
procedure RunApp;
var
  App: TApp;
begin
  App.Init;
  App.Run;
  App.Done;
end;

begin
  RunApp;
end.


kazalex писал(а):
alexs писал(а):Нужны вам переменные - так сделайте их глобальными, разместите на куче.

Глобальные переменные??? И эти люди [s]запрещают мне ковыряться в носу[/s] рассуждают о правильном пути :roll:

+1 :cry:
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Вышла новая версия компилятора FreePascal

Сообщение Лекс Айрин » 25.12.2015 18:09:01

Дож писал(а):Без комментариев:


Угу... просто тупо поменять program на procedure, еще не значит избавиться от глобальных переменных.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Вышла новая версия компилятора FreePascal

Сообщение Дож » 25.12.2015 18:24:08

Лекс Айрин писал(а):
Дож писал(а):Без комментариев:

Угу... просто тупо поменять program на procedure, еще не значит избавиться от глобальных переменных.

Конечно же, не значит! Неужто кто-то тут утверждает, что значит? :)

Вот ещё код:
Код: Выделить всё
type
TApp = class
  constructor Create;
  destructor Destroy; override;
  procedure Run;
end;

constructor TApp.Create;
begin
  ...
  Run;
end;

...

begin
  TApp.Create.Free;
end.


Кстати, просто переделать program на constructor, ещё не значит избавиться от глобальных переменных.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Пред.След.

Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 8

Рейтинг@Mail.ru
cron