Generics

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

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

Generics

Сообщение VaalKIA » 10.11.2016 23:29:06

Вопрос по дженерикам, вот код итератора:
Код: Выделить всё
unit Unit1;

{$mode objfpc}{$H+}
{$MODESWITCH ADVANCEDRECORDS}
interface

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

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

var
  Form1: TForm1;


  type
  LstGrandTyp = ^PLstGrandTyp;

  PLstGrandTyp = packed record
    early, Next: LstGrandTyp;
  end;


  LstTyp01 = ^PLstTyp01;
  PLstTyp01 = packed record
    early, Next: LstTyp01;
    Value: byte;
  end;

  LstTyp02 = ^PLstTyp02;
  PLstTyp02 = packed record
    early, Next: LstTyp02;
    Value: string[255];
  end;

implementation

type
  generic LstEnumerator<LstTyp> = record//LstTyp можно обозвать и просто T, главное, что бы уникально
  private
    lst, lst_save: LstTyp;
  public
    constructor Create(const Value: LstTyp);
    function GetEnumerator: LstEnumerator;
    function MoveNext: boolean;
    property Current: LstTyp read lst;
  end;

constructor LstEnumerator.Create(const Value: LstTyp);
begin
  lst := Value;
  lst_save := nil;
end;

function LstEnumerator.GetEnumerator: LstEnumerator;
begin
  Result := Self;
end;

function LstEnumerator.MoveNext: boolean;
begin
  if lst <> nil then
  begin
  //...какой-то код
  LstGrandTyp(lst) := LstGrandTyp(lst)^.next;//Здесь обрезка типа, причём если тип задан не в interface, а в implementation, то не компилируется. Но это внутренняя операция, на внешний тип она не влияет.
  Result := True;
  end else Result := False;
end;


1. Почему нельзя использовать вот так:
Код: Выделить всё
var
  i01, lst01: LstTyp01;
  i02, lst02: LstTyp02;

begin
  for i01 in LstEnumerator<LstTyp01>.Create(lst01) do
  begin
    i01^.Value := 10;
  end;
  for i02 in LstEnumerator<LstTyp02>.Create(lst02) do
  begin
    i02^.Value := 'ten';
  end;

end.


2. Почему вот на это выдаёт ошибку:
Код: Выделить всё
var
  i01, lst01: LstTyp01;
  i02, lst02: LstTyp02;

begin
  for i01 in LstEnumerator.Create(lst01) do
  begin
    i01^.Value := 10;
  end;
end.

Компиляция проекта, цель: C:\Users\Admin\AppData\Local\Temp\project1.exe: Код завершения 1, ошибок: 1, предупреждений: 1
unit1.pas(83,40) Warning: Variable "lst01" does not seem to be initialized
unit1.pas(83,7) Error: Internal error 200304241

3. Почему при использовании таким образом:
Код: Выделить всё
var
  i01, lst01: LstTyp01;
  i02, lst02: LstTyp02;
  en01: specialize LstEnumerator<LstTyp01>;
  en02: specialize LstEnumerator<LstTyp02>;
begin

  for i01 in en01.Create(lst01) do
  begin
    i01^.Value := 10;
  end;

  for i02 in en02.Create(lst02) do
  begin
    i02^.Value := 'ten';
  end;

end.
в функции function LstEnumerator.MoveNext: boolean;
не дают обратиься к:
Код: Выделить всё
lst^.next
Ведь в обоих специализациях это свойство есть и у компилятора есть вся информация о типе.
VaalKIA
незнакомец
 
Сообщения: 9
Зарегистрирован: 10.11.2016 22:57:58

Re: Generics

Сообщение zub » 12.11.2016 00:03:14

С генериками лучше тренироваться на транковом компиляторе. Первый кусок на транке скомпилится.
Оформите все куски в законченом виде на основе program, а не unit, чтоб можно было легко проверить
zub
долгожитель
 
Сообщения: 2411
Зарегистрирован: 14.11.2005 23:51:26

