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

Вниз

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

 
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 только для внешних функций...


 
Игорь Шевченко ©   (2008-05-07 10:13) [161]

jack128_   (07.05.08 10:04) [160]


> PS если бы по умолчанию в дельфи было принято cdecl, а не
> register, то тогда, может быть, у нас бы были сишные переменные
> параметры


Аргументы будут ?


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


Женя, я тебе страшную тайну открою - не все параметры укладываются в 4 байта.


 
jack128_   (2008-05-07 13:23) [162]


> Аргументы будут ?

в сях вызываемая функция с переменным числом параметров (ПЧП) не в курсе о ТИПЕ этих парамеров, поэтому не может очистить стек за ними. но если используется cdecl - этого и не нужно делать, чистить стек должна вызывающая функция. в register же стек должна чистить _вызываемая_ функция. поэтому функции с ПЧП в том виде в каком они реализованы в сях - при использовании register - невозможны.
собственно и не нужны.  в array of Variant - на порядок лудше.


> Женя, я тебе страшную тайну открою - не все параметры укладываются
> в 4 байта.

не понял к чему это?? к array of const vs. array of Variant ??  Можно чуть более развернуто?


 
oxffff ©   (2008-05-07 13:23) [163]


> Григорьев Антон ©   (07.05.08 08:58) [157]
>
> > oxffff ©   (06.05.08 18:07) [152]
> > Напонимаю, что ваши претензии начались с вопроса о некорректности
>
> > CopyMemory
>
> Ошибаетесь. Наш разговор начался гораздо раньше, с моего
> сообщения [50] и последовавших за этим ваших не слишком
> вежливых ответах.
>
> > и лично я все же остаюсь при мнении, что семантику копирования
>
> > TvarRec вы узнали от меня из этой ветки. :)
>
> Да, я уже почти привык к тому, что у вас в отношении меня
> регулярно возникают фантазии, которые непонятно откуда берутся.
>
>
> И вы, кажется, так и не поняли, в чём суть наших с вами
> разногласий по поводу использования CopyMemory. Вы рассуждаете
> примерно так: "Раз авторы Delphi не предусмотрели работу
> с финализируемыми типами, то и я не буду об этом заботится,
>  а тот, кто передал в мою функцию строку и получил битый
> указатель - сам дурак, потому что не понимает семантику
> TVarRec".


Я принимаю такой подход потому, что в Delphi заложена такая семантика работы с этим типом, и нарушать ее не собираюсь.
Если конструктор, создает array of const и делает простое привидение к String -> pchar, то я как пользователь этого обязан соблюдать эти правила, по очень простым причинам. Если я сознательно нарушу работу с этим типом к чему вы призываете, то я должен требовать от клиентов библиотеки также нарушать эти правила, причем начать нужно непосредственно с конструктора Представьте себе, если я увеличу счетик клиентов строки на 1 и верну TvarRec,а клиент не напишит соответствующий финализатор. Mem leak обеспечен.

Отсюда минусы того, что вы требуете
1. каждый клиент типа должен реализовывать ручную финализацию нарушающую первоначальную семантику.
2. Как распознать при возврате клиентом сделала ли это функция обработчик элементов списка.

Вы что разве это не понимаете, или сознательно хотите создать кучу граблей.

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

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

Вопрос как я узнаю, что счетчик переданного string не бы увеличен клиентом до передачи и нужно ли мне это делать?

Вы опять пытаетесь нагородить граблей из-за непонимания.

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

см. выше


 
Игорь Шевченко ©   (2008-05-07 14:02) [164]

jack128_   (07.05.08 13:23) [162]


> в сях вызываемая функция с переменным числом параметров
> (ПЧП) не в курсе о ТИПЕ этих парамеров, поэтому не может
> очистить стек за ними. но если используется cdecl - этого
> и не нужно делать, чистить стек должна вызывающая функция.
>  в register же стек должна чистить _вызываемая_ функция.
>  поэтому функции с ПЧП в том виде в каком они реализованы
> в сях - при использовании register - невозможны.
> собственно и не нужны.


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


> собственно и не нужны.  в array of Variant - на порядок
> лудше.


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

Твои действия ?


 
jack128_   (2008-05-07 14:12) [165]


> Твои действия ?
>

асм рулит :-D

Игорь, тебе для чего ПЧП нужно???  Для совместимости с сями или само по себе??  а то ведь в разных языках есть много всяких фишек, которых нет в дельфи. И все их невозможно реализовать.


 
Игорь Шевченко ©   (2008-05-07 14:28) [166]

jack128_   (07.05.08 14:12) [165]


> асм рулит :-D


реализацию не затруднит ?


> Игорь, тебе для чего ПЧП нужно???  


Я тебе вроде конкретно написал, для чего. Такая задача вполне себе стояла несколько лет назад.


> а то ведь в разных языках есть много всяких фишек, которых
> нет в дельфи. И все их невозможно реализовать.


