Процедурные типы данных

Вопросы программирования и использования среды Lazarus.

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

Ответить
resident
энтузиаст
Сообщения: 605
Зарегистрирован: 13.03.2013 16:58:51

Процедурные типы данных

Сообщение resident »

Подскажите, в Лазарусе есть процедурные типы данных? У меня не получилось их использовать.
Пробую сделать как в первом параграфе в статье http://www.rsdn.ru/article/delphi/Handlers.xml
Копирую в Делфи - все работает:

Код: Выделить всё

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm2 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

type
  TCalcFunction = function(const A, B : integer) : integer;

implementation
{$R *.dfm}

function Add(const A, B : integer) : integer;
begin Result := A + B; end;
function Sub(const A, B : integer) : integer;
begin Result := A - B; end;
function Mul(const A, B : integer) : integer;
begin Result := A * B; end;

procedure Example;
  var CalcFunction : TCalcFunction;
  begin CalcFunction := Add;
    ShowMessageFmt('CalcFunction(2, 3) = %d', [CalcFunction (2, 3)]);
    CalcFunction := Sub;
    ShowMessageFmt('CalcFunction(2, 3) = %d', [CalcFunction (2, 3)]);
    CalcFunction := Mul;
    ShowMessageFmt('CalcFunction(2, 3) = %d', [CalcFunction (2, 3)]);
  end;

procedure TForm2.FormCreate(Sender: TObject);
  begin
    Example;
  end;

end.



Копирую тоже самое в Лазарус - не хочет

Код: Выделить всё

unit FormMain;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs;

type
  TForm1 = class(TForm)
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

type
  TCalcFunction = function(const A, B : integer) : integer;

implementation
{$R *.lfm}

function Add(const A, B : integer) : integer;
begin Result := A + B; end;
function Sub(const A, B : integer) : integer;
begin Result := A - B; end;
function Mul(const A, B : integer) : integer;
begin Result := A * B; end;

procedure Example;
  var CalcFunction : TCalcFunction;
  begin CalcFunction := Add;
    ShowMessageFmt('CalcFunction(2, 3) = %d', [CalcFunction (2, 3)]);
    CalcFunction := Sub;
    ShowMessageFmt('CalcFunction(2, 3) = %d', [CalcFunction (2, 3)]);
    CalcFunction := Mul;
    ShowMessageFmt('CalcFunction(2, 3) = %d', [CalcFunction (2, 3)]);
  end;

end.
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

resident писал(а):Подскажите, в Лазарусе есть процедурные типы данных?

Lazarus - это не язык программирования (сообщаю Вам на всякий случай ;) ).
resident писал(а):в Делфи - все работает
...
в Лазарус - не хочет
...
CalcFunction := Add;

Потому что Дельфи - среда разработки для малохольных, которые не хотят разбираться в синтаксисе языка. :D
Смотрите, что Вы делаете: результат выполнения функции Add() Вы присваиваете переменной CalcFunction, вдобавок позабыв дать функции нужные ей параметры. :D Вы это делаете по "дельфийской" привычке, которая вытеснила способность думать и понимать, что Вы делаете. Забудьте про такой полоумный синтаксис, который порождает миллион ошибок и непониманий. Вам нужно переменной присвоить не результат функции, а её адрес:

Код: Выделить всё

CalcFunction := @Add;
SeZuka
постоялец
Сообщения: 209
Зарегистрирован: 05.09.2012 14:58:05

Сообщение SeZuka »

Это различия между ObjectPascal и Delphi.
Вам либо надо переключить на диалект дельфей:

Код: Выделить всё

unit FormMain;
{$mode delphi}{$H+}
...
  CalcFunction := Add;
  CalcFunction := Sub;
  CalcFunction := Mul;
Либо писать писать как принято в ObjectPascal:

Код: Выделить всё

  CalcFunction := @Add;
  CalcFunction := @Sub;
  CalcFunction := @Mul;
