Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2008.06.22;
Скачать: [xml.tar.bz2];

Вниз

Лисп   Найти похожие ветки 

 
Григорьев Антон ©   (2008-05-06 11:37) [120]


> oxffff ©   (06.05.08 10:45) [109]
> Мой пример будет работать, если вы знаете как устроен Delphi.

Правда будет? "Будет работать" в контексте нашей беседы означает "будет работать как в Лиспе". В Лиспе можно работать со строками. Ваш пример, в котором вы используете CopyMemory, со строками работать не может. Следовательно, как в Лиспе он работать не будет.

Специально разжёвываю подробно, чтобы в том случае, если вы со мной не согласны, вы могли указать, в каком именно пункте.

> Почему вы пытаетесь обвинить меня в том, как устроен TvarRec.

Извините, но это ваши фантазии. Я вас в этом не обвинял.

> И более того пытались мне вменить ошибку с CopyMemory (см
> )
>
> Напоминаю вам ваш пост
>
> Григорьев Антон ©   (05.05.08 22:12) [90]
> Будете использовать CopyMemory с автоматически финализируемым
> типом?
>
> TvarRec - имеет простую семантику копирования.
>
> Поэтому ситуацию которые вы смоделировали относится к TvarRec,
>  а не к моей реализации.

Снова разжёвываю по буквам. Чтобы вам было понятно, в чём именно я вас обвиняю. Нумерую свои утверждения, чтобы вам легче было указать, какое из них конкретно кажется вам неправильным.

1. Конструктор открытого вариантного массива позволяет передавать строки в качестве элементов массива. Строки при этом трактуются как AnsiString.

2. При передаче элементов открытого вариантного массива через стек элементы финализируемых типов просто копируются как указатели, механизм подсчёта ссылок при этом не задействется.

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

4. Время жизни результата, который возвращает ваша функция TrickInit, в общем случае непредсказуемо и может быть существенно больше, чем время жизни элементов массива.

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

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

Вот, собственно, какие именно у меня претензии к вашему коду.

> Вы сначала пытались прицепится к CopyMemory. А потом когда
> я вам популярно объяснил, что TvarRec не автоматически финализируемый
> пытались мне вменить свое незнание.  :)

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

> Я вам написал три варианта решения.
>
> Кстати как там ваше домашнее задание? см. выше

Во-первых, предупреждаю, что я последний раз терплю ваше хамство. Чтобы разговаривать таким тоном и раздавать домашние задания, надо иметь подавляющее превосходство в знаниях и опыте. Вы уверены, что оно у вас есть?

Далее, я вам с самого начала сказал, что "как в Лиспе" - это работа с простыми типами без всяких обёрток, поэтому ООП и TCustomVariant здесь не при чём - они не отвечают начальному условию задачи. Если вы этого до сих пор не поняли, то я тоже не могу нести за это ответственности. Что касается третьего варианта (точнее, первого в хронлогическом порядке), то он не умеет работать со строками. Так что вы пока не предложили ни одного решения, которое было бы сравнимо по общности с Лиспом. А вовсе не три, как вы здесь пишете.


 
crux   (2008-05-06 11:38) [121]

crux   (06.05.08 11:26) [118]

Можно написать так:

#include <string>
use namespace std;

string foo;

foo = string("foo") + "bar";

Cложение констант на С можно написать и так foo = "foo""bar", если нужно зачем-то сложить именно константы.

Если одна из переменных в выражении имеет тип string, то оператор + практически всегда будет работать.


 
Alkid ©   (2008-05-06 11:40) [122]


> Вариант на TVarRec самый простой и менее гибкий.

Верю. Есть и более гибкие :) На взять произвольную функцию sin(double) и засунуть её в этот mapcar без обёртки не получится :)

Можно вообще заменить все функции на классы, реализующие метод Apply([]), а все значения на объекты и получить на базе дельфи язык с первоклассными функциями и проч. и проч.

И не надо никакого хакинга, битов, байтов и т.п. ООП в чистом виде.
Вот только писать в таком стиле замучаешься :)


 
Alkid ©   (2008-05-06 11:42) [123]


> foo = string("foo") + "bar";