Ну так о чем и шла речь. А ты про array of const


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


> oxffff ©   (07.05.08 13:23) [163]
> Отсюда минусы того, что вы требуете
> 1. каждый клиент типа должен реализовывать ручную финализацию
> нарушающую первоначальную семантику.
> 2. Как распознать при возврате клиентом сделала ли это функция
> обработчик элементов списка.

Я всё больше убеждаюсь, что вы спорите не с моими словами, а со своими фантазиями на тему моих слов.

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

> Если конструктор, создает array of const и делает простое
> привидение к String -> pchar

А можно поинтересоваться, где там делается приведение string к PChar? Приведение string к PChar - это неявный вызов функции _LStrToPChar, которого я там что-то не увидел. string приводится к простому указателю, а не к PChar.

> Представьте себе, если я увеличу счетик клиентов строки
> на 1 и верну TvarRec,а клиент не напишит соответствующий
> финализатор. Mem leak обеспечен.

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

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

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

Попытаюсь проиллюстрировать это таким примером. Пусть есть код:
procedure TForm1.Test(const S:string);
begin
 Label1.Caption := S;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 T: string;
begin
 T := "abc";
 Test(T);
end;

С помощью отладчика легко убедиться, что при вызове Test(T) для переменной T счётчик ссылок не меняется, хотя в стеке создаётся копия строки - параметр S. Но благодаря модификатору const компилятор имеет гарантию, что строка изменена не будет, а копия S не переживёт оригинал T, и поэтому экономит время на изменении счётчика ссылок. Но стоит убрать const, и вы увидите, что в пролог и эпилог метода Test добавится работа со счётчиком ссылок по всем правилам.

Отсюда вывод: когда есть гарантии, что игнорирование счётчика ссылок не может привести к плохим последствиям, компилятор может это делать для увеличения производительности. Но из этого вовсе не следует, что счётчик ссылок можно игнорировать всегда и везде. Вы согласны с таким утверждением?

> Вопрос как я узнаю, что счетчик переданного string не бы
> увеличен клиентом до передачи и нужно ли мне это делать?

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


 
oxffff ©   (2008-05-07 16:02) [168]


> Григорьев Антон ©   (07.05.08 08:58) [157]
>
> > oxffff ©   (06.05.08 18:07) [152]
> > Напонимаю, что ваши претензии начались с вопроса о некорректности
>
> > CopyMemory
>
> Ошибаетесь. Наш разговор начался гораздо раньше, с моего
> сообщения [50] и последовавших за этим ваших не слишком
> вежливых ответах.
>
> > и лично я все же остаюсь при мнении, что семантику копирования
>
> > TvarRec вы узнали от меня из этой ветки. :)
>
> Да, я уже почти привык к тому, что у вас в отношении меня
> регулярно возникают фантазии, которые непонятно откуда берутся.
>
>
> И вы, кажется, так и не поняли, в чём суть наших с вами
> разногласий по поводу использования CopyMemory. Вы рассуждаете
> примерно так: "Раз авторы Delphi не предусмотрели работу
> с финализируемыми типами, то и я не буду об этом заботится,


Не раз авторы Delphi (самое интересное что последние страницы вы меня в это обвиняли) не предусмотрели работу с финализуруемыми типами,
а авторы Delphi как раз предусмотрели работу с ними иначе неявное приведение типа не производилось.
Только делают они Weak копирование.


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


Работа с TvarRec требует знание семантики TVarRec. Что вас не устраивает?


> Я считаю,
>  что тот, кто пишщет функцию, которую будут использовать
> другие люди, обязан предусмотреть для неё корректное поведение
> при любых входных данных.


Вот именно. Это значит соблюдая правила типа TvarRec.


>Если компилятор допускает передачу
> строки в качестве параметра, рано или поздно кто-то её передаст.
>  И ваша функция, если вы считаете такой параметр недопустимым,
>  должна выкинуть исключение,


Моя функциЯ соблюдает правила типа TvarRect. Моя функция не делает предположений, о том правильно или неправильно, она соблюдает правила.
А вы хотите осознано нагородить граблей.

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

Так работает TVarRec.  
Когда вы работаете с TvarRec вы должны знать правила неявного приведения.

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


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


 
oxffff ©   (2008-05-07 16:06) [169]


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


Расскажите, что вы не можете сделать?


 
Григорьев Антон ©   (2008-05-07 16:38) [170]


> oxffff ©   (07.05.08 16:06) [169]
> Расскажите, что вы не можете сделать?

Как что?!!! о_О Список должен быть всегда списком, одним типом данных. А в этом случае получается, что в одном случае списком называется array of Variant, а в другом - вариантный массив. И получается, что в функцию SumList, если мы захотим вызвать её отдельно от ForEachDo, мы не сможем передать аргумент типа Variant, а не TArrayOfVariant. А если заставить её принимать TArrayOfVariant, то мы не сможем передавать её в ForEachDo.

