-
> Григорьев Антон © (06.05.08 09:34) [97] > > > oxffff © (05.05.08 22:34) [91] > > А может изучить мат. часть? > > Учите. Вам знаний матчасти как раз очень не хватает.
Ну. ну. Может вы все же удостоверитесь и откроете отладчик. И посмотрите на код который генерирует компилятор?
И прежде чем мне приводить примеры все же изучите мат. часть.
-
> Григорьев Антон © (06.05.08 09:34) [97] > > > oxffff © (05.05.08 22:34) [91] > > А может изучить мат. часть? > > Учите. Вам знаний матчасти как раз очень не хватает. > > Берём ваш код и слегка дополняем, чтобы можно было получить > какой-то результат. > > type > TXFUNC=function (const a:TvarRec):TvarRec; > VarRecArray=array of TVarRec; > > function abc(var List:array of const;func:TXFUNC):integer; > > var > i:integer; > begin > for i:=0 to length(List)-1 do > LIST[i]:=func(LIST[i]); > Result:=0; > end; > > function XSample(const a:TvarRec):TvarRec; > begin > Result:=a; > end; > > function TrickInit(const List:array of const):VarRecArray; > > begin > Setlength(result,length(list)); > copyMemory(result,@list,sizeof(TvarRec)*length(List)); > end; > > procedure TForm1.Button1Click(Sender: TObject); > var A:VarRecArray; > S:string; > begin > S:='abc'; > UniqueString(S); > A:=TrickInit([S]); > S:='123'; {*} > abc(A,XSample); > ASSERT(A[0].VType = vtAnsiString); > Label1.Caption:=string(A[0].VAnsiString) > end; > > Функция XSample оставляет переданное ей значение без изменения, > поэтому следует ожидать появления в Label1 текста 'abc', > который был присвоен переменной S, переданной затем в качестве > элемента массива. Тем не менее, на экране появляется непонятно > что (проверено в Delphi 7). А вот если убрать строку, отмеченную > звёздочкой, будет, как и ожидалось, строка "abc".
А что вы хотите, если вы не знаете работу с типом TvarRec. И даже не удосужились не только открыть отладчик, но и внимательно посмотреть [92].
И copyMemory(result,@list,sizeof(TvarRec)*length(List)) не имеет к этому никакого отношения.
Тип TvarRec не имеет и иметь не может финализируемых типов. Поэтому семантика копирования простая без использования TypeInfo.
> > Поясню, что здесь происходит. С помощью UniqueString мы > добиваемся того, что значение S хранится в динамической > памяти со счётчиком ссылок, равным 1. Когда мы передаём > это значение в конструктор открытого вариантного массива, > указатель на эту строку тупо копируется как простой указатель,
Это говорит о вашем не знании. Код создания массива создает компилятор. А то что вы не знаете некоторых нюансов налицо.
Вы наверно думаете, что если вы напишите то будет использован механиазм копирования typeinfo.
var a,b:Tvarrec;
a:=b;
Ничего подобного.
Финализируемые типы в вариантных записях запрещены. :) Поэтому будет простое копирование. :)
> который и сохраняется в нулевом элементе массива A. Механизм > подсчёта ссылок при этом не включается. И когда переменной > S присваивается другое значение, память, занимаемая строкой, > считается свободной, и что там будет располагаться - это > как повезёт. А в A[0] при этом сохраняется этот битый указатель, > в результате чего мы и имеем проблемы. Кстати, рекомендую > попробовать после строки со звёздочкой вставить UniqueString(S) > - увидите ещё один интересный эффект :))
Проблемы в том, что вы не понимаете что вы делаете. И что делает компилятор. :)
> > Кстати, я вчера задал вам несколько вопросов по поводу ваших > предложений, но для ответа вы почему-то выбрали только один > из них, скромно умолчав про остальные. >
Я все ваши вопросы ответил. См. внимательно. :)
> В общем, я не советую вам больше разговароивать на грани > хамства с использованием выражений "читай справку", "учи > матчасть" и т.п., потому что после такого становится особенно > неприятно, когда тебя самого ловят на незнании матчасти.
Ну и кто теперь опять не прав? :)
> > > Конечно, можно в вашу функцию TrickInit добавить контроль > за счётчиком ссылок или вообще преобразование, сводящее > всё к PChar и ручному управлению памятью.
Это требуется от вас поскольку приведение делает компилятор и вы должны это знать. :)
Потребуется ещё > куча функций, которые будут в разных ситуациях отвечать > за правильное освобождение памяти в нужный момент. Но удобно > ли будет пользоваться такой библиотекой с такими наворотами? > Да ещё и с учётом того, что для работы с ней подходит не > любой тип данных, а специально организованный, и не любая > функция, а только специально написанная? Предлагаю вам остановится > на таком завершении спора: "В Delphi, сильно извратившись, > можно написать библиотеку, которая, при добровольном соблюдении > её пользователем кучи ограничений, позволит ему программировать > в стиле, похожем на Лисп. Но для решения любой практической > задачи будет удобнее писать в стиле Delphi, чем использовать > такую библиотеку".
C уважением Антонов Сергей. :)
-
> oxffff © (06.05.08 09:49) [100] > Ну. ну. Может вы все же удостоверитесь и откроете отладчик. > И посмотрите на код который генерирует компилятор?
Дык, смотрел ведь :) Копирование указателя увидел, изменения счётчика ссылок - нет. Да и результат работы этого кода говорит сам за себя. Или неизвестно какое значение - это то, что вы хотели получить с самого начала?
А примеры кода приводите вы. Я привожу примеры того, когда ваше решение работает неправильно.
-
> euru © (06.05.08 09:34) [98] > > > Alkid © (05.05.08 17:22) [76] > > А на ABAP как mapcar написать? :))) > > > Например, можно так: > > form mapcar > using in_table type index table > func_name type string > changing out_table type index table > . > field-symbols: <in>, <out>. > > clear out_table. > loop at in_table assigning <in>. > append initial line to out_table assigning <out>. > perform (func_name) in program (sy-cprog) > using <in> > changing <out> > . > endloop. > endform.
Спасибо за пример. Мне тоже нравится понятие field-symbols (которые по сути являются typed ref) на ABAP.
-
> А примеры кода приводите вы. Я привожу примеры того, когда > ваше решение работает неправильно.
Решение правильное. Нужно знать работу компилятора с TvarRec.
Проблема не в коде TrickInit (и кокретно не в CopyMemory). а в том, что TVarrec являясь вариантной записью не может содержать финализируемые типы. И разработчики Delphi не написали Compiler magic функций которые обрабатывают семантику этого типа. В отличии от variant.
Проблема в том что компилятор при приведении делает это грубо, а именно в строке A:=TrickInit([S]);
Посмотрите внимательно. Что будет при передаче по значению function abc(List:array of const); Будет простое копирование на стек. Никакой обработки Vtype в отличии от variant
-
> Дык, смотрел ведь :) Копирование указателя увидел, изменения > счётчика ссылок - нет.
Так устроен Delphi. И на это вы натыкатесь еще до входа в функцию TrickInit. :)
-
> oxffff © (06.05.08 10:04) [101] > Тип TvarRec не имеет и иметь не может финализируемых типов.
Напомню, что именно это я с самого начала и сказал, когда писал, что ваше решение на основе TVarRec ограничено и поэтому не может работать с финализируемыми типами, поэтому мы имеем большие ограничения на работу со строками. В отличие от Лиспа, в котором таких проблем не возникает. Если бы вы сразу признали это, не о чем было бы говорить.
> Это говорит о вашем не знании. > Код создания массива создает компилятор. > А то что вы не знаете некоторых нюансов налицо. > > Вы наверно думаете, что если вы напишите то будет использован > механиазм копирования typeinfo. > > var a,b:Tvarrec; > > a:=b; > > Ничего подобного.
Как раз этого я не думаю. Как копируются записи, я знаю. Откуда вы взяли, что я так думаю - это ваши проблемы.
> Проблемы в том, что вы не понимаете что вы делаете. И что > делает компилятор. :)
Голословное утверждение. Я подробно описал, что, на мой взгляд, делает компилятор. Если я где-то допустил ошибку, укажите, где именно.
> Ну и кто теперь опять не прав? :)
Вы. Потому что вы привели код, позиционируя его как эквивалент Лиспа и не указав дополнительных ограничений. А он эквивалентом не является, так как не умеет работать со строками.
-
to Григорьев Антон ©
Вот пример.
function abc2(list:array of const):integer; begin end;
procedure TForm1.Button1Click(Sender: TObject); begin abc2([1,2,'asd','asdasd']); end;
cм. копирование в теле abc2 при создании копии. Анализа на Vtype нет, а отличие от variant (у которых есть compiler magic). Такова семантика TvarRec.
-
> oxffff © (06.05.08 10:18) [104] > Решение правильное. Нужно знать работу компилятора с TvarRec.
Правильное решение - это то, для которого чётко указаны границы применимости. Вы ничего не написали про ограничения на работу со строками - откуда я мог знать, понимаете ли вы, что ваш пример с ними работать не будет, или нет. Вот и написал, что не будет.
> Посмотрите внимательно. Что будет при передаче по значению > > function abc(List:array of const); > Будет простое копирование на стек. Никакой обработки Vtype > в отличии от variant
А я как сказал? o_O
Я так и писал, что будет простое копирование (точнее, я назвал его не простым, а тупым, но сути это не меняет). Более того, я это знал заранее, ещё до написания этого кода, и специально писал его таким образом, чтобы наиболее наглядно это продемонстрировать.
Теперь выдохните, подумайте и напишите, в чём именно вы хотите меня убедить.
-
> Григорьев Антон © (06.05.08 10:26) [108] > > > oxffff © (06.05.08 10:18) [104] > > Решение правильное. Нужно знать работу компилятора с TvarRec. > > > Правильное решение - это то, для которого чётко указаны > границы применимости. Вы ничего не написали про ограничения > на работу со строками - откуда я мог знать, понимаете ли > вы, что ваш пример с ними работать не будет, или нет. Вот > и написал, что не будет.
Мой пример будет работать, если вы знаете как устроен Delphi.
Почему вы пытаетесь обвинить меня в том, как устроен TvarRec. И более того пытались мне вменить ошибку с CopyMemory (см )
Напоминаю вам ваш пост
Григорьев Антон © (05.05.08 22:12) [90] Будете использовать CopyMemory с автоматически финализируемым типом?
TvarRec - имеет простую семантику копирования.
Поэтому ситуацию которые вы смоделировали относится к TvarRec, а не к моей реализации.
> > > Посмотрите внимательно. Что будет при передаче по значению > > > > > function abc(List:array of const); > > Будет простое копирование на стек. Никакой обработки Vtype > > > в отличии от variant > > А я как сказал? o_O > > Я так и писал, что будет простое копирование (точнее, я > назвал его не простым, а тупым, но сути это не меняет).
А зачем был ваш вопрос про CopyMemory? :)
> Более того, я это знал заранее, ещё до написания этого кода, > и специально писал его таким образом, чтобы наиболее наглядно > это продемонстрировать.
Вы сначала пытались прицепится к CopyMemory. А потом когда я вам популярно объяснил, что TvarRec не автоматически финализируемый пытались мне вменить свое незнание. :)
> > Теперь выдохните, подумайте и напишите, в чём именно вы > хотите меня убедить.
Я вам написал три варианта решения.
Кстати как там ваше домашнее задание? см. выше
-
> oxffff © (06.05.08 09:05) [95]
Всё это, конечно круто, с точки зрения абстрактной математики :) Но это же ужасные костыли, которые неизящны, многословны и обладают ограничениями. Я не хочу писать тонны врапперов для врапперов, что бы уметь применять функцию к списку.
Суть в том, что во всех этих примерах ты делашь примерно следующее: реализуешь своими силами на уровне библиотеки то, что в Лиспе есть по дефолту, на уровне языка. Смотри, сколько ты понаписал для одной функции mapcar, которая есть только один конкретный пример функции высшего порядка, не самый сложный, кстати. И ладно бы ты эту тонну кода понаписал, а пользователь мог бы просто и изящно ей пользоваться. Так нет же, надо ещё свох обёрток понаписать для функций.
Я всё это к чему веду - есть такие вещи, которые должны быть либо поддержаны на уровне самого языка, либо должны быть выброшены и стоит программировать без них. Функции высшего порядка в общем виде, например. Не потому, что из невозможно промоделировать, а потому что полученное решение не будет иметь production quality.
В качестве примера из реальной жизни расскажу, как у нас в конторе некоторые сетлые умы решили забацать свой сборщик мусора для С++. Он даже работал. Но для корректной работы с ним надо было прекрасно разбираться в целом зоопарке смартпоинтеров, изобретённых для его поддержки. А если кто-то где-то ошибался, то вся система нагибалась разом, причём очень трудно было обнаружить, кто и где неправильно что сделал. А программистов много, приходят новые. Кто-то и где-то обязательно налажает. А ведь сборщик мусора - это один из базовых сервисов платформы, о котором не надо особо задумываться. Понятно, что он не должен усложнять программирование и служить источником ошибок.
Так же и тут. Реализовывать функции высшего порядка или хотя бы mapcar в общем виде на Delphi смысла нет, овчинка не стоит выделки. Будет как с тем сборщиком мусора - да, они это сделали, но потом требовалось такое количество магических пассов и приседаний, что бы с ним правильно работать, что лучше было бы ограничиться гораздо более простым и специализированным решением.
-
> Alkid © (06.05.08 10:48) [110]
Никто не спорит.
Было утверждение, что нельзя. Я показываю как можно. То что это костыли никто не спорит. Да это костыли. Но ходить худо бедно можно. :)
-
> oxffff © (06.05.08 10:57) [111]
- Доктор! У меня заворот кишок! - Ничего страшного! Проглотите вот эту палочку.
-
Вот в паскале есть тип string, в C (и в С++) его нету. Много лет разные умы с разной степенью успеха измышляли различные способы работы со строками, подобные работе с ними же в паскале.
И все равно, на обложке издания написано "Британская энциклопудия", то есть, работать так, как в паскале, не получается.
Это я к тому, что работа со строками прекрасно переводится на язык команд процессора.
-
> Было утверждение, что нельзя. Я показываю как можно.
Не совсем. Цитирую:
> вы хотите сказать, что на дельфи этого сделать невозможно? > не понимаю.
В рамках такой общности, как в Лисп - нет.
То, что ты предложил по общности не дотягивает. Это всё же более специальный случай, ибо не на все функции применим, а только на те, которые TVarRec принимают :)
-
> Вот в паскале есть тип string, в C (и в С++) его нету. Много > лет разные умы с разной степенью успеха измышляли различные > способы работы со строками, подобные работе с ними же в > паскале. > > И все равно, на обложке издания написано "Британская энциклопудия", > то есть, работать так, как в паскале, не получается. > > Это я к тому, что работа со строками прекрасно переводится > на язык команд процессора.
Кстати да. Те же яйца, но меньше. Как ты ни бейся, а сделать так, что бы выражение "bla-bla-bla" + "bu-bu-bu" на С++ занималось конкатенацией строк, а не сложением указателей, не выйдет.
-
> Alkid © (06.05.08 11:08) [114] > > > Было утверждение, что нельзя. Я показываю как можно. > > Не совсем. Цитирую: > > > вы хотите сказать, что на дельфи этого сделать невозможно? > > > не понимаю. > > В рамках такой общности, как в Лисп - нет. > > То, что ты предложил по общности не дотягивает. Это всё > же более специальный случай, ибо не на все функции применим, > а только на те, которые принимают :)
Вариант на TVarRec самый простой и менее гибкий. Я кстати еще написал 2 варианта решения. Например на variant, работу с которым можно расширить посредством новых типов используя TcustomVariant.
-
> Я кстати еще написал 2 варианта решения. > Например на variant, работу с которым можно расширить посредством > новых типов используя TcustomVariant.
а свой вариант с иерархией я увижу ?
-
Игорь Шевченко © (06.05.08 11:01) [113]
Вы немного искажаете действительность. Как вам должно быть прекрасно известно, в стандартной (sic!) библиотеке С++ есть тип string, предоставляющий все необходимые абстракции, которые позволяют обращаться со строками как со встроенным типом. Кроме того, интерфейс строк включает в себя интерфейс вектора из той же стандартной библиотеки. А вот интересно, есть ли в паскале стандартная возможность конкатенации строк, посредством добавления в конец (append), позволяющая добиться линейной сложности в этом деле?
-
crux (06.05.08 11:26) [118]
> Вы немного искажаете действительность. Как вам должно быть > прекрасно известно, в стандартной (sic!) библиотеке С++ > есть тип string, предоставляющий все необходимые абстракции, > которые позволяют обращаться со строками как со встроенным > типом
то есть, я могу написать string foo;
foo = "foo" + "bar";
?
|