Здравствуйте, hattab, Вы писали:
H>Повторить полный аналог можно и в дельфях, с той лишь разницей, что код она не сгенерирует В этом чтоли вся прелесть?
Конечно. Итератор для графа можно писать неделями, поверь. А если с помощью компилятора то где то за минуты можно управиться.
H>-_*>
H>-_*> foreach(Item item in GetNextItem())
H>-_*> {
H>-_*> // бесконечный цикл создания объектов
H>-_*> // со "структурами" на это памяти не хватит
H>-_*> }
H>-_*>
H>-_*> Можно идти и дальше — обход любой сложной структуры вроде дерева, кольца, графа или генерация сложной последовательности делается довольно просто.
H>Хм, что же в таком случае заставляет разработчиков самостоятельно писать перечислители?
Очевидно ты привел пример кода версии 1.0 или 1.1. В 2.0 и выше код который ты показал ужмется минимум в 10 раз.
H>-_*> А вот в Дельфи с итераторами придется попотеть.
H>Реализация одного метода это попотеть?
Итератор это не метод.
Материал из Википедии — свободной энциклопедии, -_*
Здравствуйте, hattab, Вы писали:
H>Здравствуйте, gandjustas, Вы писали:
g>> g>> H>Повторить полный аналог можно и в дельфях, с той лишь разницей, что код она не сгенерирует В этом чтоли вся прелесть?
g>> g>> Ну покажи полный аналог для такого
например.
g>> H>Т.е. ты мне на полном серьезе предлагаешь тут реализовать собственный Rx? Шутник, однако.
g>> Нет, конкретный пример повтори с итератором, можно без асинхронности.
H>Если я правильно понял, это чтение из потока.
Неправильно понял.
При читении из потока указывается буфер, сколько байт прочитать и с какой позиции писать в буфер. Так как операция чтения может прочитать меньше, чем было указано, то для полного чтения буфера реализуется цикл, на каждой итерации которого двигается позиция для записи и уменьшается число байт, которое надо прочитать.
Так вот итераторы позволяют этот цикл сделать асинхронным, так как сам yield прерывает выполнение функции, а некоторый движок обеспечивает асинхронный запуск асинхронных операций.
Я вот спрашиваю как можно вот такое прерывание на delphi сделать.
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, hattab, Вы писали:
H>>Здравствуйте, gandjustas, Вы писали:
g>>> g>> H>Повторить полный аналог можно и в дельфях, с той лишь разницей, что код она не сгенерирует В этом чтоли вся прелесть?
g>>> g>> Ну покажи полный аналог для такого
например.
g>>> H>Т.е. ты мне на полном серьезе предлагаешь тут реализовать собственный Rx? Шутник, однако.
g>>> Нет, конкретный пример повтори с итератором, можно без асинхронности.
H>>Если я правильно понял, это чтение из потока.
G>Неправильно понял. G>При читении из потока указывается буфер, сколько байт прочитать и с какой позиции писать в буфер. Так как операция чтения может прочитать меньше, чем было указано, то для полного чтения буфера реализуется цикл, на каждой итерации которого двигается позиция для записи и уменьшается число байт, которое надо прочитать.
G>Так вот итераторы позволяют этот цикл сделать асинхронным, так как сам yield прерывает выполнение функции, а некоторый движок обеспечивает асинхронный запуск асинхронных операций.
G>Я вот спрашиваю как можно вот такое прерывание на delphi сделать.
Здравствуйте, gandjustas, Вы писали:
g> При читении из потока указывается буфер, сколько байт прочитать и с какой позиции писать в буфер. Так как операция чтения может прочитать меньше, чем было указано, то для полного чтения буфера реализуется цикл, на каждой итерации которого двигается позиция для записи и уменьшается число байт, которое надо прочитать.
g> Так вот итераторы позволяют этот цикл сделать асинхронным, так как сам yield прерывает выполнение функции, а некоторый движок обеспечивает асинхронный запуск асинхронных операций.
Ты же сам сказал, можно без асинхронщины
g> Я вот спрашиваю как можно вот такое прерывание на delphi сделать.
Тю. Да я бы вообще это без итератора сделал Для такой фигни еще итераторы задействовать...
-_*> H>Повторить полный аналог можно и в дельфях, с той лишь разницей, что код она не сгенерирует В этом чтоли вся прелесть?
-_*> Конечно. Итератор для графа можно писать неделями, поверь. А если с помощью компилятора то где то за минуты можно управиться.
Да, у меня есть такой (обход RTTI дерева). Писал не неделю, но часа два точно убил.
-_*> Итератор это не метод.
Ок. Это два метода. Причем основная работа делается только в одном из них. По сути получаем конечный автомат. Бывает простой, бывает сложный. Но не невозможный.
Здравствуйте, hattab, Вы писали:
H>Здравствуйте, gandjustas, Вы писали:
g>> При читении из потока указывается буфер, сколько байт прочитать и с какой позиции писать в буфер. Так как операция чтения может прочитать меньше, чем было указано, то для полного чтения буфера реализуется цикл, на каждой итерации которого двигается позиция для записи и уменьшается число байт, которое надо прочитать.
g>> Так вот итераторы позволяют этот цикл сделать асинхронным, так как сам yield прерывает выполнение функции, а некоторый движок обеспечивает асинхронный запуск асинхронных операций.
H>Ты же сам сказал, можно без асинхронщины
ну правильно, нужно прерывание выполнение кода с сохранением контекста.
g>> Я вот спрашиваю как можно вот такое прерывание на delphi сделать.
H>Тю. Да я бы вообще это без итератора сделал Для такой фигни еще итераторы задействовать... H>
H>Сам понимаешь, что завернуть такой код в итератор труда тоже не составит.
Не понимаю. Как после Inc прервать выполнение метода? (например для шедулинга операций чтения)?
Здравствуйте, hattab, Вы писали:
H>-_*> Итератор это не метод.
H>Ок. Это два метода. Причем основная работа делается только в одном из них. По сути получаем конечный автомат. Бывает простой, бывает сложный. Но не невозможный.
Да, получается именно автомат. Сначала нужно написать обход, а потом остаётся самое муторно — преобразовать код в автомат. Задача не сложная но ошибки здесь стоят очень дорого.
Материал из Википедии — свободной энциклопедии, -_*
Здравствуйте, gandjustas, Вы писали:
g> H>Ты же сам сказал, можно без асинхронщины
g> ну правильно, нужно прерывание выполнение кода с сохранением контекста.
g> g>> Я вот спрашиваю как можно вот такое прерывание на delphi сделать.
Дроблением
g> H>Тю. Да я бы вообще это без итератора сделал Для такой фигни еще итераторы задействовать... g> H>
g> H>Сам понимаешь, что завернуть такой код в итератор труда тоже не составит.
g> Не понимаю. Как после Inc прервать выполнение метода? (например для шедулинга операций чтения)?
Ну, тут итератор не нужен вообще
TReader = Record
Offset : Integer;
Buffer : TBytes;
Constructor Create(ABufferSize : Integer);
Function GetBuffer(AStream : TStream) : Boolean;
End;
Constructor TReader.Create(ABufferSize : Integer);
Begin
SetLength(Buffer, ABufferSize);
End;
Function TReader.GetBuffer(AStream : TStream) : Boolean;
Begin
Inc(Offset, AStream.Read(Buffer[Offset], Length(Buffer) - Offset));
Result := Offset = Length(Buffer);
End;
...
With TReader.Create(1024) Do
While Not GetBuffer(Stream) Do
Begin//sheduleEnd;
А можно инициализировать стримом при создании ридера. В общем, есть варианты
Здравствуйте, enji, Вы писали:
E>ну и что? После того, как я оформлю свой подход в либу, для пользователя он будет выглядеть не сильно страшнее твоего кода
На это уйдет время, не так ли ? На все случаи либ не напишешь.
E>-_*>Серия эвентов преобразуется в последовательность координат. Это + еще кое что есть распознавание мышиных жестов. В нативном подходе, с очередями, совпадениями, надо было писать килобайты ифов, свичей, обработчиков и трястись над различными флагами.
E>Распознавание мышиных жестов в дельфях из коробки. Килобайтов ифов там нет...
А как они жесты распознают ?
E>-_*>Расширение вроде RX написать на коленке ?
E>Ты не поверишь, но RX тоже кто-то написал
Это стандартная либа с широкими возможностями и благодаря ей не надо писать либы на все случае жизни, как "жестов в дельфях из коробки". Известная вобщем то проблема еще древнего Борланда — написать либы на все случаи жизни вместо хорошего фреймворка, через полгода-года обнаружить что случаев много больше, переписать все это с нуля и опять заточить на все случаи жизни вместо хорошего фреймворка и снова обнаружить что случаев много больше и тд.
Единственно, чего в дельфях и всех ex-борландовских продуктах вызывает уважение, так это непрекращающиеся попытки сделать мир лучше. Борланд под разными именами как птица феникс из пепла восстает — банкротится, выкупается, переформируется, выпускает продукт, снова банкротится.
Материал из Википедии — свободной энциклопедии, -_*
Здравствуйте, Eugeny__, Вы писали:
E__>Если в коде такое количество связей, и объекты друг на друга ссылаются, то проблема со скоростью GC уходит даже не на второй план, а сильно дальше, потому как самая главная проблема в днк писавшего такой код.
хотелось бы надеяться, что проблема хотя бы не в днк фреймворка
Здравствуйте, gandjustas, Вы писали:
G>Ну и сколько ребер будет в графе? Очевидно что не N^2 потому что все со всеми живые объекты связаны не будут, то есть примерно количество ребер в графе будет линейно зависеть от количества вершин. В итоге тот же O(N) получим
Ощущение, что ты не совсем понимаешь что значит "доказать".
1% объектов имеют число связей, пропорциональных N, 99% имеют 0 связей => общая оценка O(N^2)
E__>>Если в коде такое количество связей, и объекты друг на друга ссылаются, то проблема со скоростью GC уходит даже не на второй план, а сильно дальше, потому как самая главная проблема в днк писавшего такой код.
HA>хотелось бы надеяться, что проблема хотя бы не в днк фреймворка
Есть примеры фреймворка, который создает ссылки "все ко всем" между объектами?
Новости очень смешные. Зря вы не смотрите. Как будто за наркоманами подсматриваешь. Только тетка с погодой в завязке.
There is no such thing as a winnable war.
Здравствуйте, -_*, Вы писали:
E>>ну и что? После того, как я оформлю свой подход в либу, для пользователя он будет выглядеть не сильно страшнее твоего кода
-_*>На это уйдет время, не так ли ? На все случаи либ не напишешь.
Ну так на все случаи и не надо Надо только на конкретные случаи. Причем где-то надо именно либу, а где то хватит обычного "одноразового" кода, который решает задачу. Запись событий мышки — типичный пример такого кода, который очень прост и элементарно пишется каждый раз с учетом потребностей.
E>>Распознавание мышиных жестов в дельфях из коробки. Килобайтов ифов там нет...
-_*>А как они жесты распознают ?
А я откуда знаю? Я про это читал, но дельфи давно уже не использую. А что, наличие Rx — обязательное условие для распознавания жестов? Насколько я все это понимаю, достаточно записать посл движений и сравнить с образцом. Алгоритм сравнения — это уже интересный вопрос. В институте на нейронных сетях делал какое-то распознавание...
-_*>Это стандартная либа с широкими возможностями и благодаря ей не надо писать либы на все случае жизни, как "жестов в дельфях из коробки". Известная вобщем то проблема еще древнего Борланда — написать либы на все случаи жизни вместо хорошего фреймворка, через полгода-года обнаружить что случаев много больше, переписать все это с нуля и опять заточить на все случаи жизни вместо хорошего фреймворка и снова обнаружить что случаев много больше и тд.
Часто оказывается что случаев даже больше, чем покрывает фреймворк И приходится его допиливать или писать что-то сбоку.
Здравствуйте, hattab, Вы писали:
H>Здравствуйте, gandjustas, Вы писали:
g>> H>Ты же сам сказал, можно без асинхронщины
g>> ну правильно, нужно прерывание выполнение кода с сохранением контекста.
g>> g>> Я вот спрашиваю как можно вот такое прерывание на delphi сделать.
H>Дроблением
g>> H>Тю. Да я бы вообще это без итератора сделал Для такой фигни еще итераторы задействовать... g>> H>
g>> H>Сам понимаешь, что завернуть такой код в итератор труда тоже не составит.
g>> Не понимаю. Как после Inc прервать выполнение метода? (например для шедулинга операций чтения)?
H>Ну, тут итератор не нужен вообще H>
H>TReader = Record
H> Offset : Integer;
H> Buffer : TBytes;
H> Constructor Create(ABufferSize : Integer);
H> Function GetBuffer(AStream : TStream) : Boolean;
H>End;
H>Constructor TReader.Create(ABufferSize : Integer);
H>Begin
H> SetLength(Buffer, ABufferSize);
H>End;
H>Function TReader.GetBuffer(AStream : TStream) : Boolean;
H>Begin
H> Inc(Offset, AStream.Read(Buffer[Offset], Length(Buffer) - Offset));
H> Result := Offset = Length(Buffer);
H>End;
H>...
H>With TReader.Create(1024) Do
H> While Not GetBuffer(Stream) Do
H> Begin
H> //shedule
H> End;
H>
H>А можно инициализировать стримом при создании ридера. В общем, есть варианты
Ну вот ты почти сделал ту работу, которую компилятор C# делает автоматически.
G>Не понимаю. Как после Inc прервать выполнение метода? (например для шедулинга операций чтения)?
Попробую тряхнуть стариной Хотя стотыщлет не пробовал Delphi, может TClientSocket не самый лучший вариант, да и современные модификации языка скорее позволят сделать много проще.
TExactReader
type
TExactReaderDone = procedure (Sender: TExactReader) of object;
TExactReader = class
Buffer: TBytes;
BufferPos, BufferSize: Cardinal;
property OnDone: TExactReaderDone;
procedure DataReceived(Sender: TObject; Socket: TCustomWinSocket)
var
DataLen: Integer;
begin
DataLen := Socket.ReceiveLength;
if BufferSize < DataLen then DataLen := BufferSize;
Socket.ReceiveBuf(@Buffer[BufferPos], DataLen);
Inc(BufferPos, DataLen);
Dec(BufferSize, DataLen);
if BufferSize = 0 then
OnDone(Self);
end;
constructor Create(Sock: TClientSocket; Size: Cardinal; Handler: TExactReaderDone)
begin
BufferSize := Size;
BufferPos := 0;
SetLength(Buffer, BufferSize);
OnDone := Handler;
Sock.OnRead := DataReceived;
end;
destructor Destroy
begin
Sock.OnRead := nil;
end;
end;
Хотя вроде изначально речь шла о работе со сложными данными, с переменными полями, когда размер получается по ходу чтения.
Тов. gandjustas, а как выглядит код её вызывающий ReadExact?
Вот еще один вариант, может тоже не совсем уж плох?
type
TDataStreamReceived = procedure (Sender: TDataStreamer) of object;
TDataStreamer = class
Buffer: TBytes;
BufferPos, BufferSize: Cardinal;
property OnReceived: TDataStreamReceived;
procedure DataReceived(Sender: TObject; Socket: TCustomWinSocket)
var
DataLen: Integer;
begin
DataLen := Socket.ReceiveLength;
if ((BufferPos+DataLen) >= BufferSize) or not Assigned(Buffer) then
begin
while (BufferPos+DataLen) >= BufferSize do BufferSize := BufferSize*2;
SetLength(Buffer, BufferSize);
end;
Socket.ReceiveBuf(@Buffer[BufferPos], DataLen);
Inc(BufferPos, DataLen);
OnReceived(Self);
end;
procedure RemoveHandled(Size: Cardinal)
begin
MoveMemory(@Buffer[0], @Buffer[Size], BufferPos-Size);
Dec(BufferPos, Size);
end;
constructor Create(Sock: TClientSocket)
begin
Buffer := nil;
BufferPos := 0;
BufferSize := 4*1024;
Sock.OnRead := DataReceived;
end;
destructor Destroy
begin
Sock.OnRead := nil;
end;
function GetByte(var AtPos: Cardinal; var Data: Byte): Boolean;
function GetWord(var AtPos: Cardinal; var Data: Word): Boolean;
function GetDWord(var AtPos: Cardinal; var Data: DWord): Boolean;
function GetString(var AtPos: Cardinal; var S: String): Boolean;
end;
TCommandProcessor = class
Sock: TClientSocket;
Streamer: TDataStreamer;
procedure OnData(Stream: TDataStreamer)
var
Cmd: Word;
Text: string;
DataType, ValueIndex: DWord;
I: Cardinal;
begin
I := 0;
if not S.GetWord(I, Cmd) then Exit;
case Cmd of
$0001: begin
if not GetString(I, Text) then Exit;
MessageBox(0, text, 'A message', MB_OK);
end;
$1001: begin
if not S.GetDWord(I, DataType) then Exit;
if not S.GetDWord(I, ValueIndex) then Exit;
ProcessInformationRequest(DataType, ValueIndex);
end;
end;
S.RemoveHandled(I);
end;
constructor Create(Sock: TClientSocket)
begin
Streamer := TDataStreamer.Create(Sock);
Streamer.OnReceived := OnData;
end;
end;
Здравствуйте, Head Ache, Вы писали:
HA>Здравствуйте, gandjustas, Вы писали:
G>>Ну и сколько ребер будет в графе? Очевидно что не N^2 потому что все со всеми живые объекты связаны не будут, то есть примерно количество ребер в графе будет линейно зависеть от количества вершин. В итоге тот же O(N) получим
HA>Ощущение, что ты не совсем понимаешь что значит "доказать".
Я вообще-то не очень понимаю что вообще хочется доказать?
HA>1% объектов имеют число связей, пропорциональных N, 99% имеют 0 связей => общая оценка O(N^2)
N что такое?
Это видимо тот самый случай когда O(N^2) оказывается меньше O(N).
Собственно сама асимптотика GC вообще-то не интересует. Интересует реальная скорость работы, которая достигается оптимизациями и хаками.
Здравствуйте, Eugeny__, Вы писали:
E__>Если в коде такое количество связей, и объекты друг на друга ссылаются, то проблема со скоростью GC уходит даже не на второй план, а сильно дальше, потому как самая главная проблема в днк писавшего такой код.
Ну что вас заставляет писать ВОТ ЭТО, да еще и хвастаться:
Как ты думаешь, что это такое ? В дотнет это почти последовательность — если вызвать n-раз. Что бы стало по настоящему последовательностью, нужно заставить компилятор генерировать чуток кода:
public IEnumarable<Item> GetNextItem()
{
while(true)
{
yeild return new Item();
}
}
....
Все просто и никаких "структур" не надо.
foreach(Item item in GetNextItem())
{
// бесконечный цикл создания объектов
// со "структурами" на это памяти не хватит
}
Здравствуйте, enji, Вы писали:
E>Ну так на все случаи и не надо Надо только на конкретные случаи. Причем где-то надо именно либу, а где то хватит обычного "одноразового" кода, который решает задачу. Запись событий мышки — типичный пример такого кода, который очень прост и элементарно пишется каждый раз с учетом потребностей.
Такой код слишком прост что бы писать его каждый раз.
E>>>Распознавание мышиных жестов в дельфях из коробки. Килобайтов ифов там нет... E>-_*>А как они жесты распознают ?
E>А я откуда знаю? Я про это читал, но дельфи давно уже не использую. А что, наличие Rx — обязательное условие для распознавания жестов?
Rx это просто фреймворк который можно приспособить куда угодно, в т.ч. для обработки мыши.
>Насколько я все это понимаю, достаточно записать посл движений и сравнить с образцом. Алгоритм сравнения — это уже интересный вопрос. В институте на нейронных сетях делал какое-то распознавание...
RX позволяет свести это исключительно к алгоритму распознавания.
E>-_*>Это стандартная либа с широкими возможностями и благодаря ей не надо писать либы на все случае жизни, как "жестов в дельфях из коробки". Известная вобщем то проблема еще древнего Борланда — написать либы на все случаи жизни вместо хорошего фреймворка, через полгода-года обнаружить что случаев много больше, переписать все это с нуля и опять заточить на все случаи жизни вместо хорошего фреймворка и снова обнаружить что случаев много больше и тд.
E>Часто оказывается что случаев даже больше, чем покрывает фреймворк И приходится его допиливать или писать что-то сбоку.
Хороший фреймворк не затачивается на все случаи, он пишется с рассчетом на то, в том числе, что его можно будет допилить или написать чтото сбоку. А у борланда испокон веков идея фикс — покрыть все возможные случаи.
Материал из Википедии — свободной энциклопедии, -_*