Дык, об этом и речь. Конструктор вызывать приходится явно. Это "протечка абстракции" в терминологии Джоэля Спольски. Со стрингами, конечно же, это фигня, не проблема. А с mapcar`ом уже нет.


 
Игорь Шевченко ©   (2008-05-06 11:44) [124]

crux   (06.05.08 11:38) [121]


> foo = string("foo") + "bar";


> Cложение констант на С можно написать и так foo = "foo""bar"


Видите ли, в Паскале можно написать
var
 s: string;
begin
 s := "foo" + "bar";
...

Об чем, собственно, был спич с самого начала. О разнице работы со строками в С и в Паскале. Хотя и то и то переводится в машинные команды.


> оператор + практически всегда будет работать.


ключевое слово, надо понимать, "практически". Так в паскале оператор сложения работает всегда, а не практически всегда.

В теме идет речь о том, можно ли смоделировать конструкции одних языков в других языках и насколько модель будет точной.
Часть авторов утверждает, что можно, часть утверждает, что целиком и полностью нельзя.
Вот и все, пример с С был приведен для иллюстрации второй точки зрения.


 
crux   (2008-05-06 11:59) [125]

Игорь Шевченко ©   (06.05.08 11:44) [124]

А как вы считаете, насколько точна модель работы со строками в c++ относительно ее же в паскале?

Можно считать, что они эквивалентны, так как авторы не учли наличие функционально схожих, но по-разному записываемых операций.

Например, вот такое выражение вполне себе будет работать

string r, s = "a";

r = s + "b" + "c" + "d";

и если рассматривать хвость "c" + "d", то фразу о том, что "Как ты ни бейся, а сделать так, что бы выражение "bla-bla-bla" + "bu-bu-bu" на С++ занималось конкатенацией строк, а не сложением указателей, не выйдет." не верно.

такое уже не будет работать

r = "b" + "c" + s + "d";

но первый оператор можно заменить на функционально-идентичный эквивалент

r = "b""c" + s + "d";

и все прекрасно заработает.


 
Alkid ©   (2008-05-06 12:10) [126]


> crux   (06.05.08 11:59) [125]

Кто же спорит?
Однако это уже иллюстрация к тому, то *точно* воспроизвести некоторые абстракции одного языка на другом не всегда получается. И это, кстати, крайне примитивный случай - строки в двух очень похожишь по идеологии языка.


 
oxffff ©   (2008-05-06 12:33) [127]


> Григорьев Антон ©   (06.05.08 11:37) [120]
>
> > oxffff ©   (06.05.08 10:45) [109]
> > Мой пример будет работать, если вы знаете как устроен
> Delphi.
>
> Правда будет? "Будет работать" в контексте нашей беседы
> означает "будет работать как в Лиспе". В Лиспе можно работать
> со строками. Ваш пример, в котором вы используете CopyMemory,
>  со строками работать не может. Следовательно, как в Лиспе
> он работать не будет.

Я вам 865 раз повторяю проблема здесь не CopyMemory, а в том что вы не понимаете как работает TVarRec. :)
Вот пример

procedure abc(a:array of const;b:array of const);
begin
a[1]:=b[1];                <- Здесь простое копирование.
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
abc([1],[2]);
end;

>
> Специально разжёвываю подробно, чтобы в том случае, если
> вы со мной не согласны, вы могли указать, в каком именно
> пункте.
>
> > Почему вы пытаетесь обвинить меня в том, как устроен TvarRec.
>
>
> Извините, но это ваши фантазии. Я вас в этом не обвинял.
>
>
> > И более того пытались мне вменить ошибку с CopyMemory
> (см
> > )
> >
> > Напоминаю вам ваш пост
> >
> > Григорьев Антон ©   (05.05.08 22:12) [90]
> > Будете использовать CopyMemory с автоматически финализируемым
>
> > типом?
> >
> > TvarRec - имеет простую семантику копирования.
> >
> > Поэтому ситуацию которые вы смоделировали относится к
> TvarRec,
> >  а не к моей реализации.
>
> Снова разжёвываю по буквам. Чтобы вам было понятно, в чём
> именно я вас обвиняю. Нумерую свои утверждения, чтобы вам
> легче было указать, какое из них конкретно кажется вам неправильным.
>
>
> 1. Конструктор открытого вариантного массива позволяет передавать
> строки в качестве элементов массива. Строки при этом трактуются
> как AnsiString.
>
> 2. При передаче элементов открытого вариантного массива
> через стек элементы финализируемых типов просто копируются
> как указатели, механизм подсчёта ссылок при этом не задействется.
>
>
> 3. При таком подходе имеется гарантия (за исключением редких
> случаев извращений с глобальными переменными или параллельной
> передачей элементов массива через другие параметры функции),
>  что время жизни массива меньше, чем время жизни его элементов,
>  поэтому такое простое копирование не приводит к осложениям.
>  (Поясню: сам массив перестаёт существовать в эпилоге "его"
> функции, а финализация элементов массива может происходить
> не раньше чем сразу после возврата из этой функции.)
>

> 4. Время жизни результата, который возвращает ваша функция
> TrickInit, в общем случае непредсказуемо и может быть существенно
> больше, чем время жизни элементов массива.

Вы предлагаете мне нарушить семантику типа  TvarRec?
Я вам привел уже несколько примеров.

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

Вы не понимаете семантику типа TVarRec
Повторяю

procedure abc(a:array of const;b:array of const);
begin
a[1]:=b[1];                <- Здесь простое копирование.
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
abc([1],[2]);
end;

> 6. Компилятор никак не защищает вашу функцию от передачи
> в неё строк. Следовательно, если вы применяете методы, которые
> для строк не подходят, вы должны сами предусмотреть защиту,
>  благодаря которой функция будет работать правильно или
> сообщать об ошибке (например, выкидывая исключение). Вы
> этого не сделали.

>
> Вот, собственно, какие именно у меня претензии к вашему
> коду.
>
> > Вы сначала пытались прицепится к CopyMemory. А потом когда
>
> > я вам популярно объяснил, что TvarRec не автоматически
> финализируемый
> > пытались мне вменить свое незнание.  :)
>
> Я не утверждал, что TVarRec финализируемый. Я утверждал
> (и продолжаю утверждать), что в вашем случае ссылка на финализируемые
> данные может попасть в TVarRec и не будет учтена при подсчёте
> ссылок, а вы ничего не сделали, чтобы предотвратить это.
>  Всё остальное - ваши личные фантазии, за которые я не могу
> нести ответственности.
>

Вы как программист должны наконец изучить работу типа TVarRec.
Семантика копирования отличается о TVarData.

> > Я вам написал три варианта решения.
> >
> > Кстати как там ваше домашнее задание? см. выше
>
> Во-первых, предупреждаю, что я последний раз терплю ваше
> хамство. Чтобы разговаривать таким тоном и раздавать домашние
> задания, надо иметь подавляющее превосходство в знаниях
> и опыте. Вы уверены, что оно у вас есть?
>
> Далее, я вам с самого начала сказал, что "как в Лиспе" -
>  это работа с простыми типами без всяких обёрток, поэтому
> ООП и TCustomVariant здесь не при чём - они не отвечают
> начальному условию задачи. Если вы этого до сих пор не поняли,
>  то я тоже не могу нести за это ответственности. Что касается
> третьего варианта (точнее, первого в хронлогическом порядке),
>  то он не умеет работать со строками. Так что вы пока не
> предложили ни одного решения, которое было бы сравнимо по
> общности с Лиспом. А вовсе не три, как вы здесь пишете.


Первый вариант не нарушает семантику типа TvarRec.
Повторяю не нарушает.

В этом примере при создании локальной копии также происходит копирование простое без анализа типа.

Вот вам ваши же грабли на вполне корретном с точки зрения синтаксиса примере.

var GlobalA:string;

procedure abc(a:array of const;b:array of const);
begin
GlobalA:="";
a[1]:=a[0];
a[0]:=b[0];
Showmessage(pchar(a[1].VString)) <- это делать небезопасною.
end;

procedure TForm1.Button1Click(Sender: TObject);
var a:string;
begin
GlobalA:=a+"bbb";
abc([GlobalA,1],[555]);
end;

Когда вы наконец пойтете как работает TvarRec. Тогда вы поймете как правильно передавать строки.
А именно использовать для этого то что ждет от вас TVarRec.
var a:string[10];

И это все от вашего незнания.


 
oxffff ©   (2008-05-06 12:39) [128]

To Григорьев Антон ©

Проблема в том что любое использование TvarRec обязывает вас(программиста) управлять временем жизни ручным способом.
Такова семантика типа TvarRec, которую я не нарушаю.


 
oxffff ©   (2008-05-06 12:45) [129]


> 5. Простое копирование ссылок на финализируемые данные с
> помощью CopyMemory или иным подобным способом в тех случаях,
>  когда нет гарантии, что копия не переживёт оригинал - абсолютно
> безграмотное действие. Именно это я и хотел сказать с самого
> начала.
>
> 6. Компилятор никак не защищает вашу функцию от передачи
> в неё строк. Следовательно, если вы применяете методы, которые
> для строк не подходят, вы должны сами предусмотреть защиту,
>  благодаря которой функция будет работать правильно или
> сообщать об ошибке (например, выкидывая исключение). Вы
> этого не сделали.


Я работаю с TVarRec и знаю семантику копирования этого типа, которая выполняет поэлементное копирование. Поэтому при работе с этим типом ответственность за LifeTime лежит на программисте.
Поэтому эти претензии не ко мне, а к Хейлсбергу.


 
Игорь Шевченко ©   (2008-05-06 12:57) [130]

crux   (06.05.08 11:59) [125]

Опять за рыбу деньги.

Можно заменить и на
foo = string("foo") + string("bar") - и будет прекрасно работать.

Речь совершенно о другом - речь о том, что не всегда возможно заменить конструкции одного языка реализацией на другом языке, строки в C(++) приведены как пример. Но на этом форуме у посетителей наблюдается одна похожая болезнь, они не вникают в смысл дискуссии и начинают ловить блох в конкретных словах конкретных постов конкретных авторов.


 
31512   (2008-05-06 13:08) [131]


> Игорь Шевченко ©   (06.05.08 12:57) [130]

Это одна сторона медали. Другая сторона заключается в том, что вот работаешь, работаешь с каким-нибудь string в С++ (QString в Qt - вот кстати любят разные разботчики своих фремворков наворотить своих "особенных" причмочек для работы со строками), а потом надо тебе воспользоваться некой функцией, а она, собака, только char* понимает. И начинаются выкрутасы... Ну никак не получается паскалеподобная работа со строками.


 
Григорьев Антон ©   (2008-05-06 13:27) [132]


> oxffff ©   (06.05.08 12:33) [127]

Во-первых, как копируются записи типа TVarRec, я знаю, о чём уже писал. Не вижу смысла в вашем повторении.


> Я вам 865 раз повторяю проблема здесь не CopyMemory, а в
> том что вы не понимаете как работает TVarRec. :)
> Вот пример
>
> procedure abc(a:array of const;b:array of const);
> begin
> a[1]:=b[1];                <- Здесь простое копирование.
>
> end;
>
> procedure TForm1.Button1Click(Sender: TObject);
> begin
> abc([1],[2]);
> end;

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

А вот указать конкретную ошибку в моих рассуждениях вы не смогли. Опять рассуждения о том, что я якобы не знаю, как копируется TVarRec. Знаю, что там простое копирование, и с самого начала из этого исходил. Что вы хотите доказать, бесконечно повторяя то, с чем я и так согласен?

> Вы как программист должны наконец изучить работу типа TVarRec.
>
> Семантика копирования отличается о TVarData.

Чем? Посмотрел, какой код генерируется в том и в другом случае - везде простое копирование, только в одном случае 8-и байт, поэтому идёт через eax по частям, в другом - 16-ти байт, поэтому идёт через четырёхкратный вызов movsd. Поясните, пожалуйста, подробнее про отличия в семантике.

> Вот вам ваши же грабли на вполне корретном с точки зрения
> синтаксиса примере.

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

Вы опять меня пытаетесь убедить в том, что я уже писал и о чём я прекрасно осведомлён и без вас. Зачем? Вы не вдумываетесь в мои слова?

> Когда вы наконец пойтете как работает TvarRec. Тогда вы
> поймете как правильно передавать строки.
> А именно использовать для этого то что ждет от вас TVarRec.
>
> var a:string[10];

Не вопрос. Переделываем Button1Click из кода в [97] так:
procedure TForm1.Button1Click(Sender: TObject);
var
 A:VarRecArray;
 S:string[10];
begin
 S:="abc";
 A:=TrickInit([S]);
 S:="123";
 abc(A,XSample);
 ASSERT(A[0].VType = vtString);
 Label1.Caption:=A[0].VString^
end;

Выводится "123", хотя в список мы вроде как записывали "abc". Проблема, думаю, вам понятна: в A[0] на самом деле сохраняется не строка, а указатель на переменную S. Немножко пошаманив, можно добиться того, чтобы на момент использования этого указателя переменной S уже не существовало, а память была занята чем-то другим, тогда будет совсем весело. Итог: string[10], который вы рекомендовали, также не позволяет использовать списки элементарных типов в стиле Лиспа. Тут же возникает куча оговорок, которые не дают выполнить многих действий.

> Я работаю с TVarRec и знаю семантику копирования этого типа,
>  которая выполняет поэлементное копирование. Поэтому при
> работе с этим типом ответственность за LifeTime лежит на
> программисте.

Да, это очень похоже на работу в Лиспе, где программист вообще не управляет распределением памяти, а время жизни определяется сборщиком мусора :)))))))))))

> Поэтому эти претензии не ко мне, а к Хейлсбергу.

Есть у меня какие-то смутные воспоминания, что TVarRec и array of const появились в относительно поздних версиях Delphi, когда Хейлсберг уже Delphi не занимался...

Но в любом случае, к разработчикам Delphi претензий нет. Они дали инструмент с вполне понятной областью применимости и ограничениями, и каждый волен использовать или не использовать его. Претензии есть к конкретному человеку под ником oxffff, который утверждает, что этот инструмент достаточно гибок, чтобы заменить списки Лиспа, но при этом все решения, которые он предлагает, оказываются намного более ограниченными, чем Лисп. Не надо сводить вопрос "можно ли так, как в Лиспе" к вопросу "как правильно использовать TVarRec. Если вы можете написать такую функцию на основе TVarRec, с помощью которой программист, как в Лиспе, сможет не думать ни о какой семантике копирования, напишите. Если нет - не надо уходить в сторону и рассуждать о том, как надо использовать TVarRec. А решения, которое работало бы и с простыми типами, и со строками без обёрток вы так и не показали.


 
Григорьев Антон ©   (2008-05-06 13:32) [133]


> oxffff ©   (06.05.08 12:39) [128]
> To Григорьев Антон ©
>
> Проблема в том что любое использование TvarRec обязывает
> вас(программиста) управлять временем жизни ручным способом.
>  
> Такова семантика типа TvarRec, которую я не нарушаю.

TVarRec - это внутренняя кухня хранения списков. Если вы не можете предложить такой метод работы со списками, который позволяет программисту не думать о внутренней кухне, а работать на более высоком уровне абстракции, значит, вы не можете предложить столь же общего решения, какое даёт Лисп. Что и требовалось доказать.


 
Пробегал2...   (2008-05-06 13:34) [134]

Игорь Шевченко ©   (05.05.08 21:06) [86]
Эт ты сказки рассказывай где-нибудь еще. Ты тут личность давно известная, повадки твои тоже


я видимо должен сгореть от стыда... Аргументы на грани фантастики.

Если вы судите о том, спорил ли я или нет лишь по моему нику - да на здоровье. Я предлагаю делать анализ на основании сказанного, а если вы перечитаете сказанное - я нигде не спорил. А уж как вам там хочется думать - ваше право.


 
Пробегал2...   (2008-05-06 13:37) [135]

oxffff, ну ты действительно не прав. Ты вместо выдачи универсального решения выдал ограниченное решение и объяснил ПОЧЕМУ оно ограниченное. Но кому нужно это объяснение? Решение не является общим и универсальным - и неважны причины, все, оно уже не такое как в LISP.

Или надо доказать, что в LISP тоже есть ограничения в решении.


 
crux   (2008-05-06 14:45) [136]

Игорь Шевченко ©   (06.05.08 12:57) [130]

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

Если в высказываниях некоторых авторов наблюдаются вполне определенные искажения истинного положения вещей (например, такие, как утверждение об отсутствии типа string в C++), то некоторые другие авторы, которым эти искажения небезразличны, стремятся немного прояснить ситуацию. Это стоит так расценивать. Прощу прощения, конечно, за препирательства, но некоторые авторы тоже должны иметь совесть.

31512   (06.05.08 13:08) [131]


> Это одна сторона медали. Другая сторона заключается в том,
>  что вот работаешь, работаешь с каким-нибудь string в С++
> (QString в Qt - вот кстати любят разные разботчики своих
> фремворков наворотить своих "особенных" причмочек для работы
> со строками), а потом надо тебе воспользоваться некой функцией,
>  а она, собака, только char* понимает. И начинаются выкрутасы.
> .. Ну никак не получается паскалеподобная работа со строками.


Опытные авторы, как правило, знают о экстракторах, о том как использовать vector<char> c legacy api для передачи и получения данных, извлекая указатель на первый элемент вектора и легким движением руки копируя его содержимое в string посредством алгоритма, либо использовании метода data() в некоторых реализациях, и как-то не жалуются особо, живя с этим. Что конечно для авторов практикующих паскаль может показаться непривычным. Окститесь. Мы ведь можем и о недостатках паскаля еще поговорить, но мы же не будем делать этого. Правда?


 
Alkid ©   (2008-05-06 15:22) [137]


> Если в высказываниях некоторых авторов наблюдаются вполне
> определенные искажения истинного положения вещей (например,
>  такие, как утверждение об отсутствии типа string в C++),
>  то некоторые другие авторы, которым эти искажения небезразличны,
>  стремятся немного прояснить ситуацию. Это стоит так расценивать.
>  Прощу прощения, конечно, за препирательства, но некоторые
> авторы тоже должны иметь совесть.

Тут не было таких утверждений. Было утверждение, что работа со строками в С++ и в Паскале реализована немного по-разному и из-за особенностей языка С++ реализовать её ТОЧНО ТАК ЖЕ, как в паскале нельзя. Так что к совести предлагаю ещё прикладывать внимательность прочтения :) Большего не утверждалось.


 
Игорь Шевченко ©   (2008-05-06 15:29) [138]

crux   (06.05.08 14:45) [136]


> Если в высказываниях некоторых авторов наблюдаются вполне
> определенные искажения истинного положения вещей (например,
>  такие, как утверждение об отсутствии типа string в C++),
>  


Такой, как в Паскале - факт, отсутствует :) Я все-таки рекомендую читать весь пост, а не отдельные буквы.
Аналогично прошу пардону за препирательство


 
31512   (2008-05-06 15:30) [139]


> crux   (06.05.08 14:45) [136]

Я не отношу себя к опытным авторам, по причине не знания определения такового.

> либо использовании метода data() в некоторых реализациях,
>  и как-то не жалуются особо

Я тоже думал, что мне будет не на что жаловаться... И возрадовался обнаружив QChar * QString::data (). Однако ж подлая void qDebug ( const char * msg, ... ) отказала мне два раза, нехочу, сказала, блин. Спасло QByteArray QString::toAscii () const. Вот и надейся потом на всякие реализации метода data(). Поплакал я немного, проштудировал документацию и программирую себе вздыхая о паскале. Живут же люди и

> и как-то не жалуются особо

Работает ведь и то счастье.


 
oxffff ©   (2008-05-06 16:09) [140]


> Григорьев Антон ©   (06.05.08 13:27) [132]
>
> > oxffff ©   (06.05.08 12:33) [127]
>
> Во-первых, как копируются записи типа TVarRec, я знаю, о
> чём уже писал. Не вижу смысла в вашем повторении.
>

Тогда что вы хотели сказать своим утверждением,
что использование  CopyMemory недопустимо?

>
> > Я вам 865 раз повторяю проблема здесь не CopyMemory, а
> в
> > том что вы не понимаете как работает TVarRec. :)
> > Вот пример
> >
> > procedure abc(a:array of const;b:array of const);
> > begin
> > a[1]:=b[1];                <- Здесь простое копирование.
>
> >
> > end;
> >
> > procedure TForm1.Button1Click(Sender: TObject);
> > begin
> > abc([1],[2]);
> > end;
>
> Ну да, простое копирование. И что, какой глубокий смысл
> у этого примера? Что я должен увидеть такого, что убедит
> меня в моей неправоте? Вы бы договаривали свои аргументы
> до конца, что ли, а то слишком они голословны.


Это я к тому что CopyMemory не вносит ошибок, а выполняет копирование в соответствии с согласшением копирования TvarRec.


>
> А вот указать конкретную ошибку в моих рассуждениях вы не
> смогли. Опять рассуждения о том, что я якобы не знаю, как
> копируется TVarRec. Знаю, что там простое копирование, и
> с самого начала из этого исходил. Что вы хотите доказать,
>  бесконечно повторяя то, с чем я и так согласен?


А хочу я вам показать, что пример использования финализируемого типа вами некорректно выполнен. Ответ см. далее.


>
> > Вы как программист должны наконец изучить работу типа
> TVarRec.
> >
> > Семантика копирования отличается о TVarData.
>
> Чем? Посмотрел, какой код генерируется в том и в другом
> случае - везде простое копирование, только в одном случае
> 8-и байт, поэтому идёт через eax по частям, в другом - 16-
> ти байт, поэтому идёт через четырёхкратный вызов movsd.
> Поясните, пожалуйста, подробнее про отличия в семантике.
>


В том то и дело, что отличия от Copymemory нет.
Почему конструктор статиического массива TVarRec у вас не вызывает подозрений? А от меня вы требуете чтобы я нарушал семантику типа, выполняя глубокое копирование.


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


Копирование происходит согласно семантики типа.
А осложнение которое вы придумываете в своих постах, вызвано тем, что вы осознанно нарушаете соглашение TvarRec передавая финализируемый тип.
А если вы это делаете осознанно, и как вы говорите знаете как это работает, чему я очень рад, то и ответственность за время жизни несете имеено вы(программист). А если вы не понимаете работу TVarRec - это другой вопрос



>
> Вы опять меня пытаетесь убедить в том, что я уже писал и
> о чём я прекрасно осведомлён и без вас. Зачем? Вы не вдумываетесь
> в мои слова?
>
> > Когда вы наконец пойтете как работает TvarRec. Тогда вы
>
> > поймете как правильно передавать строки.
> > А именно использовать для этого то что ждет от вас TVarRec.
>
> >
> > var a:string[10];
>
> Не вопрос. Переделываем Button1Click из кода в [97] так:
>
> procedure TForm1.Button1Click(Sender: TObject);
> var
>  A:VarRecArray;
>  S:string[10];
> begin
>  S:="abc";
>  A:=TrickInit([S]);
>  S:="123";
>  abc(A,XSample);
>  ASSERT(A[0].VType = vtString);
>  Label1.Caption:=A[0].VString^
> end;
> Выводится "123", хотя в список мы вроде как записывали "abc".
>  Проблема, думаю, вам понятна: в A[0] на самом деле сохраняется
> не строка, а указатель на переменную S. Немножко пошаманив,
>  можно добиться того, чтобы на момент использования этого
> указателя переменной S уже не существовало, а память была
> занята чем-то другим, тогда будет совсем весело.


Вы опять не поняли.
Использование строки в стеке, гарантирует ее жизнь на этапе всей работы
функции и не приводит к AV.
Пример приведен для того, что использование array of const налагает ограничения, а именно на управляемые типы.
А именно коли вы передали данные этих типов, то будьте добры обеспечивайте существование их экземпяров на этапе работы.
И беда эта не в том, что TrickInit как то не так написан, а в том, что такова семантика TvarRec.

Итог: string[10],
>  который вы рекомендовали, также не позволяет использовать
> списки элементарных типов в стиле Лиспа. Тут же возникает
> куча оговорок, которые не дают выполнить многих действий.


Тут возникает другой вывод, что использование TvarRec в качестве костылей, налагает ограничения не на костыли, а на семантику типа TvarRec.


> Но в любом случае, к разработчикам Delphi претензий нет.
>  Они дали инструмент с вполне понятной областью применимости
> и ограничениями, и каждый волен использовать или не использовать
> его. Претензии есть к конкретному человеку под ником oxffff,
>  который утверждает, что этот инструмент достаточно гибок,
>  чтобы заменить списки Лиспа, но при этом все решения, которые
> он предлагает, оказываются намного более ограниченными,
> чем Лисп. Не надо сводить вопрос "можно ли так, как в Лиспе"
> к вопросу "как правильно использовать TVarRec. Если вы можете
> написать такую функцию на основе TVarRec, с помощью которой
> программист, как в Лиспе, сможет не думать ни о какой семантике
> копирования, напишите.


Хм. В каждом языке есть свои правила. И лезть со своими более чем странно. Если вы не знаете принцип работы TVarRec, то это ваши проблемы.
:)

Поэтому если вы используте данные костыли, то должны знать принцип их устройства.

Я еще раз повторяю, что проблемы с финализируемым типом лежит в не  реализации костылей, а самой природе TVarRec.
И мне очень жаль, что вы пытаетсь переложить на меня эту ответственность.


Если нет - не надо уходить в сторону
> и рассуждать о том, как надо использовать TVarRec. А решения,
>  которое работало бы и с простыми типами, и со строками
> без обёрток вы так и не показали.


Я вам показал еще два способа с обертками.
В которых семантика копирования "правильная" по сравнению с семантикой TVarRec.


 
Пробегал2...   (2008-05-06 16:10) [141]

Игорь Шевченко ©   (06.05.08 12:57) [130]
Но на этом форуме у посетителей наблюдается одна похожая болезнь, они не вникают в смысл дискуссии и начинают ловить блох в конкретных словах конкретных постов конкретных авторов


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


 
oxffff ©   (2008-05-06 16:11) [142]


> Григорьев Антон ©   (06.05.08 13:32) [133]
>
> > oxffff ©   (06.05.08 12:39) [128]
> > To Григорьев Антон ©
> >
> > Проблема в том что любое использование TvarRec обязывает
>
> > вас(программиста) управлять временем жизни ручным способом.
>
> >  
> > Такова семантика типа TvarRec, которую я не нарушаю.
>
> TVarRec - это внутренняя кухня хранения списков. Если вы
> не можете предложить такой метод работы со списками, который
> позволяет программисту не думать о внутренней кухне, а работать
> на более высоком уровне абстракции, значит, вы не можете
> предложить столь же общего решения, какое даёт Лисп. Что
> и требовалось доказать.


Если вы находитесь на кухне в гостях, то соблюдайте правила этого дома.
:)


 
Игорь Шевченко ©   (2008-05-06 16:25) [143]

Пробегал2...   (06.05.08 16:10) [141]

Читаем правила форума долго и внимательно. Не удивляемся потом репрессиям.


 
Игорь Шевченко ©   (2008-05-06 16:30) [144]

oxffff ©   (06.05.08 16:09) [140]


> Хм. В каждом языке есть свои правила.


Об чем, собственно, речь на протяжении многих постов. В LISP свои правила, в Delphi свои. Попытка их смешать может привести к созданию совершенно неудобных в работе монстров.

Кстати, аналогичная фигня, но гораздо проще для понимания - это функции с переменным числом аргументов. В С они встроены в язык, реализация их на Delphi прямо скажем, затруднительна.


 
Григорьев Антон ©   (2008-05-06 16:35) [145]


> oxffff ©   (06.05.08 16:11) [142]
> Если вы находитесь на кухне в гостях, то соблюдайте правила
> этого дома.
> :)

Подвожу итог. Фактически, вы подтвердили, что программировать в стиле Лиспа на Delphi нельзя. Именно это я и сказал в своём сообщении, с которого начались ваши нападки. Спорить, видимо, больше не о чем. Согласны?

> Я еще раз повторяю, что проблемы с финализируемым типом
> лежит в не  реализации костылей, а самой природе TVarRec.
>
> И мне очень жаль, что вы пытаетсь переложить на меня эту
> ответственность.

Я пытаюсь возложить на вас ответственность за то, чтобы ваша функция правильно работала со строковыми типами. Добьётесь ли вы этого с помощью TVarRec или нет, это вопрос вторичный. Если TVarRec не умеет этого делать, то либо придумайте ему замену, либо признайте, что работать со списками простых типов в Delphi так же, как в Лиспе, не получится. Всё остальное будет пустой демагогией.

> >А решения,
> >  которое работало бы и с простыми типами, и со строками
>
> > без обёрток вы так и не показали.

>
>
> Я вам показал еще два способа с обертками.
> В которых семантика копирования "правильная" по сравнению
> с семантикой TVarRec.

Я же русским языком написал, что "как в Лиспе" - это значит без обёрток, а потому любые варианты с обёртками я в принципе не считаю решениями. Зачем вы снова и снова говорите про них?

> А хочу я вам показать, что пример использования финализируемого
> типа вами некорректно выполнен.

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

Я так понял, вы исповедуете принцип "раз разработчики Delphi об этом не позаботились, то и я не буду". Только так далеко не уедешь, если вы хотите получить в итоге не просто работающий код, а более высокоуровневую абстракцию. Вы её и не смогли сделать.

> Вы опять не поняли.
> Использование строки в стеке, гарантирует ее жизнь на этапе
> всей работы
> функции и не приводит к AV.

Да, но кто гарантирует, что она обязана быть в стеке на том же уровне, что и результат TrickInit? Вот пример:
procedure TForm1.Button1Click(Sender: TObject);
var
 A:VarRecArray;

 procedure InitA;
 var
   S:string[10];
 begin
   S := "abc";
   A := TrickInit([S])
 end;

begin
 InitA;
 abc(A,XSample);
 ASSERT(A[0].VType = vtString);
 Label1.Caption:=A[0].VString^
end;

К моменту, когда мы обращаемся к A[0], переменной S уже не существует, хотя A[0] продолжает хранить указатель на неё. Так что string[10] - это никакой не итог, просто тут появляются другие заморочки. Которых, повторяю, нет в Лиспе. А значит, ваше решение не катит на "в Delphi можно писать в стиле Лиспа".


 
oxffff ©   (2008-05-06 16:47) [146]


> Григорьев Антон ©   (06.05.08 16:35) [145]


На остальное отвечу вечером.


> Да, но кто гарантирует, что она обязана быть в стеке на
> том же уровне, что и результат TrickInit? Вот пример:
> procedure TForm1.Button1Click(Sender: TObject);
> var
>  A:VarRecArray;
>
>  procedure InitA;
>  var
>    S:string[10];
>  begin
>    S := "abc";
>    A := TrickInit([S])
>  end;
>
> begin
>  InitA;
>  abc(A,XSample);
>  ASSERT(A[0].VType = vtString);
>  Label1.Caption:=A[0].VString^
> end;
> К моменту, когда мы обращаемся к A[0], переменной S уже
> не существует, хотя A[0] продолжает хранить указатель на
> неё. Так что string[10] - это никакой не итог, просто тут
> появляются другие заморочки. Которых, повторяю, нет в Лиспе.
>  А значит, ваше решение не катит на "в Delphi можно писать
> в стиле Лиспа".


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

А осложнение которое вы придумываете в своих постах, вызвано тем, что вы осознанно нарушаете соглашение TvarRec передавая финализируемый тип.
А если вы это делаете осознанно, и как вы говорите знаете как это работает, чему я очень рад, то и ответственность за время жизни несете имеено вы(программист).


Однако я предложил не один вариант.
Может рассмотрим и их тоже. Поскольку семантика там правильная, то и проблем меньше.

Предлагаю продолжить вечером. :)
Сейчас опять R3 и таблица LIPS ждет меня.


 
Григорьев Антон ©   (2008-05-06 17:13) [147]


> oxffff ©   (06.05.08 16:47) [146]

Это вы невнимательно читаете то, что я написал. Речь не идёт о том, как правильно работать с TVarRec и array of const. Речь идёт о том, чтобы работать, как в Лиспе. А это значит, что не нужно думать ни об особенностях типа, ни о времени жизни параметров, ни о том, как выделяется память для них, потому что обо всём этом компьютер позаботится автоматически, и позаботится правильно. Своими "сфабрикованными" примерами я хочу показать только одно: вы этого не достигли. Программист должен думать о времени жизни, о том, как выделяется и освобождается память, о том, данные какого типа он передаёт. Вы всё это уже признали, и я не понимаю, почему вы не согласны с тем, что сделать в Delphi, как в Лиспе, с помощью TVarRec у вас не получилось.

> Однако я предложил не один вариант.
> Может рассмотрим и их тоже. Поскольку семантика там правильная,
>  то и проблем меньше.

Ещё раз повторяю, что значит "как в Лиспе":

1. Программист не думает о времени жизни и размещении в памяти данных, это всё отслеживается автоматически.
2. Программист работает со всякими типами данных, в т.ч. и с элементарными, без всяких обёрток.
3. Можно использовать любые функции, даже те, которые содержатся в библиотеках, авторы которых ничего не знали о ваших вариантах имитации Лиспа (встроенные функции я готов вам простить - это compiler magic, с ними мы не будем связываться).

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

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

И ещё один вопрос: а вы хорошо знаете Лисп? Или хотя бы какой-нибудь другой функциональный язык программирования? А то меня терзают смутные сомнения насчёт того, что вы просто не понимаете, что такое "как в Лиспе" и поэтому даже не представляете себе объём задачи, которую сами себе поставили.


 
jack128_   (2008-05-06 17:16) [148]


> Кстати, аналогичная фигня, но гораздо проще для понимания
> - это функции с переменным числом аргументов. В С они встроены
> в язык, реализация их на Delphi прямо скажем, затруднительна.
>

таки проблема не в языке. дельфя позволяет вызывать подобные сишные функции.

Просто в дельфи нету необходимости в такой фишке, так как есть array of Variant и array of const


 
wicked ©   (2008-05-06 17:40) [149]


> Просто в дельфи нету необходимости в такой фишке, так как
> есть array of Variant и array of const

ровно наоборот - в делфи придумали array of Variant и array of const, потому что нету функций с переменным числом аргументов


 
Игорь Шевченко ©   (2008-05-06 17:48) [150]


> Просто в дельфи нету необходимости в такой фишке, так как
> есть array of Variant и array of const


а проблема писать в случае отсутствия аргументов [] ?

Кстате, вот writeln - она истинно с переменным числом. Значит, необходимость в фишке таки есть ?


 
oxffff ©   (2008-05-06 17:57) [151]


> И ещё один вопрос: а вы хорошо знаете Лисп? Или хотя бы
> какой-нибудь другой функциональный язык программирования?
>  А то меня терзают смутные сомнения насчёт того, что вы
> просто не понимаете, что такое "как в Лиспе" и поэтому даже
> не представляете себе объём задачи, которую сами себе поставили.
>


Нет с лиспом я не знаком.
Однако, что такое closures и анонимные функции знаю.
Closures - это объект управляемой кучи.
анонимные функция - функция объявленная по месту, а фактически указатель на нее.
НО честно говоря не вижу особых препятствий для реализации. Однако поскольку нет GC, то управлять временем жизни closure придется вручную.
Я честно говоря по данному вопросу веду диалог в newsgroup по реализации анонимных методов в Delphi for win32 анонсированных недавно.


 
oxffff ©   (2008-05-06 18:07) [152]


> Григорьев Антон ©   (06.05.08 17:13) [147]
>
> > oxffff ©   (06.05.08 16:47) [146]
>
> Это вы невнимательно читаете то, что я написал. Речь не
> идёт о том, как правильно работать с TVarRec и array of
> const. Речь идёт о том, чтобы работать, как в Лиспе. А это
> значит, что не нужно думать ни об особенностях типа, ни
> о времени жизни параметров, ни о том, как выделяется память
> для них, потому что обо всём этом компьютер позаботится
> автоматически, и позаботится правильно. Своими "сфабрикованными"
> примерами я хочу показать только одно: вы этого не достигли.
>  Программист должен думать о времени жизни, о том, как выделяется
> и освобождается память, о том, данные какого типа он передаёт.
>  Вы всё это уже признали, и я не понимаю, почему вы не согласны
> с тем, что сделать в Delphi, как в Лиспе, с помощью TVarRec
> у вас не получилось.
>


Напонимаю, что ваши претензии начались с вопроса о некорректности CopyMemory и лично я все же остаюсь при мнении, что семантику копирования TvarRec вы узнали от меня из этой ветки. :)
Я остаюсь при мнении, что достичь результата можно с TVarRec можно, но
при соблюдении некоторых правил навязынных концепцией разработчиков Delphi на тип семантику типа TVarRec.
Да синтаксис не такой, а что вы хотели.

Вечером продолжим с variant.


 
Alkid ©   (2008-05-06 18:18) [153]


> Нет с лиспом я не знаком.

Познакомься :)
Для расширения кругозора всяко полезно будет.


 
Пробегал2...   (2008-05-06 19:03) [154]

Удалено модератором


 
oxffff ©   (2008-05-06 20:34) [155]


> Григорьев Антон ©   (06.05.08 17:13) [147]


Меняем TvarRec на TVarData.

type TUnaryFunc=function (var Value:variant):variant;
    TArrayOfVariant=array of variant;

function SomeUnaryFunc(var Value:variant):variant;
begin
showmessage(value);
end;

function ForEachDo(var List:array of variant;UnaryFunc:TUnaryFunc):integer;
var i:integer;
begin
for i:=0 to length(List)-1 do List[i]:=UnaryFunc(List[i]);
end;

function TrickInit(List:array of variant):TArrayOfVariant;
var p:pointer;
   Count:integer;
   Res:pointer;
begin
Count:=length(List);
setlength(result,Count);
Copymemory(Result,@list,Count*SizeOf(variant));
p:=typeinfo(Variant);
Res:=result;
asm
mov ecx,Count;
mov edx,p;
mov eax,Res;
call system.@AddRefArray;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
   ArrayOfVariant:TArrayOfVariant;
begin
ArrayOfVariant:=TrickInit(["HI ALL","HERE WE ARE",1,2,3]);
ForEachDo(ArrayOfVariant,SomeUnaryFunc);
end;


 
oxffff ©   (2008-05-06 20:41) [156]


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


Можете прочитать мой блог.

Реализация С# yield на Delphi.
http://santonov.blogspot.com/2007/10/yield-you.html

Там как раз используется аналог closure в виде сохранения Machine State, во всяком смысл тот же - захват внешних переменных.


 
Григорьев Антон ©   (2008-05-07 08:58) [157]


> oxffff ©   (06.05.08 18:07) [152]
> Напонимаю, что ваши претензии начались с вопроса о некорректности
> CopyMemory

Ошибаетесь. Наш разговор начался гораздо раньше, с моего сообщения [50] и последовавших за этим ваших не слишком вежливых ответах.

> и лично я все же остаюсь при мнении, что семантику копирования
> TvarRec вы узнали от меня из этой ветки. :)

Да, я уже почти привык к тому, что у вас в отношении меня регулярно возникают фантазии, которые непонятно откуда берутся.

И вы, кажется, так и не поняли, в чём суть наших с вами разногласий по поводу использования CopyMemory. Вы рассуждаете примерно так: "Раз авторы Delphi не предусмотрели работу с финализируемыми типами, то и я не буду об этом заботится, а тот, кто передал в мою функцию строку и получил битый указатель - сам дурак, потому что не понимает семантику TVarRec". Я такой подход не приемлю в принципе. Я считаю, что тот, кто пишщет функцию, которую будут использовать другие люди, обязан предусмотреть для неё корректное поведение при любых входных данных. Если компилятор допускает передачу строки в качестве параметра, рано или поздно кто-то её передаст. И ваша функция, если вы считаете такой параметр недопустимым, должна выкинуть исключение, а не втихую запороть указатель, заложив в программу мину замедленного действия, которая сработает неизвестно где. Другими словами, функция должна обеспечивать определённый уровень абстракции, а не заставлять пользователя вникать во внутреннюю кухню. По моему глубокому убеждению, если функция этого не обеспечивает, это говорит о низком профессионализме того, кто её писал, и никакие ссылки на семантику типа здесь не катят.

> Я остаюсь при мнении, что достичь результата можно с TVarRec
> можно, но
> при соблюдении некоторых правил навязынных концепцией разработчиков
> Delphi на тип семантику типа TVarRec.
> Да синтаксис не такой, а что вы хотели.

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

> oxffff ©   (06.05.08 20:34) [155]
> Меняем TvarRec на TVarData.

Всё-таки не на TVarData, а на Variant. Я, конечно, знаю, что Variant основан на TVarData, но ведь если объявить var A, B:TVarData, то A:=B также будет простым копированием, как и в случае TVarRec. Чтобы включились механизмы управления временем жизни, нужен всё-таки Variant.

Начнём сначала с мелочей. в Лиспе никогда не модифицируется имеющийся список, любые операции над списком приводят к созданию нового списка. Поэтому ваша функция ForEachDo должна выглядеть так:
function ForEachDo(List: array of variant; UnaryFunc: TUnaryFunc): TArrayOfVariant;
var
 I: Integer;
begin
 SetLength(Result,Length(List));
 for I := 0 to High(List) do
   Result[I] := UnaryFunc(List[I]);
end;


Тогда и функция TrickInit становится не нужна, можно писать просто
ForEachDo(["HI ALL","HERE WE ARE",1,2,3],SomeUnaryFunc);

Но это решение только для простых типов. Чтобы было как в Лиспе, нужно, чтобы ForEachDo умела работать с любым списком, а в Лиспе элементами списка могут быть другие списки. Вот, скажем, такой пример. Пусть у нас есть функция SumList, которая на входе принимает список, на выходе выдаёт число - сумму его элементов. Тогда должна быть допустима такая конструкция (пишу в синтаксисе Паскаля, чтобы было понятнее)
ForEachDo([[1,2,3], [4,5,6], [7,8,9]], SumList);
На выходе должен получится список [6, 15, 24]. Глупый вопрос: сможет ли ваша функция реализовать такое? Без обёрток - вряд ли. Кстати, вариант вида
ForEachDo([VarArrayOf([1,2,3]),VarArrayOf([4,5,6]),VarArrayOf([7,8,9])],Su mList);
на "как в Лиспе" не тянет. Уже догадались, почему, или требуются пояснения?


 
ANB   (2008-05-07 09:49) [158]

Прочитал про ЛИСП и подумал про себя : круче клиппера языка нету :)
Мона писать свои операторы (расширять язык - я так сделал для оконного вывода и печати), мона исполнять любые выражения из строки. Причем не только числовые. Есть массивы переменной размерности. Все остальное мона прикрутить.
Потом еще подумал : а в делфи при желании мона прикрутить практически тоже самое.


 
ANB   (2008-05-07 09:50) [159]

Да, а на скл сортировка пишется в одну строку :)


 
jack128_   (2008-05-07 10:04) [160]


> а проблема писать в случае отсутствия аргументов [] ?

ну если это проблема, то конечно :-))


> в делфи придумали array of Variant и array of const, потому
> что нету функций с переменным числом аргументов


array of Variant - не придумывали. Такой параметр ничем не отличается от array of Integer, например.  а вот нафиг нужен array of const мне вобще не понятно.

PS если бы по умолчанию в дельфи было принято cdecl, а не register, то тогда, может быть, у нас бы были сишные переменные параметры.  А так - имеем, то что имеем. поддержку varargs только для внешних функций...



Страницы: 1 2 3 4 5 6 вся ветка

Форум: "Прочее";
Текущий архив: 2008.06.22;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.96 MB
Время: 0.067 c
2-1212044089
pirks
2008-05-29 10:54
2008.06.22
Каскадные прокси


15-1210238925
@!!ex
2008-05-08 13:28
2008.06.22
Кто не прав.


15-1210575142
zdm77
2008-05-12 10:52
2008.06.22
Ошибка coreide100.bpl


10-1118062128
som
2005-06-06 16:48
2008.06.22
Ошибка при заполнении таблицы данными (Word)


2-1212039243
brother
2008-05-29 09:34
2008.06.22
имеет ли смысл задержка?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский