Можно ли реализовать связанные списки объектов разных типов?

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

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

Можно ли реализовать связанные списки объектов разных типов?

Сообщение java73 » 22.03.2017 22:03:24

Я посмотрел в модуль fgl, но дженериках совсем не разбираюсь. На первый взгляд построить динамический связанный список, содержащий объекты разных типов, не получится. Так ли это?
Есть ли у нас аналог foreach еще?
И вообще, где можно подробно почитать о планах развития free pascal? А то тут разрекламировали pascalABC, но он только под винду фактически.
Мне нравится паскаль, я с ним с детства знаком, мне приятен синтаксис и возможность быстро понять код и разобраться, но когда читаешь про более новые языки, смотришь примеры на питоне, зависть берет (взять хоть пресловутое множественное присваивание a,b=b,a или методы, встроенные в массивы и списки - sort, first, last и т.д.)
java73
постоялец
 
Сообщения: 176
Зарегистрирован: 21.11.2013 09:08:10

Re: Можно ли реализовать связанные списки объектов разных ти

Сообщение pupsik » 22.03.2017 22:24:32

Так ли это?
не так.
Есть ли у нас аналог foreach еще?
в смысле?
..о планах развития free pascal?
кто его знает. В принципе, на вики можно просмотреть что приблизительно будет. Вроде как.
А то тут разрекламировали pascalABC
тут? Не видел :)
взять хоть пресловутое множественное присваивание a,b=b,a или методы
это нечто такого:
Код: Выделить всё
var
  a, b, z, g : Integer;

begin
  a := 1;
  b := 3;
  z := 3;
  g := 2;
  if [a, b] = [z, g] then
    WriteLn('t')
  else
    WriteLn('f');
  ReadLn;   
?
....sort, first, last
в смысле?
pupsik
энтузиаст
 
Сообщения: 882
Зарегистрирован: 20.08.2014 16:20:13

Re: Можно ли реализовать связанные списки объектов разных ти

Сообщение Лекс Айрин » 22.03.2017 22:29:52

Если я правильно понял задачу, то для этого хватит классического паскаля.

Код: Выделить всё
Type
Start: ^Item;
Item = record
pred, Next, Data:pointer;
end;

Да и через дженерики не сложно... но тут без справки не напишу, но разница не такая большая.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 3239
Зарегистрирован: 19.02.2013 16:54:51

Re: Можно ли реализовать связанные списки объектов разных ти

Сообщение vitaly_l » 22.03.2017 22:44:03

pupsik писал(а):Есть ли у нас аналог foreach еще?
в смысле?

foreach - это из PHP позволяет перебрать массив.
Код: Выделить всё
<?php
$someArray[ 'Федя' ]    = 'Пупкин';
$someArray[ 'Пупкин' ] = 'федя';

foreach ($someArray as $key => $value) {
//Соответственно здесь
//в $key - вернёт при первой итерации Федя, при второй Пупкин
//в $value - вернёт при первой итерации Пупкин, при второй Федя
}
?>

В Паскале такого нет (насколько я знаю). Разве что кто-то написал свой класс.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 2304
Зарегистрирован: 31.01.2012 16:41:41

Re: Можно ли реализовать связанные списки объектов разных ти

Сообщение java73 » 22.03.2017 22:54:55

pupsik писал(а):не так.

Хочу пример. Я бы вот тогда свою тестовую программулину усовершенствовал. Есть базовый класс TPetal, о него куча потомков. Член списка может быть объектом любого класса, а следующий - например, типа string, а за ним integer, а за ним опять TPetal. Так можно?

pupsik писал(а):в смысле?

вроде нашел это http://wiki.freepascal.org/for-in_loop/ru

pupsik писал(а):это нечто такого:

пример на питоне a,b=b,a - одной строкой обмен данными в переменных, другие примеры a,b,c=1,2,"string"; a=b=c=1;

pupsik писал(а):в смысле?

типа:
a: array of integer;
b: array of TMyclass;
....
a.Sort;
c:=b.First;
d:=b.Last.....