Другими словами, мы должны будем всё время помнить, что у списка может быть несколько форматов, и при необходимости конвертировать его из одного формата в другой. А это уже не "как в Лиспе".

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

А ещё напомню, что для достижения аналогичного уровня абстракции надо иметь возможность передавать в ForEachDo любую функцию без всяких обёрток, а не только специально написанную. Можно ли, например, без обёртки передать в ForEachDo функцию Math.Ceil? Если нет, то это не "как в Лиспе".

А смысл вашего сообщения [168] я просто не понял. Это ответ на моё сообщение [157], на которое вы уже ответили в [163]. А я уже ответил на него в [167]. Зачем вы через час после моего ответа вновь повторяете те же самые аргументы? Впрочем, вы меня не первый раз уже удивляете тем, что по несколько раз отвечаете на одно сообщение, нередко просто повторяясь.


 
oxffff ©   (2008-05-07 16:47) [171]


> Григорьев Антон ©   (07.05.08 15:07) [167]
>
> > oxffff ©   (07.05.08 13:23) [163]
> > Отсюда минусы того, что вы требуете
> > 1. каждый клиент типа должен реализовывать ручную финализацию
>
> > нарушающую первоначальную семантику.
> > 2. Как распознать при возврате клиентом сделала ли это
> функция
> > обработчик элементов списка.
>
> Я всё больше убеждаюсь, что вы спорите не с моими словами,
>  а со своими фантазиями на тему моих слов.
>
> Я требую, чтобы ваша функция как минимум распознавала данные,
>  с которыми она не умеет работать (строки) и выкидывала
> исключение, если ей передан такой тип. При этом никто ни
> от вас, ни от клиента финализации не требует.
>
> > Если конструктор, создает array of const и делает простое
>
> > привидение к String -> pchar
>
> А можно поинтересоваться, где там делается приведение string
> к PChar? Приведение string к PChar - это неявный вызов функции
> _LStrToPChar, которого я там что-то не увидел. string приводится
> к простому указателю, а не к PChar.
>


Не к простому, а к указателю PShortString.


> > Представьте себе, если я увеличу счетик клиентов строки
>
> > на 1 и верну TvarRec,а клиент не напишит соответствующий
>
> > финализатор. Mem leak обеспечен.
>
> Абсолютно правильно. Но ведь вы же взялись сделать такой
> же высокий уровень абстракции, как в Лиспе, в котором нет
> ни ошибок работы со строками, ни утечек памяти, ни ручной
> финализации. Вот и делайте.


Вы ничего не путате? Я за это не брался.
Я взялся показать, как это можно сделать.
Например с помощью TVarrec.


>Все мои примеры направлены на
> то, чтобы показать: вы такого уровня абстракции не достигли,
>  ваш вариант, в отличие от Лиспа, заставляет пользователя
> думать о том, как размещаются данные в памяти и в какой
> момент эта память освобождается. Так что либо ищите способ
> уменьшить потом этот счётчик автоматически, либо признайте,
>  что "как в Лиспе" через TVarRec у вас не получается. Ничего
> другого я от вас не требую.


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


>
> > Я продолжаю убеждаться, что вы не понимаете простое правило.
>
> >
> > Есть правила типа, которые общие для всех.
> > А первый запор указателя делает компилятор.
>
> Как я уже говорил, у компилятора другая ситуация. Он создаёт
> копию, которая почти со 100%-ой вероятностью (исключение
> составляют случаи сознательного вредительства) не переживёт
> оригинал, поэтому есть гарантия, что за время жизни этой
> неучтённой счётчиком ссылок копии данные не будут освобождены.
>  Вы же действуете в условиях, когда созданная вами копия
> со 100% вероятностью живет дольше, чем оригинал, так что
> никаких гарантий вы не имеете. Мне даже удивительно, что
> вы не понимаете разницу между этими ситуациями.


А у меня как раз складывается другое впечатление, что ситуации которые вы придумали , как раз связаны с тем, что вы видите разницу между этими случаями. А я вам уже показывал, что разницы между этими случаями нет.
Поскольку вы нарушаете правила TvarRec.

var Global:string;

procedure abc(const a:array of const);
begin
.....
Global:="";
showmessage(a[0].vtString); <- сами знаете, что будет. Или вам Пояснить?
end;

abc([Global]);


>
> Попытаюсь проиллюстрировать это таким примером. Пусть есть
> код:
> procedure TForm1.Test(const S:string);
> begin
>  Label1.Caption := S;
> end;
>
> procedure TForm1.Button1Click(Sender: TObject);
> var
>  T: string;
> begin
>  T := "abc";
>  Test(T);
> end;
> С помощью отладчика легко убедиться, что при вызове Test(T)
> для переменной T счётчик ссылок не меняется, хотя в стеке
> создаётся копия строки - параметр S. Но благодаря модификатору
> const компилятор имеет гарантию, что строка изменена не
> будет, а копия S не переживёт оригинал T, и поэтому экономит
> время на изменении счётчика ссылок. Но стоит убрать const,
>  и вы увидите, что в пролог и эпилог метода Test добавится
> работа со счётчиком ссылок по всем правилам.