Re: Generics

Сообщение VaalKIA » 12.11.2016 00:22:54

Не знаю что такое транк, у меня 3.0 64bit. Все куски оформленны в законченном виде: это продолжение юнита, который оканчивается на end. Скомпилировалось окончание под номером 1 или первый кусок кода из текста?

чтоб можно было легко проверить

Это троллинг что ли? Создайте проект в лазарусе, Ctrl+a и два раза сделайте паст: первый кусок кода и окончание на выбор.
VaalKIA
незнакомец
 
Сообщения: 9
Зарегистрирован: 10.11.2016 22:57:58

Re: Generics

Сообщение zub » 12.11.2016 00:33:45

>>Скомпилировалось окончание под номером 1 или первый кусок кода из текста?
Не знаю что такое окончание, у меня первый кусок компилитруется. Остальное не компилируется: это продолжение непойми чего, хоть и заканчивается на end.

Хочешь помощи - оформи так чтоб и помогающие и ты не парились. т.е. копипастил и компилировал.

Транк - последняя актуальная версия из официальной системы контроля версий проекта http://svn.freepascal.org/svn/fpc/trunk/ генерики последнее время активно пилятся, а 3.0 - это старый хлам)) надеюсь к новому году будет 3.0.2

Это не тролинг, вполне серъезно, клеить твои обрезки в пятницу вечером...

Добавлено спустя 4 минуты 36 секунд:
>>Это троллинг что ли? Создайте проект в лазарусе,
Возми и создай, только за основу возми не "приложение" а "простая программа"

Добавлено спустя 8 минут 23 секунды:
то что у тебя под цифрой 1 скомпилируется если ты почитаешь про отличия синтаксиса генериков в режимах делфи и фпц (забыл speсialize)
2 - ошибка потому что это не специализированый генерик
3 - в транке компилируется
zub
долгожитель
 
Сообщения: 2411
Зарегистрирован: 14.11.2005 23:51:26

Re: Generics

Сообщение VaalKIA » 12.11.2016 01:49:12

zub писал(а):>>Скомпилировалось окончание под номером 1 или первый кусок кода из текста?
Не знаю что такое окончание, у меня первый кусок компилитруется.


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

zub писал(а):Остальное не компилируется: это продолжение непойми чего, хоть и заканчивается на end.

Окончание текста модуля, которое оформляется вот так: "begin end.", обращаю ваше внимание на точку и отсылаю к мануалам:
Структура модуля

Модуль имеет следующую структуру:
UNIT <имя модуля>
INTERFACE
<раздел интерфейсный>
IMPLEMENTATION
<раздел реализации>
BEGIN
<раздел инициализации>
END.



zub писал(а):Хочешь помощи - оформи так чтоб и помогающие и ты не парились. т.е. копипастил и компилировал.


Вам приведенно полностью из схемы выше:
unit
interface
implementation

и отдельно несколько варинатов: <раздел инициализации>
А если вы потрудитесь почитать, комментарии к этим вариантам, то вы поймёте что среди них рабочий только один, а все остальные являются сутью вопроса, до которого вы ещё не опустились, но уже успели меня протроллить на полностью очевидные вещи.

zub писал(а):Транк - последняя актуальная версия из официальной системы контроля версий проекта

При это на сайте написано:
"Актуальные версии
FPC 3.0.0 release"
Грубо говоря, вы советуете: поставьте бажный пакет, что бы ловить глюки в проектах, зато получится поэксперементировать с новой фичей и помечатать, что когда доведут до ума это можно будет использовать. Релиз, для вас это ненужный хлам, ок.

zub писал(а):Это не тролинг, вполне серъезно, клеить твои обрезки в пятницу вечером...

Пффф, с оффтопиком го-ту в другие ветки, нечего здесь мусор разводить.


zub писал(а):>>Это троллинг что ли? Создайте проект в лазарусе,
Возми и создай, только за основу возми не "приложение" а "простая программа"

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


