Конференция "Прочее" » Лисп
 
  • jack128_ (07.05.08 10:04) [160]

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

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


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


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

    PS если бы по умолчанию в дельфи было принято cdecl, а не register, то тогда, может быть, у нас бы были сишные переменные параметры.  А так - имеем, то что имеем. поддержку varargs только для внешних функций...
  • Игорь Шевченко © (07.05.08 10:13) [161]
    jack128_   (07.05.08 10:04) [160]


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


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


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


    Женя, я тебе страшную тайну открою - не все параметры укладываются в 4 байта.
  • jack128_ (07.05.08 13:23) [162]

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

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


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

    не понял к чему это?? к array of const vs. array of Variant ??  Можно чуть более развернуто?
  • oxffff © (07.05.08 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 не бы увеличен клиентом до передачи и нужно ли мне это делать?

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

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

    см. выше
  • Игорь Шевченко © (07.05.08 14:02) [164]
    jack128_   (07.05.08 13:23) [162]


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


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


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


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

    Твои действия ?
  • jack128_ (07.05.08 14:12) [165]

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

    асм рулит :-D

    Игорь, тебе для чего ПЧП нужно???  Для совместимости с сями или само по себе??  а то ведь в разных языках есть много всяких фишек, которых нет в дельфи. И все их невозможно реализовать.
  • Игорь Шевченко © (07.05.08 14:28) [166]
    jack128_   (07.05.08 14:12) [165]


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


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


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


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


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


    Ну так о чем и шла речь. А ты про array of const
  • Григорьев Антон © (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.

    > Представьте себе, если я увеличу счетик клиентов строки
    > на 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 © (07.05.08 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 © (07.05.08 16:06) [169]

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


    Расскажите, что вы не можете сделать?
  • Григорьев Антон © (07.05.08 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 © (07.05.08 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 © (07.05.08 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.


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

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

    НО!!!

    Поэтому с вашего позволения мне нужно какое то время для выполнения ваших новых требований для списков в списках.
    Я пострараюсь вам предложить решение вечером.
    Чисто из спортивного интереса.
  • Григорьев Антон © (07.05.08 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 © (07.05.08 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 произвольную функцию без обёртки, а это входило
    > в условие задачи.
    >
    > Кстати, я уже в каком сообщении напоминаю вам про передачу
    > функций без обёртки, а вы это вообще никак не комментируете.
    >  Как я должен это понимать? Как то, что вы понимаете безнадёжность
    > этой затеи и пытаетесь замолчать её?
    >
    > > Я пострараюсь вам предложить решение вечером.
    > > Чисто из спортивного интереса.
    >
    > Постарайтесь. Только про произвольные функции без обёртки
    > не забудьте.
  • Игорь Шевченко © (07.05.08 20:07) [175]
    oxffff ©   (07.05.08 19:42) [174]

    В FIDO было наказание за оверквотинг. Не стоит злоупотреблять
  • Григорьев Антон © (07.05.08 20:25) [176]

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


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

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

    "Не стоит указывать другим участникам на несоответствие их сообщений данным Правилам. Если Вы считаете, что чье-то сообщение не соответствует Правилам, пошлите сообщение модератору данного форума или (при отсутствии модератора) администратору. "
    http://www.delphimaster.ru/forums.shtml#rule
  • oxffff © (07.05.08 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 и предоставляю к ней доступ пользователю вместо той которая не видна для пользователя (статический массив который создает компилятор) является причной всех бед мне не понятен. Почему?

    Пользователь имеет такие же шансы сделать "ссылку недействительной" в самой процедуре. И пользоваться ей.
 
Конференция "Прочее" » Лисп
Есть новые Нет новых   [134435   +11][b:0.001][p:0.001]