resident
энтузиаст
Сообщения: 605
Зарегистрирован: 13.03.2013 16:58:51

Сообщение resident »

Vadim писал(а):Lazarus - это не язык программирования

В разделе форума про язык небольшая посещаемость, так что я зарядил тему сюда в надежде, что никто не заметит :)

Vadim писал(а):Потому что Дельфи - среда разработки для малохольных, которые не хотят разбираться в синтаксисе языка. :D

Дельфи - среда быстрой разработки, и этим все сказано :D

Vadim писал(а):Забудьте про такой полоумный синтаксис, который порождает миллион ошибок и непониманий. Вам нужно переменной присвоить не результат функции, а её адрес:

Код: Выделить всё

CalcFunction := @Add;

Вот спасибо. Логично. А то я думаю, что что-то не так, читаемости нет в Делфийском примере.
Теперь посмотришь и все понятно.

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

Добавлено спустя 2 минуты 42 секунды:
SeZuka писал(а):Вам либо надо переключить на диалект дельфей:

Зачем же. Или были случаи возвращения людей с Лазаруса на Делфи?

SeZuka писал(а):Либо писать писать как принято в ObjectPascal:

Код: Выделить всё

  CalcFunction := @Add;

Ок, спасиб :)
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

resident писал(а):Кстати, исправил в Делфи, там тоже заработало с адресом.

Так и должно быть, потому что это изначально было правильно. Просто в Дельфи синтаксис некоторых вещей упростили в ущерб понятности. Например, у динамически выделенной переменной, типа record, для взятия оттуда значения, символ "^" можно не писать, что многих тоже вводит в тягостное недоумение, т.к. они свято верят, что это статическая переменная и память под неё выделять не нужно. :)
resident
энтузиаст
Сообщения: 605
Зарегистрирован: 13.03.2013 16:58:51

Сообщение resident »

Vadim писал(а):
resident писал(а): т.к. они свято верят, что это статическая переменная и память под неё выделять не нужно. :)

Не в курсе этих подробностей :)

Я все играюсь с тем примером. Опять не получается, может подскажите, как тут быть?
Вот если мне понадобиться передать функцию в качестве параметра какой-нибудь процедуре (например добавлю procedure Calculate), то как мне это сделать?
Почитал про указатели. Понятного мало. Сама процедура компилируется, но как туда передать функции не понимаю. На выражения аля Calculate(2,3,@Add); компилятор ругается.

Код: Выделить всё

unit FormMain;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs;

type

  { TForm1 }

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

type
  TCalcFunction = function(const A, B : integer) : integer;
  PCalcFunction = ^TCalcFunction;

implementation
{$R *.lfm}

function Add(const A, B : integer) : integer;
begin Result := A + B; end;
function Sub(const A, B : integer) : integer;
begin Result := A - B; end;
function Mul(const A, B : integer) : integer;
begin Result := A * B; end;

procedure Calculate(A, B: integer; P: PCalcFunction);
  var CalcFunction : TCalcFunction;
  begin
    CalcFunction := P^;
    ShowMessageFmt('CalcFunction(2, 3) = %d', [CalcFunction (A, B)]);
  end;

procedure Example;
  begin
    Calculate(2,3,@Add);
    Calculate(2,3,@Sub);
    Calculate(2,3,@Mul);
  end;

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
  begin
    Example;
  end;



end.

Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

Код: Выделить всё

procedure Calculate(A, B: integer; P: TCalcFunction);

Теперь на место P можно подставлять адрес функции.
P - это уже указатель, т.к. ничего другого, кроме адреса функции, процедурный тип не предусматривает, поэтому никакие другие указатели из него делать не надо. Далее, уже внутри процедуры, это самое P можно использовать как функцию, без других промежуточных переменных.
alexey38
долгожитель
Сообщения: 1627
Зарегистрирован: 27.04.2011 19:42:31

Сообщение alexey38 »

resident писал(а):Или были случаи возвращения людей с Лазаруса на Делфи?