Мне объяснять способы передач не нужно. Вот вам пример

var Global:string;

procedure abc(const a:string);
begin
Global:="";
showmessage(a); <- Пояснить вам
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
global:="AAA";
UniqueString(global);
abc(global);
end;

Вы теперь будете опять мне предъявлять, что я должен  сделать _Addref строки самостоятельно?
Или теперь будете говорить, что const передача String кривая?

А я вам говорю, что есть правила которые нужно соблюдать при выполнении
Weak копирования.

А может вы и к этому тоже скажите, что это не правильно работает.

constructor TAggregatedObject.Create(const Controller: IInterface);
begin
 // weak reference to controller - don"t keep it alive
 FController := Pointer(Controller);
end;

>
> Отсюда вывод: когда есть гарантии, что игнорирование счётчика
> ссылок не может привести к плохим последствиям, компилятор
> может это делать для увеличения производительности. Но из
> этого вовсе не следует, что счётчик ссылок можно игнорировать
> всегда и везде. Вы согласны с таким утверждением?

Нет, не согласен. Пример см. выше.

А вы теперь со мной согласитесь?


 
oxffff ©   (2008-05-07 16:53) [172]


> Григорьев Антон ©   (07.05.08 16:38) [170]
>
> > oxffff ©   (07.05.08 16:06) [169]
> > Расскажите, что вы не можете сделать?
>
> Как что?!!! о_О Список должен быть всегда списком, одним
> типом данных. А в этом случае получается, что в одном случае
> списком называется array of Variant, а в другом - вариантный
> массив. И получается, что в функцию SumList, если мы захотим
> вызвать её отдельно от ForEachDo, мы не сможем передать
> аргумент типа Variant, а не TArrayOfVariant. А если заставить
> её принимать TArrayOfVariant, то мы не сможем передавать
> её в ForEachDo.


Если вы чего не можете, то это не значит, что этого не могут другие.

Во первых, речи пока не было о списках как о элементах.
И я не брал на себя этой ответственности.
Поставленная ранее задача мной решена как минимум двумя способами.

НО!!!

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


 
Григорьев Антон ©   (2008-05-07 17:44) [173]


> oxffff ©   (07.05.08 16:47) [171]


> Не к простому, а к указателю PShortString.

string - к PShortString? Вы уверены?

> Вы ничего не путате? Я за это не брался.
> Я взялся показать, как это можно сделать.
> Например с помощью TVarrec.

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

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

Какую семантику я нарушил? В статье Variant open array parameters из справки Delphi приведена функция function MakeStr(const Args: array of const): string; Посмотрите, никто не запрещает работать с этой функцией так:
var
 S1, S2: string;
begin
 S1 := "abc";
 UniqueString(S1);
 S2 := MakeStr([S1, 2]);
 S1 := "";
end;

Ни к каким ошибкам этот код не приводит. Значит, семантика array of const сама по себе не запрещает передавать в функцию строковые переменные, которые затем очивающтся. А с вашей функцией такой номер не прошёл. Следовательно, это не только семантика TVarRec, это ещё и особенности вашего кода, о которых нельзя догадаться, если не знать, как ваша функция реализована изнутри.

> var Global:string;
>
> procedure abc(const a:array of const);
> begin
> .....
> Global:="";
> showmessage(a[0].vtString); <- сами знаете, что будет. Или
> вам Пояснить?
> end;

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

> Вы теперь будете опять мне предъявлять, что я должен  сделать
> _Addref строки самостоятельно?
> Или теперь будете говорить, что const передача String кривая?
>
>
> А я вам говорю, что есть правила которые нужно соблюдать
> при выполнении
> Weak копирования.
>
> А может вы и к этому тоже скажите, что это не правильно
> работает.

Из того, что при передаче параметров как TVarRec происходит слабое копирование, вы делаете вывод, что учёт ссылок при работе с TVarRec вообще не нужен. Почему же тогда, встретив у компилятора слабое копирование string, вы не делаете вывод, что вы тоже имеете право в любой ситуации копировать string без учёта ссылок? Или сделали?

> А у меня как раз складывается другое впечатление, что ситуации
> которые вы придумали , как раз связаны с тем, что вы видите
> разницу между этими случаями.

Да, я вижу её. Вижу разницу между созданием копии, которая без специальных телодвижений не переживёт оригинал, и копии, которая этот оригинал точно переживёт. И в CodeGear, судя по тому, как они передают const S:string, тоже её видят. Так что пока вы в меньшинстве.

> Во первых, речи пока не было о списках как о элементах.
>
> И я не брал на себя этой ответственности.