zub писал(а):то что у тебя под цифрой 1 скомпилируется если ты почитаешь про отличия синтаксиса генериков в режимах делфи и фпц (забыл speсialize)

specialize не даёт вставлять в коде, а про отличия я, действительно, не в курсе.

zub писал(а):2 - ошибка потому что это не специализированый генерик

А описание ошибки не наводит на интересные мысли? Не я просто так вставил, типа текст для привлечения внимания, Карл!

zub писал(а):3 - в транке компилируется

А у меня где-то написано, что не компилируется? Это как раз рабочий вариант и там прямо об этом написано, а так же написано про процедуру, которую найти не сложно и там тело из одной строки.
В кратце, не дают использовать разъименовывание , с полями прекрасно работает.
Вы вообще врубаетесь, что такое дженерики и чем отличается вот это
Код: Выделить всё
LstGrandTyp(lst) := LstGrandTyp(lst)^.next;

от вот этого:
Код: Выделить всё
lst:=lst^.next

можно даже просто написать:
Код: Выделить всё
with lst^ do begin end;
VaalKIA
незнакомец
 
Сообщения: 9
Зарегистрирован: 10.11.2016 22:57:58

Re: Generics

Сообщение zub » 12.11.2016 02:30:09

Ты приводишь какуюто пакость и хочешь чтоб другие в ней разбирались
Код: Выделить всё
  LstTyp01 = ^PLstTyp01;
  PLstTyp01 = packed record
    early, Next: LstTyp01;
    Value: byte;
  end;

P принято ставить у типов указателей, а не наоборот. Это конечно к делу не относится, просто чтоб ты понимал какие чувства вызывают такие портянки)))

>>Грубо говоря, вы советуете: поставьте бажный пакет, что бы ловить глюки в проектах, зато получится поэксперементировать с новой фичей
Я советую поставить последнюю версию компилятора. благо через месяц она (почти она) станет следующим релизом.
FPC - 3.0.2 (Scheduled For Release 2015-11-26) [ View Issues ]
FPC - 3.2.0 (Scheduled For Release 2016-10-16) [ View Issues ]
FPC - 4.0.0 (Scheduled For Release 2016-12-06) [ View Issues ]

Ихними устами бы мед пить, но я всетаки надеюсь на релиз к новому году, слишком много актуальных для меня багов было исправлено со времен 3.0.0

Применительно к генерикам какраз ты ловишь "глюки" в проектах с "бажным" релизом = пользуешь фичу недоделаную в текущем релизе.
Хочешь новых возможностей - будь добр и версию поновей хотеть. Internal error это баг компилятора, таких ошибок недолжно быть.

>>Вам приведенно полностью из схемы выше:
Я знаю только такую схему - дается минимальный пример с ошибкой, чтобы сэкономить время человека который его будет смотреть (а заодно пока такой пример делается, вопросы обычно сами собой снимаются). Это правила хорошего тона. разводить портянки и склейки ненадо - только если ошибку неполучается вычленить и она воспроизводится только в большом фрагменте.

>>Это как раз рабочий вариант и там прямо об этом написано, а так же написано про процедуру, которую найти не сложно и там тело из одной строки.
Это портянка на сотню строк, найти несложно. только нафиг? у меня на одном экране не поместилось - я не увидел.
>>Вы вообще врубаетесь, что такое дженерики и чем отличается вот это
Я та врубаюсь, а ты? чтоб уйти от разименования в данном случае придется сделать
PLstTyp01 PLstTyp02 обжектами или классами наследниками PLstGrandTyp. (фу какое уродство обманывать и добавлять P к неуказателям), а генерик LstEnumerator ограничить в специализации типом PLstGrandTyp и его наследниками. тогда в теле генерика появится доступ к полям PLstGrandTyp. Врубаешся? нет?

зы. спасибо ненадо

Добавлено спустя 6 минут 35 секунд:
зы2. посмотрел, ограничить тип специализации можно только
- "record"
- "class"
- a class identifer
- an interface identifier