Безусловно, что многие используют Лазарь и ФПС как вспомогательное средство, особенно когда нужно под линухом написать некоторую прогу. Писать большие виндовые проекты под дельфей было всегда удобнее, как на уровне самой ИДЕ, так и на уровне многих элементов, типа уникода, ОЛЕ и т.п.
stanilar
постоялец
Сообщения: 289
Зарегистрирован: 09.03.2010 18:09:02

Сообщение stanilar »

resident писал(а):Вот спасибо. Логично. А то я думаю, что что-то не так, читаемости нет в Делфийском примере.
Теперь посмотришь и все понятно.


При работе а собакой отсутствует проверка на типы со всеми вытекающими. Лучше пользоваться {$mode delphi}, оставьте себе возможность избавиться от дурацких ошибок на этапе компиляции :) .
Аватара пользователя
VirtUX
энтузиаст
Сообщения: 880
Зарегистрирован: 05.02.2008 09:52:19
Откуда: Крым, Алушта

Сообщение VirtUX »

stanilar писал(а):При работе а собакой отсутствует проверка на типы со всеми вытекающими. Лучше пользоваться {$mode delphi}, оставьте себе возможность избавиться от дурацких ошибок на этапе компиляции :) .

Зачем Вы человека учите невежеству? Пусть "дурацкие ошибки" (хотя я бы сказал: "ошибки, приводящие к пониманию") заставляют становиться мудрее ;) С замылинным взглядом на жизнь мы все уже и так живем :( Так пусть хоть в творчестве люди будут чисты и трезвы :)
P.S. ИМХО...
stanilar
постоялец
Сообщения: 289
Зарегистрирован: 09.03.2010 18:09:02

Сообщение stanilar »

VirtUX писал(а):ИМХО...


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

ИМНО: Давайте пойдем еще дальше: пусть человек отбросит паскаль и учит сразу правильный си, а еще лучше прочищающий мозги с++.
resident
энтузиаст
Сообщения: 605
Зарегистрирован: 13.03.2013 16:58:51

Сообщение resident »

Vadim писал(а):Теперь на место P можно подставлять адрес функции.
P - это уже указатель, т.к. ничего другого, кроме адреса функции, процедурный тип не предусматривает, поэтому никакие другие указатели из него делать не надо.

Не получилось подставить. Ну да мне не особо нужно, только любопытно было сработает или нет. Спасиб.

Добавлено спустя 2 минуты 1 секунду:
alexey38 писал(а):Безусловно, что многие используют Лазарь и ФПС как вспомогательное средство, особенно когда нужно под линухом написать некоторую прогу


Ах вот в чем тут дело. Я то думал, что он нужен, чтобы лицензия была. Вроде все бесплатно.

Добавлено спустя 6 минут 19 секунд:
stanilar писал(а):При работе а собакой отсутствует проверка на типы со всеми вытекающими. Лучше пользоваться {$mode delphi}, оставьте себе возможность избавиться от дурацких ошибок на этапе компиляции


Я почитал в инете, так в Делфи действительно не все так просто упростили. Даже не знаю, что лучше.
Особенно посмешил пост:
http://www.gamedev.ru/flame/forum/?id=154986&page=2#m26
"И ваша пгограмма выдаст ой вей вместо того, чтобы габотать. " :lol:
Alex2013
долгожитель
Сообщения: 3211
Зарегистрирован: 03.04.2013 11:59:44

Сообщение Alex2013 »

То есть так ?

Код: Выделить всё

procedure Calculate(A, B: integer; P: PCalcFunction);
  begin 
    ShowMessageFmt( '  CalcFunction (2, 3) = %d', [P (A, B)]);
  end;


Столкнулся при присваивании обработчика событий что то типа T.OnTimer:=@ MyTmer ;
В дельфях работает без собаки
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

Alex2013 писал(а):В дельфях работает без собаки

Delphi, в этом случае, не пример для подражания. Из-за Delphi Вы забыли (или изначально не знали) правильный синтаксис.
Ответить