Ошибаетесь. Речь с самого начала шла о том, чтобы "как в Лиспе". А раз в Лиспе возможны вложенные списки, значит, речь шла и об этом. А то, что вы в силу слабого знания Лиспа сами не знали, на что подписываетесь - это исключительно ваши проблемы.

> Поставленная ранее задача мной решена как минимум двумя
> способами.

Кем поставленная? Ечли лично вами, то, может быть, и решена - я не могу этого сказать, так как своё видение того, что именно должно быть сделано, чтобы было "как в Лиспе", вы так и не представили. Но первоначальная задача - нет, потому что "как в Лиспе" у вас не получилось.

И заметьте, что ни один из этих способов не позволяет передавать в ForEachDo произвольную функцию без обёртки, а это входило в условие задачи.

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

> Я пострараюсь вам предложить решение вечером.
> Чисто из спортивного интереса.

Постарайтесь. Только про произвольные функции без обёртки не забудьте.


 
oxffff ©   (2008-05-07 19:42) [174]


> Григорьев Антон ©   (07.05.08 17:44) [173]
>
> > oxffff ©   (07.05.08 16:47) [171]
>
>
> > Не к простому, а к указателю PShortString.
>
> string - к PShortString? Вы уверены?

Здесь я поторопился. Признаю. Приводится к pointer.

>
> > Вы ничего не путате? Я за это не брался.
> > Я взялся показать, как это можно сделать.
> > Например с помощью TVarrec.
>
> Ну так покажите. Пока вы смогли только привести пример,
> весьма далёкий от возможностей Лиспа, что я вам и показал,
>  а на все возражения продолжаете твердить "можно сделать".

Речь зашла вот с этого

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

>oxffff
>А пытался?

>  Я уже не первый раз вам говорю, что у вас только два пути,
>  которые позволяют остаться человеком, отвечающим за свои
> слова. Либо вы делаете пример на TVarRec, который умеет
> нормально работать со строками, не взваливая на клиента
> обязанность управлять их временем жизни, либо вы признаёте,
>  что ошиблись, и через TVarRec сделать этого нельзя. Любой
> другой вариант будет непорядочным поступком.
>
> > Подождите, подождите, нарушить семантику предлагали вы.
>  
> > А я вам ответил, что это не правильно и почему.
> > При соблюдении правил TVarRec все получается.
>
> Какую семантику я нарушил? В статье Variant open array parameters
> из справки Delphi приведена функция function MakeStr(const
> Args: array of const): string; Посмотрите, никто не запрещает
> работать с этой функцией так:
> var
>  S1, S2: string;
> begin
>  S1 := "abc";
>  UniqueString(S1);
>  S2 := MakeStr([S1, 2]);
>  S1 := "";
> end;
> Ни к каким ошибкам этот код не приводит. Значит, семантика
> array of const сама по себе не запрещает передавать в функцию
> строковые переменные, которые затем очивающтся. А с вашей
> функцией такой номер не прошёл. Следовательно, это не только
> семантика TVarRec, это ещё и особенности вашего кода, о
> которых нельзя догадаться, если не знать, как ваша функция
> реализована изнутри.
>
> > var Global:string;
> >
> > procedure abc(const a:array of const);
> > begin
> > .....
> > Global:="";
> > showmessage(a[0].vtString); <- сами знаете, что будет.
>  Или
> > вам Пояснить?
> > end;
>
> Зачем вы приводите мне в пример ситуацию, о которой я сам
> первый заговорил и сам же сказал, что здесь произойдёт?
> Я получил ещё одно подтверждение того, что мои сообщения
> вы читаете по диагонали и не помните, о чём мы разговаривали.
>
>
> > Вы теперь будете опять мне предъявлять, что я должен  
> сделать
> > _Addref строки самостоятельно?
> > Или теперь будете говорить, что const передача String
> кривая?
> >
> >
> > А я вам говорю, что есть правила которые нужно соблюдать
>
> > при выполнении
> > Weak копирования.
> >
> > А может вы и к этому тоже скажите, что это не правильно
>
> > работает.
>
> Из того, что при передаче параметров как TVarRec происходит
> слабое копирование, вы делаете вывод, что учёт ссылок при
> работе с TVarRec вообще не нужен. Почему же тогда, встретив
> у компилятора слабое копирование string, вы не делаете вывод,
>  что вы тоже имеете право в любой ситуации копировать string
> без учёта ссылок? Или сделали?
>
> > А у меня как раз складывается другое впечатление, что
> ситуации
> > которые вы придумали , как раз связаны с тем, что вы видите
>
> > разницу между этими случаями.
>
> Да, я вижу её. Вижу разницу между созданием копии, которая
> без специальных телодвижений не переживёт оригинал, и копии,
>  которая этот оригинал точно переживёт. И в CodeGear, судя
> по тому, как они передают const S:string, тоже её видят.
>  Так что пока вы в меньшинстве.
>
> > Во первых, речи пока не было о списках как о элементах.
>  
> >
> > И я не брал на себя этой ответственности.
>
> Ошибаетесь. Речь с самого начала шла о том, чтобы "как в
> Лиспе". А раз в Лиспе возможны вложенные списки, значит,
>  речь шла и об этом. А то, что вы в силу слабого знания
> Лиспа сами не знали, на что подписываетесь - это исключительно
> ваши проблемы.
>
> > Поставленная ранее задача мной решена как минимум двумя
>
> > способами.
>
> Кем поставленная? Ечли лично вами, то, может быть, и решена
> - я не могу этого сказать, так как своё видение того, что
> именно должно быть сделано, чтобы было "как в Лиспе", вы
> так и не представили. Но первоначальная задача - нет, потому
> что "как в Лиспе" у вас не получилось.
>
> И заметьте, что ни один из этих способов не позволяет передавать
> в ForEachDo произвольную функцию без обёртки, а это входило
> в условие задачи.
>
> Кстати, я уже в каком сообщении напоминаю вам про передачу
> функций без обёртки, а вы это вообще никак не комментируете.
>  Как я должен это понимать? Как то, что вы понимаете безнадёжность
> этой затеи и пытаетесь замолчать её?
>
> > Я пострараюсь вам предложить решение вечером.
> > Чисто из спортивного интереса.
>
> Постарайтесь. Только про произвольные функции без обёртки
> не забудьте.


 
Игорь Шевченко ©   (2008-05-07 20:07) [175]