такчто PLstTyp01 PLstTyp02 PLstGrandTyp придется сделать классами.
ну или генерик по нормальному написать, чего и советую))

Добавлено спустя 23 минуты 16 секунд:
зы3.
Future work:
................................
- "enum": the type must be a enumerationn type
- "ordinal": the type must be one of the ordinal types (Integer,
LongWord, etc.)
- "array": the type must be an array type
- "string": the type must be one of the string types
- "object": the type must be an "object" type (analogous to "record")
- object identifier: the type must derive from the given object type
- support for Objective Pascal types like objcclass, objcprotcol, etc.
- "operator X": the type must support the operator "X" (available for
all other constraints)

Возможность огранияения обжектами всетаки когдато нам светит... дожить бы))

Добавлено спустя 1 минуту 17 секунд:
цитаты из древнего анонса generics constraints http://lists.freepascal.org/fpc-announc ... 00586.html
zub
долгожитель
 
Сообщения: 2411
Зарегистрирован: 14.11.2005 23:51:26

Re: Generics

Сообщение VaalKIA » 12.11.2016 03:08:54

>>Вам приведенно полностью из схемы выше:
Я знаю только такую схему - дается минимальный пример с ошибкой, чтобы сэкономить время человека который его будет смотреть

Именно так и сделано - вместо трёх почти одинаковых портянок на сотню строк и планомерной работы по вычлинению отличий, три цикла с телом в одну строку, которые опытным людям даже в компилятор запихивать не надо.
ПРИ ЭТОМ ЧЁТКО НАПИСАНО, ЧТО В ПЕРВОМ КОДЕ РЕАЛИЗОВАН ИТЕРАТОР, А В ДАЛЕЕ ПРИМЕРЫ ЕГО ИСПОЛЬЗОВАНИЯ, ПО КОТОРЫМ ЕСТЬ ВОПРОСЫ.

>>Это как раз рабочий вариант и там прямо об этом написано, а так же написано про процедуру, которую найти не сложно и там тело из одной строки.
Это портянка на сотню строк? у меня на одном экране не поместилось - я не увидел.


цитирую ещё раз, например, второй пример:
Код: Выделить всё
var
1 i01, lst01: LstTyp01;
2 i02, lst02: LstTyp02;

begin
3  for i01 in LstEnumerator.Create(lst01) do
  begin
4   i01^.Value := 10;
  end;
end.

Итого - 4 значащих строки, честно, не пиши в эту тему - не надо, по человечески тебя прошу.


>>Вы вообще врубаетесь, что такое дженерики и чем отличается вот это
Я та врубаюсь, а ты? чтоб уйти от разименования в данном случае придется сделать
PLstTyp01 PLstTyp02 обжектами или классами наследниками PLstGrandTyp. (фу какое уродство обманывать и добавлять P к неуказателям), а генерик LstEnumerator ограничить в специализации типом PLstGrandTyp и его наследниками. тогда в теле генерика появится доступ к полям PLstGrandTyp. Врубаешся? нет?


Даже не стал читать эту чушь, которая тут написана. Человек не потрудился прочитать ни строчки из оригинального вопроса.
Иллюстрирую:
Код: Выделить всё
type
  TestTyp = record
    yes, no: byte;
  end;

  generic GenTyp<T> = record
  public
    procedure proc(var Value: T);
  end;

procedure GenTyp.proc(var Value: T);
begin
  Value.yes := Value.yes;
end;


var
  Value: TestTyp;
  test: specialize GenTyp<TestTyp>;
begin
  test.proc(Value);
end.

Какие классы, какие объекты, какие ограничения?!!! Доступ к полю yes есть? Есть. Он будет если сделать три разных типа у которых есть поля yes.

То о чём шла речь:
Код: Выделить всё
type
  TestTyp = ^PTestTyp;
  PTestTyp = record
    yes, no: byte;
  end;

  generic GenTyp<T> = record
  public
    procedure proc(var Value: T);
  end;

