Можно ли реализовать связанные списки объектов разных типов?
Модератор: Модераторы
Можно ли реализовать связанные списки объектов разных типов?
Я посмотрел в модуль fgl, но дженериках совсем не разбираюсь. На первый взгляд построить динамический связанный список, содержащий объекты разных типов, не получится. Так ли это?
Есть ли у нас аналог foreach еще?
И вообще, где можно подробно почитать о планах развития free pascal? А то тут разрекламировали pascalABC, но он только под винду фактически.
Мне нравится паскаль, я с ним с детства знаком, мне приятен синтаксис и возможность быстро понять код и разобраться, но когда читаешь про более новые языки, смотришь примеры на питоне, зависть берет (взять хоть пресловутое множественное присваивание a,b=b,a или методы, встроенные в массивы и списки - sort, first, last и т.д.)
Есть ли у нас аналог foreach еще?
И вообще, где можно подробно почитать о планах развития free pascal? А то тут разрекламировали pascalABC, но он только под винду фактически.
Мне нравится паскаль, я с ним с детства знаком, мне приятен синтаксис и возможность быстро понять код и разобраться, но когда читаешь про более новые языки, смотришь примеры на питоне, зависть берет (взять хоть пресловутое множественное присваивание a,b=b,a или методы, встроенные в массивы и списки - sort, first, last и т.д.)
не так.Так ли это?
в смысле?Есть ли у нас аналог 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
- Лекс Айрин
- долгожитель
- Сообщения: 5723
- Зарегистрирован: 19.02.2013 16:54:51
- Откуда: Волгоград
- Контактная информация:
Если я правильно понял задачу, то для этого хватит классического паскаля.
Да и через дженерики не сложно... но тут без справки не напишу, но разница не такая большая.
Код: Выделить всё
Type
Start: ^Item;
Item = record
pred, Next, Data:pointer;
end;
Да и через дженерики не сложно... но тут без справки не напишу, но разница не такая большая.
pupsik писал(а):Есть ли у нас аналог foreach еще?
в смысле?
foreach - это из PHP позволяет перебрать массив.
Код: Выделить всё
<?php
$someArray[ 'Федя' ] = 'Пупкин';
$someArray[ 'Пупкин' ] = 'федя';
foreach ($someArray as $key => $value) {
//Соответственно здесь
//в $key - вернёт при первой итерации Федя, при второй Пупкин
//в $value - вернёт при первой итерации Пупкин, при второй Федя
}
?>
В Паскале такого нет (насколько я знаю). Разве что кто-то написал свой класс.
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)
- alexs
- долгожитель
- Сообщения: 4066
- Зарегистрирован: 15.05.2005 23:17:07
- Откуда: г.Ставрополь
- Контактная информация:
vitaly_l писал(а):В Паскале такого нет (насколько я знаю).
Это называется итератор. И как минимум в 3.0 он уже есть. А может и раньше появился. По простым типам - он сразу есть, для коллекций или ещё чего - надо самому объявить:
Код: Выделить всё
type
TA = array [1..10] of string;
var
A:TA;
...
for B in A do
bla_bla_bla(B)Мне нравится - достаточно удобно. Сокрашает код на 1 строку присваивания. Но иногда и по старому - через индексы работаешь - когда нужно знать индекс эелемента.
Вот такая идея (ну, здесь не связный, но сам принцип организации гетерогенного контейнера):
Простой Variant может быть лучше, конечно.
Добавлено спустя 11 минут 12 секунд:
Код: Выделить всё
{$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.Добавлено спустя 11 минут 12 секунд:
Это сравнение множеств со всем сопутствующим (в т. ч. 0..255).pupsik писал(а):if [a, b] = [z, g] then
- alexs
- долгожитель
- Сообщения: 4066
- Зарегистрирован: 15.05.2005 23:17:07
- Откуда: г.Ставрополь
- Контактная информация:
runewalsh писал(а):Вот такая идея (ну, здесь не связный, но сам принцип организации гетерогенного контейнера):
А в этом случае может лучше обычное наследование сделать от базового класса? В наследниках уточнять уже тип хранимых данных.
Аналог - TField и его производные.
alexs писал(а):for B in A do
Похоже но не foreach. (удобная, я про неё не знал,
Чтобы организовать в Паскале foreach, можно сделать так:
Код: Выделить всё
type
TForeach = record
key : string;
value : string;
end;
А дальше делать массив из TForeach и перебирать его, любым способом. В итоге получите: key и value как в PHP.
vitaly_l
Сделай над собой усилие, не пости везде подряд, только там где более менее понимаешь))
Сделай над собой усилие, не пости везде подряд, только там где более менее понимаешь))
zub писал(а):Сделай над собой усилие, не пости везде подряд, только там где более менее понимаешь
Вы уже научились находить пересечение линии с координатами мышки или всё ещё наивно полагаете что компьютер это математический осциллятор? Мой код был на порядок быстрее Вашего - это Вас так сильно расстроило? А вот Ваше замечание (которое есть комплекс) - действитеьно в этом топике не в тему. Хорошего всем настроения
Нифига не быстрее, в GC-языках их специально везде используют, чтобы не плодить работу GC, и даже в FPC... э-ээ... лень специально замерять, но вот у меня была функция выбора из взвешенных вариантов, вида
и в случаях, когда веса запрятаны в объектах и массив weights нужно формировать руками, она работала СИЛЬНО быстрее (2~4x, не помню), ну, не с итератором, но с чем-то его напоминающим в главном — неформировании всего массива в памяти:
Код: Выделить всё
function Choose(const weights: array of double): integer;Код: Выделить всё
type
GetWeightFunc = function(index: integer; param: pointer): double;
function Choose(count: integer; getWeight: GetWeightFunc; param: pointer): integer;vitaly_l блажен кто верит))
zub писал(а):vitaly_l блажен кто верит))
Сделай над собой усилие, не пости везде подряд! Пости только там где можешь спостить хоть что-то кроме флуда. Заметь-те я хоть какой-то код привёл по теме, а Вы вообще ничего, кроме флуда в этом топике не напечатали.
runewalsh писал(а):лень специально замерять
Не знаю, возможно. Всё зависит от конечной задачи. Если ему нужны только стринговые ключи и их перебор, то зачем тогда дженерики, если всё можно сделать через record ?
.
vitaly_l
"я хоть какой-то код привёл")))
"я хоть какой-то код привёл")))