oxffff ©   (07.05.08 19:42) [174]

В FIDO было наказание за оверквотинг. Не стоит злоупотреблять


 
Григорьев Антон ©   (2008-05-07 20:25) [176]


> oxffff ©   (07.05.08 19:42) [174]
> Речь зашла вот с этого
>
> >Григорьев Антон ©
> > Если вкратце, то функция mapcar получает на вход два параметра:
>
> >  унарную функцию и список. После чего она применяет функцию
>
> > к каждому элементу списка и формирует список, содержащий
>
> > результаты применения, который и возвращает. В языке дельфи,
>
> >  с его системой типов, написать обобщённую функцию такого
>
> > характера не представляется возможным.
>
> >oxffff
> >А пытался?


Те слова, которые вы написали здесь под моим именем, вообще-то написал не я, а Alkid в сообщении [42]. Не надо приписывать мне чужие слова.

Честное слово, такая невнимательность уже начинает изрядно раздражать...


 
ПостОвый терминатор ©   (2008-05-07 20:25) [177]

См. ПостОвый терминатор ©   (05.05.08 17:38) [79]
Господа, существует чат, электроннная почта, ICQ и многое другое.
Вернитесь к посту [79]. Внимательно (очень внимательно) ознакомьтесь с темой ветки.
Не буду перечислять всех дискутирующих не по теме, но отмечу oxffff ©, который в совершенстве владеет Copy - Paste (цитата).


 
Игорь Шевченко ©   (2008-05-07 20:34) [178]

ПостОвый терминатор ©   (07.05.08 20:25) [177]

"Не стоит указывать другим участникам на несоответствие их сообщений данным Правилам. Если Вы считаете, что чье-то сообщение не соответствует Правилам, пошлите сообщение модератору данного форума или (при отсутствии модератора) администратору. "
http://www.delphimaster.ru/forums.shtml#rule


 
oxffff ©   (2008-05-07 21:15) [179]


> Григорьев Антон ©   (07.05.08 20:25) [176]


Предлагаю по теме.

1. Пример при const передачи возможны проблемы.
Для этого нужно сделать weak ссылку недействительной.
Есть различные пути для этого.

В том числе и для массива который не должен пережить оригинал.

Поэтому в примере

> var
>  S1, S2: string;
> begin
>  S1 := "abc";
>  UniqueString(S1);
>  S2 := MakeStr([S1, 2]);
>  S1 := "";
> end;

В MakeStr потенциально можно сделать так, что ссылка с которой она работает стала недействительной. Пример будет аналогичен моему примеру со строками.

2. Теперь, что касаемо TvarRec.

То пример из [97] который приводит в недействительной ссылке слегка некорректен. Вот почему.

Функция обрабатывающая значение не создает нового значения.

function XSample(const a:TvarRec):TvarRec;
begin
Result:=a;
end;

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

3. Я начиная с начала дискуссии не говорил, что синтаксис будет идентичен.

4. Я никак не могу понять какие ко мне претензии.

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

Поэтому, довод что я делаю копию с помощью TrickInit и предоставляю к ней доступ пользователю вместо той которая не видна для пользователя (статический массив который создает компилятор) является причной всех бед мне не понятен. Почему?

Пользователь имеет такие же шансы сделать "ссылку недействительной" в самой процедуре. И пользоваться ей.


 
oxffff ©   (2008-05-07 21:18) [180]


> Пользователь имеет такие же шансы сделать "ссылку недействительной"
> в самой процедуре. И пользоваться ей.