Сижу вот еще курю SDL руководство (deCAL)
java73
постоялец
 
Сообщения: 176
Зарегистрирован: 21.11.2013 09:08:10

Re: Можно ли реализовать связанные списки объектов разных ти

Сообщение alexs » 22.03.2017 23:00:47

vitaly_l писал(а):В Паскале такого нет (насколько я знаю).

Это называется итератор. И как минимум в 3.0 он уже есть. А может и раньше появился. По простым типам - он сразу есть, для коллекций или ещё чего - надо самому объявить:
Код: Выделить всё
type
  TA = array [1..10] of string;
var
  A:TA;
...
  for B in A do
      bla_bla_bla(B)

Мне нравится - достаточно удобно. Сокрашает код на 1 строку присваивания. Но иногда и по старому - через индексы работаешь - когда нужно знать индекс эелемента.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 3423
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Можно ли реализовать связанные списки объектов разных ти

Сообщение runewalsh » 22.03.2017 23:02:29

Вот такая идея (ну, здесь не связный, но сам принцип организации гетерогенного контейнера):
Код: Выделить всё
{$mode objfpc} {$h+}
uses
   typinfo, SysUtils;

type
   StorageBase = class
      function StoredTypeInfo: PTypeInfo; virtual; abstract;
   end;

   generic Storage<T> = class(StorageBase)
      value: T;
      function StoredTypeInfo: PTypeInfo; override;
   end;

   HeterogenousList = class
      store: array of StorageBase;
      destructor Destroy; override;
   end;

   generic Pusher<T> = class
      class procedure Push(list: HeterogenousList; const value: T);
   end;

   generic Getter<T> = class
      class function Get(list: HeterogenousList; index: SizeInt): T;
   end;

   function Storage.StoredTypeInfo: PTypeInfo;
   begin
      result := TypeInfo(T);
   end;

   destructor HeterogenousList.Destroy;
   var
      i: SizeInt;
   begin
      for i := 0 to High(store) do
         store[i].Free;
      inherited;
   end;

   class procedure Pusher.Push(list: HeterogenousList; const value: T);
   type
      SpecificStorage = specialize Storage<T>;
   var
      st: SpecificStorage;
   begin
      st := SpecificStorage.Create;
      st.value := value;
      SetLength(list.store, length(list.store) + 1);
      list.store[High(list.store)] := st;
   end;

   class function Getter.Get(list: HeterogenousList; index: SizeInt): T;
   type
      SpecificStorage = specialize Storage<T>;
   begin
      if (index < 0) or (index >= length(list.store)) then
         raise ERangeError.CreateFmt('index = %d, min = %d, max = %d', [index, Low(list.store), High(list.store)]);

      if not (list.store[index] is SpecificStorage) then
         raise Exception.CreateFmt('%dth element type mismatch: stored %s, asked %s', [index, list.store[index].StoredTypeInfo^.Name, PTypeInfo(TypeInfo(T))^.Name]);
      result := SpecificStorage(list.store[index]).value;
   end;

type
   PushInteger = specialize Pusher<integer>;
   PushString = specialize Pusher<string>;
   GetInteger = specialize Getter<integer>;
   GetString = specialize Getter<string>;

var
   list: HeterogenousList;

begin
   list := HeterogenousList.Create;
   try
      PushInteger.Push(list, 5);
      PushString.Push(list, 'first string');
      PushInteger.Push(list, 25);
      PushString.Push(list, 'second string');

      writeln('integer at #0 = ', GetInteger.Get(list, 0));
      try
         writeln(' string at #0 = ', GetString.Get(list, 0));
      except
         on E: Exception do writeln(E.Message);
      end;
      writeln(' string at #1 = ', GetString.Get(list, 1));
      writeln('integer at #2 = ', GetInteger.Get(list, 2));
      writeln(' string at #3 = ', GetString.Get(list, 3));
   finally
      list.Free;
   end;

   readln;
end.
Простой Variant может быть лучше, конечно.

Добавлено спустя 11 минут 12 секунд:
pupsik писал(а):if [a, b] = [z, g] then
Это сравнение множеств со всем сопутствующим (в т. ч. 0..255).
Аватара пользователя
runewalsh
постоялец
 
Сообщения: 308
Зарегистрирован: 27.04.2010 00:15:25

Re: Можно ли реализовать связанные списки объектов разных ти

Сообщение alexs » 23.03.2017 09:44:21

runewalsh писал(а):Вот такая идея (ну, здесь не связный, но сам принцип организации гетерогенного контейнера):

А в этом случае может лучше обычное наследование сделать от базового класса? В наследниках уточнять уже тип хранимых данных.
Аналог - TField и его производные.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 3423
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Можно ли реализовать связанные списки объектов разных ти

Сообщение vitaly_l » 23.03.2017 10:02:36

alexs писал(а):for B in A do

Похоже но не foreach. (удобная, я про неё не знал, :roll: спасибо)

Чтобы организовать в Паскале foreach, можно сделать так:
Код: Выделить всё
type
TForeach = record
key : string;
value : string;
end;

А дальше делать массив из TForeach и перебирать его, любым способом. В итоге получите: key и value как в PHP.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 2304
Зарегистрирован: 31.01.2012 16:41:41

Re: Можно ли реализовать связанные списки объектов разных ти

Сообщение zub » 23.03.2017 10:19:08

vitaly_l
Сделай над собой усилие, не пости везде подряд, только там где более менее понимаешь))
zub
долгожитель
 
Сообщения: 1918
Зарегистрирован: 14.11.2005 23:51:26

Re: Можно ли реализовать связанные списки объектов разных ти

Сообщение vitaly_l » 23.03.2017 10:43:22

zub писал(а):Сделай над собой усилие, не пости везде подряд, только там где более менее понимаешь

Вы уже научились находить пересечение линии с координатами мышки или всё ещё наивно полагаете что компьютер это математический осциллятор? Мой код был на порядок быстрее Вашего - это Вас так сильно расстроило? А вот Ваше замечание (которое есть комплекс) - действитеьно в этом топике не в тему. Хорошего всем настроения :wink: .
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 2304
Зарегистрирован: 31.01.2012 16:41:41

Re: Можно ли реализовать связанные списки объектов разных ти

Сообщение runewalsh » 23.03.2017 10:52:46

Нифига не быстрее, в GC-языках их специально везде используют, чтобы не плодить работу GC, и даже в FPC... э-ээ... лень специально замерять, но вот у меня была функция выбора из взвешенных вариантов, вида
Код: Выделить всё
function Choose(const weights: array of double): integer;
и в случаях, когда веса запрятаны в объектах и массив weights нужно формировать руками, она работала СИЛЬНО быстрее (2~4x, не помню), ну, не с итератором, но с чем-то его напоминающим в главном — неформировании всего массива в памяти:
Код: Выделить всё
type
   GetWeightFunc = function(index: integer; param: pointer): double;

function Choose(count: integer; getWeight: GetWeightFunc; param: pointer): integer;
Аватара пользователя
runewalsh
постоялец
 
Сообщения: 308
Зарегистрирован: 27.04.2010 00:15:25

Re: Можно ли реализовать связанные списки объектов разных ти

Сообщение zub » 23.03.2017 11:09:30

vitaly_l блажен кто верит))
zub
долгожитель
 
Сообщения: 1918
Зарегистрирован: 14.11.2005 23:51:26

Re: Можно ли реализовать связанные списки объектов разных ти

Сообщение vitaly_l » 23.03.2017 11:25:47

zub писал(а):vitaly_l блажен кто верит))

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

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

.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 2304
Зарегистрирован: 31.01.2012 16:41:41

Re: Можно ли реализовать связанные списки объектов разных ти

Сообщение zub » 23.03.2017 11:29:40

vitaly_l
"я хоть какой-то код привёл")))
zub
долгожитель
 
Сообщения: 1918
Зарегистрирован: 14.11.2005 23:51:26

След.

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

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

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

Рейтинг@Mail.ru