procedure GenTyp.proc(var Value: T);
begin
  Value^.yes := Value^.yes;
end;


var
  Value: TestTyp;
  test: specialize GenTyp<TestTyp>;
begin
  test.proc(Value);
end.

Доступа нет.
Только это второстепенный вопрос и поэтому показан он был на основном коде.
VaalKIA
незнакомец
 
Сообщения: 9
Зарегистрирован: 10.11.2016 22:57:58

Re: Generics

Сообщение zub » 12.11.2016 03:41:45

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

>>И вообще, ваши половые проблеммы - смешны, поскольку тут не используется ни одного контрола.
Вреш и не краснеешь. TForm? FileUtil, Forms, Controls, Graphics, Dialogs?
Давай, поржи. С чего ты взял что лазарь есть у всех подряд? у меня на данный момент на этом компе его нет. И это какраз твои проблемы))

Интересно, будут еще желающие тебе помочь))
zub
долгожитель
 
Сообщения: 2411
Зарегистрирован: 14.11.2005 23:51:26

Re: Generics

Сообщение VaalKIA » 12.11.2016 03:50:16

zub писал(а):Ну а с чего ты взял что разименование может быть применено к обобщенному типу? Я по наивности подумал что ограничения помогут если конкретезировать что тип это указатель а не обобщенный тип, ошибся, о чем сразу написал.

С того, что тип описан полностью, и дженерики как раз и состоят в том, что компилятор знает что это за тип, как только объявили специализацию, какие у него поля и по чём, соотвественно по этому типу генерирует вариант кода. То есть, специализированный код именно под этот тип он генерирует, но доступ к телу вам - хренушки.
VaalKIA
незнакомец
 
Сообщения: 9
Зарегистрирован: 10.11.2016 22:57:58

Re: Generics

Сообщение zub » 12.11.2016 03:55:16

Ты ошибся.
>>как только объявили специализацию
Прикинь, некоторые объявляют тело генерика в одном модуле, а специализируют в другом. и он компилируется (ну хоть не компилируется, но синтаксис проверяется) еще до специализации... И добрый компилятор вежливо говорит что нефиг разименовывать то что вполне может оказаться неразименовываемым
zub
долгожитель
 
Сообщения: 2411
Зарегистрирован: 14.11.2005 23:51:26

Re: Generics

Сообщение VaalKIA » 12.11.2016 04:03:16

до специализации

Дженерик это тип. Пока нет специализации, не нужна реализация, код можно вообще игнорировать, как только появилась специализация, сразу известно какая именно реализация нужна. О какой проверке синтаксиса может идти речь, если даже не известно можно ли его присваивать складывать или проводить другие элементарные операции?

Добавлено спустя 3 минуты 1 секунду:
zub писал(а):Интересно, будут еще желающие тебе помочь))


Помочь? Я сам себе помог, обрезав тип, и это полностью решило мои текущие проблемы.

Моя цель была, поговрить с умными людьми, что бы прояснить на будущее неочевидные нюансы, потому что понимание почему что-то работает или не работает именно так - важно.
Ни одного реального ответа в этой ветке не было, только чат-бот - zub, который соскочил со всех тем, но заставил удовлетворить все свои комплексы.
VaalKIA
незнакомец
 
Сообщения: 9
Зарегистрирован: 10.11.2016 22:57:58

Re: Generics

Сообщение zub » 12.11.2016 04:11:37

С такими вопросами на багтрекер. Делфи емнип и . не пропускает, не то что ^ такчто есть шансы что и нам запретят))

Дженерик это тип. Пока нет специализации...

Теоретезировать будешь когда станешь разрабом fpc, или хотябы продавишь свои хотелки на бактрекере. А пока кушай что дают.
zub
долгожитель
 
Сообщения: 2411
Зарегистрирован: 14.11.2005 23:51:26

Re: Generics

Сообщение VaalKIA » 12.11.2016 04:16:49

Теоретезировать будешь когда станешь разрабом fpc, или хотябы продавишь свои хотелки на бактрекере. А пока кушай что дают.

Ответ соотвествует интеллекту. У нас же есть ещё и компилятор.
Иллюстрирую код, какая проверка синтаксиса тут проводится, если кроме этого кода ничего больше нет. Он проверил, что поля какие-то есть и что присваивание можно делать? Не смешите меня, код, касающийся типа дженерика просто проигнорировали и компиляция прошла успешно.

Код: Выделить всё
type
  generic GenTyp<T> = record
  public
    procedure proc(var Value: T);
  end;

procedure GenTyp.proc(var Value: T);
begin
  Value.yes := Value.yes;
end;

А вот попробуте теперь сделать специализацию, где нет поля yes и как-то резко всё перестанет компилироваться.
VaalKIA
незнакомец
 
Сообщения: 9
Зарегистрирован: 10.11.2016 22:57:58

Re: Generics

Сообщение zub » 12.11.2016 04:20:12

>>Моя цель была, поговрить с умными людьми
В пятницу вечером? Я бухой в это время обычно))

>>обрезав тип, и это полностью решило мои текущие проблемы.
А мог бы подсмотреть как нормальные люди такие вопросы решают (вернее у них их не возникает при правильном подходе), например в fpc-stl

Добавлено спустя 7 минут 44 секунды:
Прикинь, а вот тут вот проверка синтаксиса провелась
Код: Выделить всё
program Project1;
{$mode objfpc}{$H+}
{$MODESWITCH ADVANCEDRECORDS}
type
  generic GenTyp<T> = record
  public
    procedure proc(var Value: T);
  end;

procedure GenTyp.proc(var Value: T);
begin
  Value.yes := Value.yes;
  Ne_IGNORINUI_Menya;
end;

Может потому что . и ^ совсем разные вещи? разименование оно и в африке разименование, а . может оказаться хелпером определенным только в модуле специализации? а, умник?

Добавлено спустя 5 минут 25 секунд:
>>только чат-бот - zub, который соскочил со всех тем, но заставил удовлетворить все свои комплексы.
Попросил поправить твой код... в приличном обществе типа багтрекера fpc с тобой бы разговаривать нестали изза ненужной зависимости от лазаря, а в неприличном заплевали бы за неP=^P; чем ты и мои хмельные мозги по началу в ступор ввел
zub
долгожитель
 
Сообщения: 2411
Зарегистрирован: 14.11.2005 23:51:26

Re: Generics

Сообщение VaalKIA » 12.11.2016 04:39:47

zub писал(а):>>обрезав тип, и это полностью решило мои текущие проблемы.
А мог бы подсмотреть как нормальные люди такие вопросы решают (вернее у них их не возникает при правильном подходе), например в fpc-stl

Люди использующие чистые макросы, ненормальны по определению, думаю, им и Паскаль без надобности, потому что языки высокого уровня именно для того и создавались, что бы не было этой фигни и хоть что-то можно было контролировать.

zub писал(а):Прикинь, а вот тут вот проверка синтаксиса провелась

Провелась проверка синтаксиса, не имеющая отношения к дженерику, поскольку тип дженерика только у value. И то что по этому типу только будет создана реальная процедура к делу не имеет отношения.

zub писал(а):Может потому что . и ^ совсем разные вещи? разименование оно и в африке разименование, а . может оказаться хелпером определенным только в модуле специализации? а, умник?

А может кто-то что-то попутал, и забыл, что знак "^" можно опускать, и есть ещё и вот такая директива компилятора: {$X+}, так что обращение через точку ещё не говорит, что там нет разъименования? Фундаментальность ваших знаний - поражает.
VaalKIA
незнакомец
 
Сообщения: 9
Зарегистрирован: 10.11.2016 22:57:58

След.

Вернуться в Lazarus

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

Сейчас этот форум просматривают: Google Adsense [Bot] и гости: 7

Рейтинг@Mail.ru