И эта причиной является сама слабая ссылка.


 
Григорьев Антон ©   (2008-05-08 09:26) [181]


> oxffff ©   (07.05.08 21:15) [179]
> Предлагаю по теме.

Давайте. Тема началась с сообщения [42] от Alkid, в котором он написал следующее:


> > вы хотите сказать, что на дельфи этого сделать невозможно?
>
> >  не понимаю.

>
> В рамках такой общности, как в Лисп - нет. И дело тут не
> в процессоре а в том, наборе абстракций и ограничений, которые
> представляют собой язык Delphi.

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

> Я начиная с начала дискуссии не говорил, что синтаксис будет
> идентичен.

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

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

Теперь давайте про TVarRec.

> В MakeStr потенциально можно сделать так, что ссылка с которой
> она работает стала недействительной. Пример будет аналогичен
> моему примеру со строками.

Если вы, не меняя код самой функции MakeStr, а только окружение, в котором она вызывается, сможете сделать так, чтобы ссылка стала недействительной, я буду очень благодарен вам за этот интересный и познавательный пример. Потому что пока я вижу только один способ - запороть S1 из другой нити во время работы MakeStr.

А вообще, спор про TVarRec следует заканчивать, и вот почему:

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

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

Если говорить шире, я вообще считаю array of const очень неудачной добавкой в Delphi. Это средство хорошо справляется с несколькими достаточно узкими проблемами, но при этом порождает большие проблемы, стоит чуть-чуть выйти за пределы той области, на которую она расчитана. Я считаю, что в хорошем языке программирования таких "дырявых абстракций" (по терминологии Джоэла Спольски) быть не должно. Именно поэтому мне не нравится C++ - там слишком много таких средств. Мне ближе подход, который Вирт попытался реализовать в Обероне: всё, что есть в языке, должно описываться на уровне хорошей математической абстракции, для понимания которой не нужно знать, как это реализуется изнутри.

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


 
oxffff ©   (2008-05-08 10:09) [182]


> Если вы, не меняя код самой функции MakeStr, а только окружение,
>  в котором она вызывается, сможете сделать так, чтобы ссылка
> стала недействительной, я буду очень благодарен вам за этот
> интересный и познавательный пример. Потому что пока я вижу
> только один способ - запороть S1 из другой нити во время
> работы MakeStr.


Я сказал о другом. Что функция, которая принимает array of const и передача как const не может считаться безопасной, поскольку с своей работе она может сделать ссылку недействительной самостоятельно обращаясь к внешним переменным или несамостоятельно вызовом других функций, которые понятия не имеют о переданном в другую weak ссылок.
Что касаемо конкретно makestr, то естественно это случай с другим потоком.

Теперь об обещанном мною примере о списках в списке.
Мне нужны некоторые уточнения о  Sum списков.
Sum суммирует только Leaf списки?
что будет, если я напишу так

[ [1,2,3],[4,5,6], [7,8,9,],10, [11,12,[13,14]],]

Мне нужно знать семантику операции для ее реализации.

P.S. Я постараюсь вернутся к обсуждению вечером.


 
Григорьев Антон ©   (2008-05-08 10:20) [183]


> oxffff ©   (08.05.08 10:09) [182]


> Я сказал о другом. Что функция, которая принимает array
> of const и передача как const не может считаться безопасной,
>  поскольку с своей работе она может сделать ссылку недействительной
> самостоятельно обращаясь к внешним переменным или несамостоятельно
> вызовом других функций, которые понятия не имеют о переданном
> в другую weak ссылок.

Абсолютно верно, всё зависит от внутреннего кода функции. Именно из этого я и делаю вывод о том, что ответственность за безопасную работу с array of const лежит на авторе функции, а не на том, кто её потом использует.

> Мне нужны некоторые уточнения о  Sum списков.
> Sum суммирует только Leaf списки?

А это как напишете, так и будет. Так как стоит задача добиться "того же уровня общности", то мы должны иметь возможность, например, написать функцию Sum по-разному, и чтобы в ForEachDo могла работать с любым вариантом этой функции. Мы же не о частной задаче ведём речь, а о достижении определённого уровня общности.


 
oxffff ©   (2008-05-08 10:36) [184]


> Григорьев Антон ©   (08.05.08 10:20) [183]

> Абсолютно верно, всё зависит от внутреннего кода функции.
>  Именно из этого я и делаю вывод о том, что ответственность
> за безопасную работу с array of const лежит на авторе функции,
>  а не на том, кто её потом использует.
>


Да почему же, автор функции может не знать о других переданных параметрах и объектах (в котором могут быть поля). и поэтому может финализировать управляемые ссылки на объекты кучи вызвав Weak reference
в const массиве.

Поэтому безопасность целиком ложится на вызывающего поскольку именно он должен обеспечить корректность переданных параметров.
А также он ответственен за них из-за потоков, которые также могут иметь к ним доступ.

P.S.

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


> А это как напишете, так и будет. Так как стоит задача добиться
> "того же уровня общности", то мы должны иметь возможность,
>  например, написать функцию Sum по-разному, и чтобы в ForEachDo
> могла работать с любым вариантом этой функции. Мы же не
> о частной задаче ведём речь, а о достижении определённого
> уровня общности.


Что должно получится из примера?


 
DiamondShark ©   (2008-05-08 12:23) [185]

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


 
никто   (2008-05-09 14:07) [186]

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


 
ага   (2008-05-09 14:16) [187]

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


 
Ketmar ©   (2008-05-09 14:29) [188]

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


 
ага   (2008-05-09 14:35) [189]

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


 
Ketmar ©   (2008-05-09 14:52) [190]

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


 
ага   (2008-05-09 15:45) [191]

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


 
Ketmar ©   (2008-05-09 15:50) [192]

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


 
ага   (2008-05-09 15:58) [193]

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


 
oxffff ©   (2008-05-10 12:02) [194]

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


 
Ketmar ©   (2008-05-12 05:58) [195]

> oxffff ©   (10.05.08 12:02) [194]
к твоему огромному сожалению, «секу». как в Delphi, так и в LISP. только в глупый и заранее проиграный тобой спор не ввязываюсь — неинтересно. и kpmc лениво назад на рабочий откатывать.


 
Григорьев Антон ©   (2008-05-12 08:54) [196]


> oxffff ©   (08.05.08 10:36) [184]
> Что должно получится из примера?

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

Вот только, насколько я помню Лисп (если помню неправильно, пусть знающие товарищи поправят), в нём нельзя писать функции, которые могут принимать на вход и атомы (т.е. простые значения), и списки. Поэтому с вашим списком [ [1,2,3],[4,5,6], [7,8,9,],10, [11,12,[13,14]],] работать ничего не должно, т.к. на первых трёх итерациях ForEachDo отправит в переданную ей функцию список, а на четвёртой - атом.

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


 
oxffff ©   (2008-05-12 08:58) [197]


> Ketmar ©   (12.05.08 05:58) [195]
> > oxffff ©   (10.05.08 12:02) [194]
> к твоему огромному сожалению, «секу». как в Delphi, так
> и в LISP. только в глупый и заранее проиграный тобой спор
> не ввязываюсь — неинтересно


Есть подозрение, что ты не только не сечешь в теме, но и не внимательный.
Мой конкретный спор был про реализацию функции принимающей различные типы.
А не про реализацию идентичного с LISP синтаксиса.

Хотя я также не вижу особых преград для реализации например суммы списков в списках, но повторяю, что для поддержания LIFETIME при использования TvarRec придется использовать явные вызовы _Addref при возврате.
А при использовании variant можно реализовать без явного вызова _Addref,
но только для тех объектов кучи, корни которых являются переменными программы, то есть без корней в других объектах кучи.  

P.S. Говорить можешь все, что угодно. :)
Можем продолжить дискуссию, но поскольку я не знаю LISP, то спрашиваю у тебя, что получится из oxffff  [182].


 
oxffff ©   (2008-05-12 09:03) [198]


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


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


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


Ну не беда нам ничего не мешает проводить анализ VarType на наличие только атомов (не VariantArray) или только списков (VariantArray). :)
Поэтому продолжаю считать, что технически это возможно.


 
oxffff ©   (2008-05-12 09:07) [199]


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


Рабочая функция - указатель на которую мы передадим в ForEach, будет принимать только Leaf списки, разбор на которые будет произведет в ForEach. :)


 
Григорьев Антон ©   (2008-05-12 10:25) [200]


> oxffff ©   (12.05.08 09:03) [198]
> Я еще раз в повторяю, что я этого не утверждал и не брался
> за это. :)
> Я брался за реализацию функции принимающей различые типы.

В таком случае продолжать разговор не имеет смысла. Всё, что я писал о невозможности реализации в Delphi, я писал в контексте фразы Alkid ©   (05.05.08 15:21) [42] В рамках такой общности, как в Лисп - нет. Если вы сами говорите, что не брались доказывать возможность реализации с той же общностью, то спор становится бессмысленным, потому что частные решения вполне возможны, и я уже не раз говорил об этом.



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

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

Наверх





Память: 0.96 MB
Время: 0.061 c
2-1211854505
AlekseyB
2008-05-27 06:15
2008.06.22
DBGRID


2-1212076413
Сергей
2008-05-29 19:53
2008.06.22
Как создать onClick для PopupMenu, созданного программно?


2-1211574528
Otz
2008-05-24 00:28
2008.06.22
Записи в DBGrid


15-1210213823
Slider007
2008-05-08 06:30
2008.06.22
С днем рождения ! 8 мая 2008 четверг


2-1211867426
ab1e
2008-05-27 09:50
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
Английский Французский Немецкий Итальянский Португальский Русский Испанский