• AEN (02.05.08 21:46) [0]
    А как вы относитесь к языку Lisp? Освоил за один день... Показался самым нормальным языком... По логичности и структурности получше, чем Pascal и C...
  • TUser © (02.05.08 21:47) [1]
    Говорят, там так
    ))))))))))))))))))))))))))))))))))))))))

  • Morgan (02.05.08 21:54) [2]
    За один день? Вообще-то, знать лисп и уметь программировать на лиспе это немного разные вещи.

    Ситуация такая, что production software на нем сложно писать из-за бедности библиотеками промышленного уровня, по сравнения с тем же C++ (во всяком случае, для свободных имплементаций, в платные встроено много enterprise причиндалов, и для серверной стороны вполне подойдет).
  • DrPass © (02.05.08 23:35) [3]

    > А как вы относитесь к языку Lisp? Освоил за один день..

    Осваивай лучше камасутру - куда более полезная вещь, чем Lisp
  • Тимохов (03.05.08 00:06) [4]
    прикольно, я полгода читал про функциональные языки, так и не понял до всей глубины, а он за один день.

    талант, видимо.
  • Германн © (03.05.08 02:08) [5]

    > Тимохов   (03.05.08 00:06) [4]
    >
    > прикольно, я полгода читал про функциональные языки, так
    > и не понял до всей глубины, а он за один день.
    >
    > талант, видимо.
    >

    Дим. А сколько ты потратил на первый свой вариант "Hello World"? Наверняка меньше одного дня. :)
  • Джо © (03.05.08 05:42) [6]
    >
    >
    > [0] AEN   (02.05.08 21:46)
    > А как вы относитесь к языку Lisp?

    Вразумительно.


    > Освоил за один день

    Маладес.


    > По логичности и структурности получше, чем Pascal и C...

    После дня знакомства с Lisp'ом и не такое почудится может.
  • Ketmar © (03.05.08 13:14) [7]
    я фигею, дорогая редакция. с такой сменой нам всем пора на свалку истории. строем.
  • lerkin (03.05.08 19:24) [8]
    где метла?
  • _ShaggyDoc (03.05.08 19:37) [9]
    Ну, вот я "отношусь" к Lisp. Лет 20 на нем программирую. И лет 25-30 на Pascal.

    Lisp действительно особый язык. Принципиально отличающийся от императивных языков типа Pascal, C и т.п.  Насчет "логичности" могу согласиться, насчет "структурности" - дело спорное. Да и логика бывает разная.

    Однако после 20 лет работы в нем я не рискну сказать, что "освоил". Lisp можно понять действительно за день (или не понять никогда). Вот если "понял", прочувствовал - тогда можно и начинать осваивать.

    Абсолютно бессмысленно противопоставлять Lisp другим языкам. Да, я могу в одной строчке Lisp написать с помощью только самых базовых функций языка то же самое, что потребует нескольких страниц на Delphi. Ну и что? Я с удовольствием пишу в Delphi. Или вынужден с удовольствием писать. Для каждого языка (а более - для среды програмирования) есть своя ниша. Увы, для Lisp она достаточно ограничена.

    Хотя встречаются и в "мире Лиспа" экстремисты, пишущие в Интернет опусы с названием, например, "Скажи нет субд" (именно маленькими буковками) - дескать, ассоциированный список в LISP лучше любой базы данных. Но это для медиков повод познакомиться.

    Возможно и Pascal остался бы замечательным "языком для обучения", придуманным Виртом, если бы не появилась среда Turbo Pascal, а затем и Delphi. А вот для Lisp сопоставимого по качеству хотя бы с TP 3.0 так и не появилось.

    Цитирую из своей книги (где я тоже цитировал кого-то)

    > Существует мнение, что "перепиши хакеры из MIT, Стэнфорда
    > и Карнеги-Меллонского университета ITS на LISP, вся история
    > пошла бы в другую сторону, и открытыми системами мы называли
    > бы, скорее всего, не потомков Unix, а потомков ITS".

    Справка - ITS (Incompatible Timesharing System) - это ОС для мини-компьютеров PDP-10.

    Но этого не случилось, и LISP остался языком для "гурманов", применяется в отдельных направлениях (например, в AutoCAD). Но зато появился C и ему подобные. Что совсем даже не плохо.

    >AEN  

    Незачем вылезать на форум "Дельфинов" с провокационными темами. Приходи хотя бы на DWG.RU, там и разберемся, насколько "освоил". :)

    Сумей, например, объяснить, что делает выражение
    (apply 'mapcar (cons 'list lst))


    и десяток каких именно страниц на Pascal оно может заменить. Тогда и можно будет скромно написать - "начал осваивать".
  • Тимохов (03.05.08 22:05) [10]
    я вообще, когда читал про функц. языки понимал, что это красота неземная :)

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

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

    -----------

    как разработчик (программист + думать приходится) могу сказать, что для мат. моделирования функциональные языки - это вещь. вот только, уверен, пока они не сравняться с изобретательностью чел. разума в области оптимизации вычислений.
  • Ketmar © (03.05.08 22:10) [11]
    > дескать, ассоциированный список в LISP лучше любой базы
    > данных.

    ну, не то, чтобы любой, но очень часто таки лучше.

    > А вот для Lisp сопоставимого по качеству хотя бы с TP 3.
    > 0 так и не появилось.

    оно таки да, подобного убожества нет. есть emacs и целая куча Common Lisp'ов, например. DrScheme/MzScheme. и ты пы. ты это, выйди из пещеры, в гугль сходи, что ли…

    > Сумей, например, объяснить, что делает выражение
    > (apply 'mapcar (cons 'list lst))

    глючит? кто такая lst?
  • Morgan (04.05.08 10:53) [12]
    > (apply 'mapcar (cons 'list lst))

    Может быть,  имелось в виду

    (apply 'mapcar (cons 'list (list lst)))
    ?
  • oldman © (04.05.08 11:13) [13]

    > AEN   (02.05.08 21:46)  
    > А как вы относитесь к языку Lisp? Освоил за один день...
    >  


    В далеком 1993 я за день перешел с Basic на Clipper. Имея в своем распоряжении только хелп по синтаксису.

    Сие значит, что Clipper лучше Basic?
  • Anatoly Podgoretsky © (04.05.08 14:12) [14]
    > oldman  (04.05.2008 11:13:13)  [13]

    Клиппер в основе ФоксПро.
    Они одинаковые, оба интерпритаторы в основе. С похожим свободным (бейсик более свободен) языком.
    Поэтому они очень легко осваиваются, надо под рукой иметь только справку, лучше OnLine
  • _ShaggyDoc (04.05.08 22:05) [15]
    >Ketmar ©   (03.05.08 22:10) [11]
    >> дескать, ассоциированный список в LISP лучше любой базы
    >> данных.
    >ну, не то, чтобы любой, но очень часто таки лучше.

    Список - это все-таки данные в памяти, и это совсем не СУБД и даже не простенький плоский DBF-файл.

    Списки в памяти обрабатывать через LISP действительно удобнее всего - для того язык и придуман.

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

    Повернись история иначе, можно было бы и HTML и XML не придумывать - все, что там есть, можно выразить через LISP.

    > есть emacs и целая куча Common Lisp'ов, например. DrScheme/MzScheme. и ты пы. ты это, выйди из пещеры, в гугль сходи, что ли…

    "Хамишь, парниша" (C) Людоедка Эллочка.

    Зачем мне "в гугль" ходить, я же написал, что 20 лет в LISP работаю и конечно, слежу за его инструментами. И всяких "ты пы" у меня и на машине установлено.

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

    А в "пещерах" сидят язычники, которые поклоняются своим божкам и не желают оглянуться на окружающий мир. Людодке Эллочке
    нельзя объяснять, что ее "мексиканский тушкан" всего лишь крашеная акварелью собачья шкура. Сожрет.

    По поводу приведенного кода. Там все правильно. lst - это обрабатываемый список. Будет понятнее, если оформить в виде функции

    (defun ru-list-Douglas-Wilson-transpose (lst)
     (apply 'mapcar (cons 'list lst))
    )



    Алгоритм придумал Douglas Wilson.

    Эта функция транспонирует элементы списка списков - например, перевернуть содержимое, полученное при чтении базы данных

    Пример:
    (ru-list-Douglas-Wilson-transpose
    (list
     (list "ПОЛЕ1_ЗАПИСЬ1" "ПОЛЕ1_ЗАПИСЬ2" "ПОЛЕ1_ЗАПИСЬХ")
     (list "ПОЛЕ2_ЗАПИСЬ1" "ПОЛЕ2_ЗАПИСЬ2" "ПОЛЕ2_ЗАПИСЬХ")
     (list "ПОЛЕ3_ЗАПИСЬ1" "ПОЛЕ3_ЗАПИСЬ2" "ПОЛЕ3_ЗАПИСЬХ")
    )
    )

    Вернет
    (
     ("ПОЛЕ1_ЗАПИСЬ1" "ПОЛЕ2_ЗАПИСЬ1" "ПОЛЕ3_ЗАПИСЬ1")
     ("ПОЛЕ1_ЗАПИСЬ2" "ПОЛЕ2_ЗАПИСЬ2" "ПОЛЕ3_ЗАПИСЬ2")
     ("ПОЛЕ1_ЗАПИСЬХ" "ПОЛЕ2_ЗАПИСЬХ" "ПОЛЕ3_ЗАПИСЬХ")
    )



    И наоборот:

    (ru-list-Douglas-Wilson-transpose
    (list
     (list "ПОЛЕ1_ЗАПИСЬ1" "ПОЛЕ2_ЗАПИСЬ1" "ПОЛЕ3_ЗАПИСЬ1")
     (list "ПОЛЕ1_ЗАПИСЬ2" "ПОЛЕ2_ЗАПИСЬ2" "ПОЛЕ3_ЗАПИСЬ2")
     (list "ПОЛЕ1_ЗАПИСЬХ" "ПОЛЕ2_ЗАПИСЬХ" "ПОЛЕ3_ЗАПИСЬХ")
    )
    )



    Вернет
    (
     ("ПОЛЕ1_ЗАПИСЬ1" "ПОЛЕ1_ЗАПИСЬ2" "ПОЛЕ1_ЗАПИСЬХ")
     ("ПОЛЕ2_ЗАПИСЬ1" "ПОЛЕ2_ЗАПИСЬ2" "ПОЛЕ2_ЗАПИСЬХ")
     ("ПОЛЕ3_ЗАПИСЬ1" "ПОЛЕ3_ЗАПИСЬ2" "ПОЛЕ3_ЗАПИСЬХ")
    )



    Здесь не ограничено количество полей и записей, нет циклов, использованы только базовые функции apply, mapcar, cons и list, да "симовл квотирования" - апостроф.

    Попробуйте сделать подобное таким минимумом штатных средств другого языка. А это - LISP!
  • Palladin © (04.05.08 22:26) [16]
    где вы блин раньше были... я вот буквально недавно интересовался по поводу реализации быстрой сортировки в лиспе...
  • Пробегал2... (05.05.08 00:47) [17]
    _ShaggyDoc   (03.05.08 19:37) [9]
    Сумей, например, объяснить, что делает выражение
    (apply 'mapcar (cons 'list lst))


    а что делает это выражение, что нужно заменить десятком страниц на Delphi?

    Anatoly Podgoretsky ©   (04.05.08 14:12) [14]
    надо под рукой иметь только справку, лучше OnLine


    а чем это справки онлайн стали лучше офлайн?

    _ShaggyDoc   (04.05.08 22:05) [15]
    использованы только базовые функции apply, mapcar, cons и list, да "симовл квотирования" - апостроф


    я не понимаю. Ну а я на Delphi могу использовать какую-нибудь DLL или .PAS юнит, где тоже надо будет дернуть только 1-2 фунции. И что?

    Только то, что в LISP эти функции являются частью языка?
  • Palladin © (05.05.08 01:05) [18]

    >Только то, что в LISP эти функции являются частью языка?


    да. логика используемого (избранного тобой как основной, любимый, несравненый) языка очень сильно влияет на мышление. ты даже не представляешь на сколько сильно. мне очень очень сложно мыслить в рамках перла например. в рамках лиспа еще сложней. подсознание пытается построить процедурное, не списочное, решение. а в чужой монастырь сотсвои уставом не лезут.
  • Anatoly Podgoretsky © (05.05.08 01:33) [19]
    > Пробегал2...  (05.05.2008 0:47:17)  [17]

    Тем что не надо рыться, поскольку контенстная.
    Ты не путай с Интернетом.
    OnLine значит на ходу, по месту, нажимаешь F1 и сразу в теме.
  • _ShaggyDoc (05.05.08 09:04) [20]

    > Пробегал2...   (05.05.08 00:47) [17]


    > Ну а я на Delphi могу использовать какую-нибудь DLL или
    > .PAS юнит, где тоже надо будет дернуть только 1-2 фунции.
    >  И что?

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

    Или, например, вычисление выражения, написанного в виде исходного текста. Есть такие библиотеки и в Delphi, но реализация их непростая - надо парсить, анализировать и прочее. А в LISP опять же очень просто - всего лишь
    (eval (read expression))



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

    Например, при вызове функции

    (ru-3d-pump-k 320.0 675.0 140.0 670.0 145.0 237.0 700.0 1102.0 395.0 395.0 24.0 0 0.0 0.0 (ru-3d-pipe-flange-std-150-16) (ru-3d-pipe-flange-std-125-16) (ru-3d-electro-motor-160-1001))



    Будет создана 3D-модель насоса с электродвигателем, всеми болтиками, фланцами и прочим - почти как фото. Вызов функции можно встроить в программу более высокого уровня, например для выбора  модели (т.е. аргументов) из базы данных. Но вот работу с БД я лучше сделаю на Delphi - там это можно реализовать гораздо лучше.

    Этот же код, в виде текстового атрибута, у меня вписывается в меню, написанное на XML. Именно на XML, а не в виде LISP-текста (хотя и так можно). Но XML более универсален. И функция для визуальной работы с XML (фактически выбор из древовидной БД), реализована у меня на Delphi, включая парсер XML. Вызов же этой функции осуществляется из LISP.


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


    Сортировка - это не то, что я показал. Это сложнее, займет целую страницу. Правда сейчас в большинстве реализаций LISP сортировка является штатным средством, поэтому к её разработкам охладели. Или студентов ею мучают.

    LISP это как бы иная "цивилизация" с иным образом мышления. Не лучше и не хуже, например, Pascal, а просто иная. В LISP, например, вообще нет операторов, а есть только функции - даже if функция, а не просто "управляющая конструкция". Типы данных есть, но объявлять их не надо. С точки зрения Pascal это ужасно, а в LISP оборачивается преимуществом. На LISP можно писать и "по-бейсиковски", но от этого надо сразу избавляться. Можно вводить переменные, а можно и без них обходиться. Но и LISP заимствует кое-что из "традиционных" языков, например аналог try...except. Или возможность использовать COM-технологии.
  • Григорьев Антон © (05.05.08 09:39) [21]

    > _ShaggyDoc   (05.05.08 09:04) [20]
    >
    >> Сортировка - это не то, что я показал. Это сложнее, займет
    > целую страницу.

    А что так много? На Хаскеле - две строки:

    qsort [] = []
    qsort (x:xs) = qsort (filter (<=x) xs) ++ [x] ++ qsort (filter (>x) xs)



    Неужели в Лиспе это нельзя написать так же кратко?
  • ferr (05.05.08 11:04) [22]
    > Неужели в Лиспе это нельзя написать так же кратко?

    ну не также кратко, но идейно тоже самое написать легко, медленно это очень.
  • тимохов (05.05.08 11:14) [23]
    а вот идеологи функциональных языков говорят, что у ф. языков большие перспективы - были бы интеллектуальные среды выполнения, которые умеют распараллеливать выполенения.

    т.е. типа - пишешь программу, а она сама на кластер раскладывается.
  • ferr (05.05.08 11:17) [24]
    > а вот идеологи функциональных языков говорят, что у ф. языков
    > большие перспективы - были бы интеллектуальные среды выполнения,
    > которые умеют распараллеливать выполенения.
    >
    > т.е. типа - пишешь программу, а она сама на кластер раскладывается.

    Ну так это разьве не очевидно? смотрим на [21] и понимаем что два вызова qsort могут идти на абсолютно любые машины/процессоры т.к. они не вызывают side effect's. Главное чтобы интерпретатор смог сообразить что да куда, а это ведь жутко нетривиально.
  • Ketmar © (05.05.08 11:27) [25]
    > _ShaggyDoc   (04.05.08 22:05) [15]
    > Список — это все-таки данные в памяти, и это совсем не СУБД
    > и даже не простенький плоский DBF-файл.

    take a look at PicoLISP.

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

    ну да, формостроительства и батонокидательства нет. наверное, не надо никому. в остальном — а что, есть что-то мощней emacs? O_O

    > Там все правильно. lst — это обрабатываемый список.
    откуда мне это знать было? может, это убойный макрос вовсе, который в твоём диалекте лиспа во что-то раскрывается в таком виде?

    > Palladin ©   (04.05.08 22:26) [16]
    > где вы блин раньше были… я вот буквально недавно интересовался
    > по поводу реализации быстрой сортировки в лиспе…

    каком именно? например, на многих common lisp категорически воспрещается писать рекурсивную функциональщину. потому что в стандарте нет требования на tail recursion in constant stack space, как в scheme, и люди не озадачиваются реализацией этой штучки.

    > _ShaggyDoc   (05.05.08 09:04) [20]
    > Сортировка — это не то, что я показал. Это сложнее, займет
    > целую страницу.

    ; ArrowLISP Example Program
    ; Copyright © 2005,2006 Nils M Holm. All rights reserved.
    ; See the file LICENSE of the ArrowLISP distribution
    ; for conditions of use.

    ; Sort a list using the Quicksort algorithm:
    ; (require '=nmath)
    ; (qsort <= '
    (#5 #1 #3 #2 #4)) => '(#1 #2 #3 #4 #5)

    (define (qsort p a)
     (letrec

       ((filter (lambda (p a r)
         (cond ((null a) (reverse r))
           ((p (car a))
             (filter p (cdr a) (cons (car a) r)))
           (t (filter p (cdr a) r)))))

       (_qsort (lambda (a)
         (cond ((null a) a)
           (t (letrec
                ((left-part (lambda (x)
                  (lambda (y) (not (p x y)))))
                (right-part (lambda (x)
                  (lambda (y) (p x y)))))
                (append
                  (_qsort (filter
                            (left-part (car a))
                            (cdr a) ()))
                  (list (car a))
                  (_qsort (filter
                            (right-part (car a))
                            (cdr a) ())))))))))

       (_qsort a)))



    > Григорьев Антон ©   (05.05.08 09:39) [21]
    > А что так много? На Хаскеле — две строки
    реализация лиспа: 100 килобайт на C. писана за пару дней. покажите мне такое же для хаскеля. чтобы при этом оно ещё и не тормозило, как квака на старых 486-х.

    помимо прочего — хаскель нифига не применим в качестве скриптового языка. к тому же я его не знаю, и это ему большой минус. %-)
  • Ketmar © (05.05.08 11:31) [26]
    > тимохов   (05.05.08 11:14) [23]
    > т.е. типа — пишешь программу, а она сама на кластер раскладывается.

    абсолютно любой язык, где есть возможность писать код без side effects обладает этим свойством. штука в том, что такие языки — они как раз функциональные.
  • Palladin © (05.05.08 11:35) [27]

    > каком именно? например, на многих common lisp категорически
    > воспрещается писать рекурсивную функциональщину.

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

    помню только что мой вопрос остался без ответа :)
  • Григорьев Антон © (05.05.08 11:43) [28]

    > тимохов   (05.05.08 11:14) [23]
    > а вот идеологи функциональных языков говорят, что у ф. языков
    > большие перспективы - были бы интеллектуальные среды выполнения,
    >  которые умеют распараллеливать выполенения.
    >
    > т.е. типа - пишешь программу, а она сама на кластер раскладывается.
    >

    На эту тему много пишет Jack Of Shadows вот здесь: http://www.delphikingdom.com/asp/talktopic.asp?ID=366 Если покопаться, можно найти интересные ссылки как на теоретические работы, так и на экспериментальные распараллеливающие трансляторы.
  • Пробегал2... (05.05.08 13:54) [29]
    Anatoly Podgoretsky ©   (05.05.08 1:33) [19]
    Ты не путай с Интернетом.
    OnLine значит на ходу


    ну это конечно. У вас как всегда самая актуальная информация насчет значений слов.

    "Онлайн (англ. online, от англ. on line — русск. на линии) — «находящийся в состоянии подключения». Первоначально использовалось только в отношении коммуникационного оборудования для указания на режим связи. В отношении ПО почти всегда означает «подключённый к интернету» или функционирующий только при подключении к интернету. Также — «происходящее в Интернете», «существующее в Интернете». К примеру «онлайн-банкинг», «онлайн-магазин», «онлайн-казино», «онлайн-игра». В этих значениях часто употребляется также прилагательное онлайновый.

    Технические специалисты в отношении применения в русском языке данного заимствованного слова могут сказать, что «термин используется для потребительского описания клиентской части в архитектуре „клиент-сервер“».

    Первоначальное значение — «не вешая трубку», за один телефонный звонок, т. е. в режиме реального времени"


    http://ru.wikipedia.org/wiki/Online

    _ShaggyDoc   (05.05.08 9:04) [20]
    Только надо, чтобы эти функции, которые можно "дернуть", кто-то разработал


    конечно. Также как кто-то должен был разработать компилятор LISP'а

    _ShaggyDoc   (05.05.08 9:04) [20]
    Можно и самому написать, но с тем же транспонированием придется изрядно поработать, привлекая еще какие-то библиотеки. А тут полстрочки.


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

    _ShaggyDoc   (05.05.08 9:04) [20]
    Или, например, вычисление выражения, написанного в виде исходного текста. Есть такие библиотеки и в Delphi, но реализация их непростая - надо парсить, анализировать и прочее


    Ну опять же можно подумать, что реализация компилятора LISP'а простая? Там будто нету парсинга, анализа и прочего?

    _ShaggyDoc   (05.05.08 9:04) [20]
    Кроме того, на LISP также пишут собственные библиотеки, фактически создавая расширение языка


    вот тут я вообще прифигел. На самом деле на других языках точно также можно писать свои библиотеки. И допустим под windows есть даже стандарт таких библиотек - DLL, который позволяет использовать библиотеку, написанную на другом языке.
  • Alkid © (05.05.08 13:56) [30]

    > А как вы относитесь к языку Lisp? Освоил за один день...
    >  Показался самым нормальным языком... По логичности и структурности
    > получше, чем Pascal и C...

    А ты какой Лисп изучил? Фишка в том, что сейчас нет "просто" Лиспа, есть Common Lisp и Scheme + разные другие диалекты.
  • Palladin © (05.05.08 13:58) [31]

    > Alkid ©   (05.05.08 13:56) [30]

    фишка в том, что он его изучил по "Lisp для чайников за 24 часа"... как и Pascal и C...
  • Alkid © (05.05.08 14:06) [32]

    > фишка в том, что он его изучил по "Lisp для чайников за
    > 24 часа"... как и Pascal и C...

    Мда уж.
    Я, вот, Prolog не так давно *начал* изучать.  Понимание того, как это работает пришло на третьем прочтении вводного курса. До этого было "понятно" на уровне "ага, утверждения, правила вывода, унификация, всё просто". А потом как прозрел - так стыдно стало.

    Сейчас, кстати, активно штудирую книгу Пола Грэхэма "Onlisp".  Специально к автору топика - почитай, увидишь, как ты "изучил" Lisp :)
  • Игорь Шевченко © (05.05.08 14:08) [33]
    Пробегал2...   (05.05.08 13:54) [29]


    > Ну опять же можно подумать, что реализация компилятора LISP'а
    > простая? Там будто нету парсинга, анализа и прочего?


    Видишь ли, в компиляторе Delphi тоже есть анализ, парсинг и прочая хрень, а вот готовой функции, которая выражение вычисляет, нету...
  • Пробегал2... (05.05.08 14:26) [34]
    Игорь Шевченко ©   (05.05.08 14:08) [33]
    Видишь ли, в компиляторе Delphi тоже есть анализ, парсинг и прочая хрень, а вот готовой функции, которая выражение вычисляет, нету...


    так и я об этом. LISP получается "уникален" только тем, что в него встроена куча готовых функций математических. И все?

    Я не знаю на каком языке написан LISP, но если этот язык умеет компилировать DLL, то в принципе получается, что при определенном подходе можно сделать кучу готовых DLL с богатыми экспортными функциями LISP'а, после чего на любом языке можно будет программировать под LISP.
  • Alkid © (05.05.08 14:47) [35]

    > так и я об этом. LISP получается "уникален" только тем,
    > что в него встроена куча готовых функций математических.
    >  И все?

    Сорри за нескромный вопрос - насколько глубоко Вы Lisp знаете?
    Что Вы о нём читали, писали ли программы?

    Если брать дифференцированное описание от дельфи, то в лиспе есть:
    1. Макросы (не путать с C/C++ макросами), позволяющие почти произвольным образом расширять язык.
    2. Первоклассные функции и функции высшего порядка.
    3. Замыкания
    4. (в Схеме) первоклассные продолжения. Мне, кстати, схема этим оч-чень нравится. При помощи продолжений так очень классно реализуюте недетерминистические алгоритмы. :)

    Это, ИМХО, основное.

    P.S. mapcar - это совсем не математическая функция. Прочитайте про неё и попробуйте сделать то же самое на Delphi.
  • Григорьев Антон © (05.05.08 14:49) [36]

    > Пробегал2...   (05.05.08 14:26) [34]

    Прежде чем делать такие заявления, может, стоит немного познакомиться с функциональным подходом? Вот, очень рекомендую: http://www.lib.ru/CTOTOR/FUNCPROG/

    А вот небольшой и неполный список того, что есть в функциональных языках и что никакой DLL не сделать:
    1. Сопоставление аргумента шаблону
    2. Функции высших порядков и анонимные функции
    3. Карринг функций
    4. Передача аргументов по имени, ленивые вычисления.

    Не всё это есть в Лиспе (ленивых вычислений точно нет, карринга, кажется, тоже), но его всё равно просто так к императивному языку не прикрутишь.
  • Игорь Шевченко © (05.05.08 14:51) [37]
    Пробегал2...   (05.05.08 14:26) [34]


    > Я не знаю на каком языке написан LISP


    А на каком языке написан С++ ?
  • Alkid © (05.05.08 15:13) [38]

    > 1. Сопоставление аргумента шаблону

    Кстати, а разе в CL или Scheme есть паттерн-матчинг?  Я стандарт подразумеваю, прикрутить макросами его можно - это ясно.
  • Пробегал2... (05.05.08 15:13) [39]
    Alkid ©   (05.05.08 14:47) [35]
    Сорри за нескромный вопрос - насколько глубоко Вы Lisp знаете?


    вообще никак.

    Alkid ©   (05.05.08 14:47) [35]
    Что Вы о нём читали, писали ли программы?


    ничего не читал, ничего не писал и не собираюсь. Но заинтересовала эта тема.

    Alkid ©   (05.05.08 14:47) [35]
    mapcar - это совсем не математическая функция. Прочитайте про неё и попробуйте сделать то же самое на Delphi


    вы хотите сказать, что на дельфи этого сделать невозможно? не понимаю.
    Это ведь очевидно не комманда для процессора, а соответственно она как-то должна быть разложена в комманды для процессора. И в компиляторе (интерпритаторе?) LISP'а эти преобразования делаются. Почему же в дельфи их нельзя сделать?

    Ведь в LISP'е (который написан наверняка не на LISP'е) этого же сделали?

    Игорь Шевченко ©   (05.05.08 14:51) [37]
    А на каком языке написан С++ ?


    если вы решили поиграть в придирки к словам - то замечу, что я имел в виду "Я не знаю на каком языке написан компилятор/интерпритатор LISP'а"
  • Alkid © (05.05.08 15:14) [40]

    > А на каком языке написан С++ ?

    На английском!
    :)
  • Григорьев Антон © (05.05.08 15:20) [41]

    > Alkid ©   (05.05.08 15:13) [38]
    > Кстати, а разе в CL или Scheme есть паттерн-матчинг?

    А я не говорил про Лисп, я говорил про функциональный подход вообще. А конкретно Лисп я знаю очень слабо, обзорно, на уровне того, что такое CAR и CDR :)))
  • Alkid © (05.05.08 15:21) [42]

    > ничего не читал, ничего не писал и не собираюсь. Но заинтересовала
    > эта тема.

    Гугль в помощь.
    Советую сайт paulgraham.com, там, помимо прочего, есть интересные заметки о Лисп.
    Вообще, изучать альтернативные языки полезно, даже если не собираешься их применять на практике. Сильно способствует просветлению.
    Так же советую Пролог :)


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

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

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

    > А я не говорил про Лисп, я говорил про функциональный подход
    > вообще. А конкретно Лисп я знаю очень слабо, обзорно, на
    > уровне того, что такое CAR и CDR :)))

    А, понятно.
    Меня, кстати, сейчас логическая парадигма интересует, как обобщение функциональной.
  • Anatoly Podgoretsky © (05.05.08 15:26) [44]
    > Пробегал2...  (05.05.2008 13:54:29)  [29]

    А ты не путай маркетинговые потуги с википедией, но даже там есть пункт "т. е. в режиме реального времени"
    OnLine слово волшебное.им к доктору.
  • Anatoly Podgoretsky © (05.05.08 15:28) [45]
    > Игорь Шевченко  (05.05.2008 14:08:33)  [33]

    Кстати учитывая последнии шаги Борланда я удивлен, а почему нет, а вот IncDay есть.
  • Игорь Шевченко © (05.05.08 15:33) [46]
    Пробегал2...   (05.05.08 15:13) [39]

    Ты эта...прежде чем спорить, про предмет спора почитай малость. Чтобы не оказаться в глупой ситуации.
  • Игорь Шевченко © (05.05.08 15:35) [47]
    Anatoly Podgoretsky ©   (05.05.08 15:28) [45]

    IncDay больше востребован
  • oxffff © (05.05.08 15:36) [48]

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



    А пытался?
  • Palladin © (05.05.08 15:43) [49]

    > oxffff ©   (05.05.08 15:36) [48]

    написать можно, но нафика? :)
  • Григорьев Антон © (05.05.08 15:46) [50]

    > oxffff ©   (05.05.08 15:36) [48]
    > А пытался?

    Но ведь действительно невозможно. В Delphi придётся задавать тип элементов списка и функции на этапе компиляции, а в Лиспе тиипзация будет динамической, что-то вроде шаблона. А самое главное, что если элементы списка имеют разные типы, но к каждому из них функция, переданная в mapcar, применима, тоже всё будет в порядке - такого в Delphi не написать, даже если были бы generic'и.
  • Palladin © (05.05.08 15:47) [51]

    > Григорьев Антон ©   (05.05.08 15:46) [50]


    > В Delphi придётся задавать тип элементов списка и функции
    > на этапе компиляции

    угу и это будет variant
  • oxffff © (05.05.08 15:48) [52]
    type
    TXFUNC=function (const a:TvarRec):TvarRec;

    function abc(var List:array of const;func:TXFUNC):integer;
    var i:integer;
    begin
    for i:=0 to length(List)-1 do LIST[i]:=func(LIST[i]);
    end;

    function XSample(const a:TvarRec):TvarRec;
    begin

    end;

    procedure TForm1.Button1Click(Sender: TObject);
    var a:array of TVarRec;
    begin
    abc(A,XSample);
    end;

    И это не предел. Если хорошо отштудировать систему типов Delphi.
    То можно динамически добавлять типы.
    Но об этом позже, если эти аргументы будут востребованы.  

    ЗЫ. решения есть еще. и не одно.
  • oxffff © (05.05.08 15:49) [53]

    > Григорьев Антон ©   (05.05.08 15:46) [50]


    Нужно лучше знать Delphi. И вопросов будет меньше.
  • oxffff © (05.05.08 15:50) [54]

    > Григорьев Антон ©   (05.05.08 15:46) [50]
    >
    > > oxffff ©   (05.05.08 15:36) [48]
    > > А пытался?
    >
    > Но ведь действительно невозможно. В Delphi придётся задавать
    > тип элементов списка и функции на этапе компиляции, а в
    > Лиспе тиипзация будет динамической, что-то вроде шаблона.
    >  А самое главное, что если элементы списка имеют разные
    > типы, но к каждому из них функция, переданная в mapcar,
    > применима, тоже всё будет в порядке - такого в Delphi не
    > написать, даже если были бы generic'и.


    Как у вас с ООП?
  • oxffff © (05.05.08 15:51) [55]

    > Григорьев Антон ©   (05.05.08 15:46) [50]
    >
    > > oxffff ©   (05.05.08 15:36) [48]
    > > А пытался?
    >
    > Но ведь действительно невозможно. В Delphi придётся задавать
    > тип элементов списка и функции на этапе компиляции, а в
    > Лиспе тиипзация будет динамической, что-то вроде шаблона.
    >  А самое главное, что если элементы списка имеют разные
    > типы, но к каждому из них функция, переданная в mapcar,
    > применима, тоже всё будет в порядке - такого в Delphi не
    > написать, даже если были бы generic'и.


    Далее по тексту? Читали ли мы TcustomVariant?
    Это кстати другое решение.
    Еще есть два мощнейших и простых наследника у него.
    Но это к вопросу о расширениии языка.
  • Alkid © (05.05.08 15:54) [56]

    >
    > И это не предел. Если хорошо отштудировать систему типов
    > Delphi.
    > То можно динамически добавлять типы.
    > Но об этом позже, если эти аргументы будут востребованы.


    Супер. И как мне стандартную функцию sin(x:double) тут заюзать? :)
  • Anatoly Podgoretsky © (05.05.08 15:54) [57]
    > Игорь Шевченко  (05.05.2008 15:35:47)  [47]

    Все правильно, более приоритетен, а у Eval пока недостаточный приоритет, иконку, которая там, тоже не сразу сделали.
  • Palladin © (05.05.08 15:58) [58]

    > oxffff ©

    ты эта :) не нервничай... подобие реализовать можно, но ограничено... именно так как в лиспе - не выйдет...
  • oxffff © (05.05.08 15:59) [59]

    > Palladin ©   (05.05.08 15:58) [58]


    Я эта не нервничаю. Ежели что. :)
  • Игорь Шевченко © (05.05.08 16:02) [60]
    oxffff ©   (05.05.08 15:51) [55]

    А нафига Codegear в язык добавляет Generic-и ? Если все так просто можно сделать и без них...
  • тимохов (05.05.08 16:02) [61]
    что же ты все, сергей, на личности переходишь...
  • oxffff © (05.05.08 16:06) [62]
    Alkid ©
    Я даже боюсь сказать о том, что синтаксис можно сокрашить до.
    var a:variant;
    begin

    a.sin;
  • oxffff © (05.05.08 16:07) [63]

    > тимохов   (05.05.08 16:02) [61]


    Рад слышать.
    Где?
  • oxffff © (05.05.08 16:09) [64]

    > oxffff ©   (05.05.08 16:06) [62]


    Более того эту конструкцию можно даже расширить.

    function abc(a:variant;funcName:string);
    c вызовом abc(a,'sin');

    ЗЫ. Читаем справку по Delphi.
  • Ketmar © (05.05.08 16:13) [65]
    2oxffff: ну и что ты пытаешься доказать? что в конце концов всё спускается к машинному коду, и что реализуемо на одном turing-complete, то можно и на другом реализовать? можно. баян. лучше спроси у лисперов, как сделать статическую (или хотя бы динамическую) проверку типов без изменения интерпретатора — и будете в рассчёте.
  • Игорь Шевченко © (05.05.08 16:14) [66]
    И вообще все можно написать на ассемблере. Только долго.
  • oxffff © (05.05.08 16:20) [67]

    > Игорь Шевченко ©   (05.05.08 16:02) [60]
    > oxffff ©   (05.05.08 15:51) [55]
    >
    > А нафига Codegear в язык добавляет Generic-и ? Если все
    > так просто можно сделать и без них...


    В том то и дело. То о чем говорю я это будет динамика.
    Поэтому этот тип фактически является оберткой над реальным типом.
    Это может быть например TvarRec, TvarData , Объект, и надо подумать на чем еще построить.

    Что касаемо generics. То это статика. Поэтому вызов будет проверяться в compile time.
    А если нацеплен constraint (а я думаю что  delphi Win32 будет поддерживать концепцию .NET generics, а не С++ templates).
    Но честно говоря характеристики Win32 generics не известны.
  • oxffff © (05.05.08 16:28) [68]

    > Ketmar ©   (05.05.08 16:13) [65]
    > 2oxffff: ну и что ты пытаешься доказать?


    Где?
    Я только хочу сказать, что если надо, то задача решаема.
    И достаточно просто. И при желании. До простого синтаксиса.

    [62],[64]

    Кто короче?
  • oxffff © (05.05.08 16:36) [69]

    > Игорь Шевченко ©   (05.05.08 16:02) [60]
    > oxffff ©   (05.05.08 15:51) [55]
    >
    > А нафига Codegear в язык добавляет Generic-и ? Если все
    > так просто можно сделать и без них...


    Можно.
    Но не забываем что нам на всех форумах представители С++ сообщества ставят в укор. А любят они тыкать нас носом на шаблонную сортировку.
    И заслуженно кстати. Любая операция с динамическим анализом и преобразованием занимает время. Поэтому в скорости мы проигрываем.
    И пока мы пишем код для разных типов для сопоставимых результатов с С++, они уже решают другие задачи.
  • Григорьев Антон © (05.05.08 16:36) [70]

    > oxffff ©   (05.05.08 15:48) [52]
    > type
    > TXFUNC=function (const a:TvarRec):TvarRec;
    >
    > function abc(var List:array of const;func:TXFUNC):integer;
    >
    > var i:integer;
    > begin
    > for i:=0 to length(List)-1 do LIST[i]:=func(LIST[i]);
    > end;
    >
    > function XSample(const a:TvarRec):TvarRec;
    > begin
    >
    > end;
    >
    > procedure TForm1.Button1Click(Sender: TObject);
    > var a:array of TVarRec;
    > begin
    > abc(A,XSample);
    > end;

    Не компилируется abc([1,'a', 2], XSample), т.е. константный список кушать не хочет. В Лиспе с этим проблем нет. Я уж молчу о том, что чтобы правильно сформировать содержимое массива a, надо будет повозиться с полями TVarRec, что очень неудобно. Полиморфизм функции XSample тоже не так просто сделать.

    > oxffff ©   (05.05.08 15:50) [54]
    > Как у вас с ООП?

    Видимо, очень плохо. Потому что не представляю, при чём вообще ООП, когда я хочу выполнить простые операции над типами integer, real, char и т.п.

    > oxffff ©   (05.05.08 15:51) [55]
    > Далее по тексту? Читали ли мы TcustomVariant?
    > Это кстати другое решение.

    Да, читали. Но TCustomVariant - это всё-таки не элементарный тип, а обеспечивать полиморфизм на уровне простых типов Delphi не умеет.

    > oxffff ©   (05.05.08 16:06) [62]
    > Я даже боюсь сказать о том, что синтаксис можно сокрашить
    > до.
    > var a:variant;
    > begin
    >
    > a.sin;

    Написал такую проверку:
    procedure TForm1.Button1Click(Sender: TObject);
    var v:Variant;
    begin
     v:=0;
     v.Sin(0)
    end;


    Получил ожидаемый результат - исключение в строке с синусом. Потому что такие фокусы проходят только когда v содержит указатель на IDispatch, т.е. простые типы опять пролетают как фанера над Парижем. Ответ насчёт стандартной функции sin не засчитывается.
  • Григорьев Антон © (05.05.08 16:40) [71]

    > oxffff ©   (05.05.08 16:28) [68]
    > Я только хочу сказать, что если надо, то задача решаема.

    Решаема. Можно вообще написать на Delphi библиотеку - интерпретатор Лиспа и делать что-то вроде
    a := LispEval('(apply 'mapcar (cons 'list lst))');


    Совсем короткий синтаксис получится :)
  • Игорь Шевченко © (05.05.08 16:42) [72]
    oxffff ©   (05.05.08 16:20) [67]

    Мне будет крайне интересна передача классов в иерархии через TVarRec

    type
     TFooBase = class
     public
        procedure SomeMethod (Param: TParam); virtual;
     end;

     TFoo = class(TFooBase)
     ...
     end;
     TBar = class(TFoo)
     ...
     public
        procedure SomeMethod (Param: TParam); override;
     end;

    То есть, при generic-ах я могу написать

     type
       TFooList = TList<TFoobase>
       public
        ...
         procedure ApplySomeMethod (Param: TParam);
       end;

    procedure TFooList.ApplySomeMethod (Param: TParam);
    var
     I: Integer;
    begin
     for I:=0 to Count-1 do
       Items[I].SomeMethod (Param);
    end;
  • oxffff © (05.05.08 16:47) [73]

    > Григорьев Антон ©   (05.05.08 16:36) [70]


    На все твои замечения ответы дам вечером.
  • oxffff © (05.05.08 16:50) [74]

    > Игорь Шевченко ©   (05.05.08 16:42) [72]


    Предлагаю назначить время вечером и я думаю все решим.
    Во сколько сегодня?

    P.S. Шеф срочно просит написать хрень на ABAP.
  • ПостОвый терминатор © (05.05.08 16:55) [75]
    Давно не наблюдаю AEN   (02.05.08 21:46), а пост живет и здравствует. Особенно радуеи состав полемистов:)
    Успехов Вам в вашем творчестве.
  • Alkid © (05.05.08 17:22) [76]

    > P.S. Шеф срочно просит написать хрень на ABAP.

    А на ABAP как mapcar написать? :)))
  • Alkid © (05.05.08 17:24) [77]

    > ПостОвый терминатор ©   (05.05.08 16:55) [75]

    Осталось ещё участкового терминатора придумать :)
  • Ega23 © (05.05.08 17:32) [78]

    > Alkid ©   (05.05.08 17:24) [77]


    Почту проверь.
  • ПостОвый терминатор © (05.05.08 17:38) [79]
    Господа, заинтересованные! Извините еще в очередной раз. Позвольте спросить, что Вам мешает открыть соответствующую (новую) обсуждению ветку? А не флудить в ветке автора, которого ваша "переписка" похоже не интересует:(
  • Palladin © (05.05.08 17:42) [80]

    > ПостОвый терминатор ©   (05.05.08 17:38) [79]

    А ведь кто-то, буквально ~8 минут назад, флуданул в другой ветке. Не будем показывать пальцами, но это был слоненок.
  • Игорь Шевченко © (05.05.08 17:44) [81]
    ПостОвый терминатор ©   (05.05.08 17:38) [79]

    А зачем ты в начинающих пишешь под чужими никами ? Накажу.
  • ПостОвый терминатор © (05.05.08 17:47) [82]

    > Игорь Шевченко ©   (05.05.08 17:44) [81]

    Не понял, а каком посте идет речь?
  • Пробегал2... (05.05.08 18:50) [83]
    Игорь Шевченко ©   (05.05.08 15:33) [46]
    прежде чем спорить, про предмет спора почитай малость


    а я ни с чем не спорил. Перечитываем дружно два раза.
  • oxffff © (05.05.08 20:40) [84]
    Итак приступим


    > Григорьев Антон ©   (05.05.08 16:36) [70]
    >
    > > oxffff ©   (05.05.08 15:48) [52]
    > > type
    > > TXFUNC=function (const a:TvarRec):TvarRec;
    > >
    > > function abc(var List:array of const;func:TXFUNC):integer;
    >
    > >
    > > var i:integer;
    > > begin
    > > for i:=0 to length(List)-1 do LIST[i]:=func(LIST[i]);
    > > end;
    > >
    > > function XSample(const a:TvarRec):TvarRec;
    > > begin
    > >
    > > end;
    > >
    > > procedure TForm1.Button1Click(Sender: TObject);
    > > var a:array of TVarRec;
    > > begin
    > > abc(A,XSample);
    > > end;
    >
    > Не компилируется abc([1,'a', 2], XSample), т.е. константный
    > список кушать не хочет. В Лиспе с этим проблем нет. Я уж
    > молчу о том, что чтобы правильно сформировать содержимое
    > массива a, надо будет повозиться с полями TVarRec, что очень
    > неудобно. Полиморфизм функции XSample тоже не так просто
    > сделать.


    А разве должно?
    function abc(var )

    Однако кто вам мешает сделать так?

    type
    TXFUNC=function (const a:TvarRec):TvarRec;
    VarRecArray=array of TVarRec;

    function abc(var List:array of const;func:TXFUNC):integer;
    var i:integer;
    begin
    for i:=0 to length(List)-1 do LIST[i]:=func(LIST[i]);
    end;

    function XSample(const a:TvarRec):TvarRec;
    begin

    end;

    function TrickInit(const List:array of const):VarRecArray;
    begin
    Setlength(result,length(list));
    copyMemory(result,@list,sizeof(TvarRec)*length(List));
    end;


    procedure TForm1.Button1Click(Sender: TObject);
    var A:VarRecArray;
    begin
    A:=TrickInit([1,'2',3,4]);
    abc(A,XSample);
    end;
  • oxffff © (05.05.08 20:58) [85]
    Продолжим.


    > Григорьев Антон ©   (05.05.08 16:36) [70]
    > oxffff ©   (05.05.08 15:50) [54]
    > Как у вас с ООП?
    > Видимо, очень плохо. Потому что не представляю, при чём
    > вообще ООП, когда я хочу выполнить простые операции над
    > типами integer, real, char и т.п.


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

    Используя аналогичную идею как с TCustomvariant
  • Игорь Шевченко © (05.05.08 21:06) [86]
    Пробегал2...   (05.05.08 18:50) [83]

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

    > Григорьев Антон ©   (05.05.08 16:36) [70]
    >
    > Да, читали. Но TCustomVariant - это всё-таки не элементарный
    > тип, а обеспечивать полиморфизм на уровне простых типов
    > Delphi не умеет.
    >
    > Получил ожидаемый результат - исключение в строке с синусом.
    >  Потому что такие фокусы проходят только когда v содержит
    > указатель на IDispatch, т.е. простые типы опять пролетают
    > как фанера над Парижем. Ответ насчёт стандартной функции
    > sin не засчитывается.


    Это вам задание на дом, а именно как прикрутить disp вызовы к элементарным типам. Подумайте.
  • oxffff © (05.05.08 21:15) [88]

    > Игорь Шевченко ©   (05.05.08 16:42) [72]
    > oxffff ©   (05.05.08 16:20) [67]
    >
    > Мне будет крайне интересна передача классов в иерархии через
    > TVarRec
    >
    > type
    >  TFooBase = class
    >  public
    >     procedure SomeMethod (Param: TParam); virtual;
    >  end;
    >
    >  TFoo = class(TFooBase)
    >  ...
    >  end;
    >  TBar = class(TFoo)
    >  ...
    >  public
    >     procedure SomeMethod (Param: TParam); override;
    >  end;
    >
    > То есть, при generic-ах я могу написать
    >
    >  type
    >    TFooList = TList<TFoobase>
    >    public
    >     ...
    >      procedure ApplySomeMethod (Param: TParam);
    >    end;
    >
    > procedure TFooList.ApplySomeMethod (Param: TParam);
    > var
    >  I: Integer;
    > begin
    >  for I:=0 to Count-1 do
    >    Items[I].SomeMethod (Param);
    > end;


    Я не понял вашего вопроса?
  • Grids (05.05.08 21:31) [89]

    > ПостОвый терминатор ©   (05.05.08 17:38) [79]
    > Господа, заинтересованные! Извините еще в очередной раз.
    >  Позвольте спросить, что Вам мешает открыть соответствующую
    > (новую) обсуждению ветку? А не флудить в ветке автора, которого
    > ваша "переписка" похоже не интересует:(

    Мне показалось, что меня не поняли:(
    Или на самом деле на этом форуме все ...
    Еще раз прошу извинить за резкость (просто становится обидно за форум)
  • Григорьев Антон © (05.05.08 22:12) [90]

    > oxffff ©   (05.05.08 20:40) [84]
    > Однако кто вам мешает сделать так?
    <...>
    procedure TForm1.Button1Click(Sender: TObject);
    var A:VarRecArray;
    begin
    A:=TrickInit([1,'2',3,4]);
    abc(A,XSample);
    end;

    А если понадобится так?
    procedure TForm1.Button1Click(Sender: TObject);
    var A:VarRecArray;
    begin
    A:=TrickInit([1,'abc',3,4]);
    abc(A,XSample);
    end;
    Будете использовать CopyMemory с автоматически финализируемым типом?
  • oxffff © (05.05.08 22:34) [91]

    > Будете использовать CopyMemory с автоматически финализируемым
    > типом?


    А может изучить мат. часть?

     TVarRec = record { do not pack this record; it is compiler-generated }
       case Byte of
         vtInteger:    (VInteger: Integer; VType: Byte);
         vtBoolean:    (VBoolean: Boolean);
         vtChar:       (VChar: Char);
         vtExtended:   (VExtended: PExtended);
         vtString:     (VString: PShortString);
         vtPointer:    (VPointer: Pointer);
         vtPChar:      (VPChar: PChar);
         vtObject:     (VObject: TObject);
         vtClass:      (VClass: TClass);
         vtWideChar:   (VWideChar: WideChar);
         vtPWideChar:  (VPWideChar: PWideChar);
         vtAnsiString: (VAnsiString: Pointer);
         vtCurrency:   (VCurrency: PCurrency);
         vtVariant:    (VVariant: PVariant);
         vtInterface:  (VInterface: Pointer);
         vtWideString: (VWideString: Pointer);
         vtInt64:      (VInt64: PInt64);
     end;
  • oxffff © (05.05.08 22:36) [92]

    > oxffff ©   (05.05.08 22:34) [91]
    >
    > > Будете использовать CopyMemory с автоматически финализируемым
    >
    > > типом?
    >
    >
    > А может изучить мат. часть?
    >
    >  TVarRec = record { do not pack this record; it is compiler-
    > generated }
    >    case Byte of
    >      vtInteger:    (VInteger: Integer; VType: Byte);
    >      vtBoolean:    (VBoolean: Boolean);
    >      vtChar:       (VChar: Char);
    >      vtExtended:   (VExtended: PExtended);
    >      vtString:     (VString: PShortString);
    >      vtPointer:    (VPointer: Pointer);
    >      vtPChar:      (VPChar: PChar);
    >      vtObject:     (VObject: TObject);
    >      vtClass:      (VClass: TClass);
    >      vtWideChar:   (VWideChar: WideChar);
    >      vtPWideChar:  (VPWideChar: PWideChar);
    >      vtAnsiString: (VAnsiString: Pointer);
    >      vtCurrency:   (VCurrency: PCurrency);
    >      vtVariant:    (VVariant: PVariant);
    >      vtInterface:  (VInterface: Pointer);
    >      vtWideString: (VWideString: Pointer);
    >      vtInt64:      (VInt64: PInt64);
    >  end;
  • Игорь Шевченко © (05.05.08 23:37) [93]
    oxffff ©   (05.05.08 21:15) [88]


    > Я не понял вашего вопроса?


    Есть иерархия. Она описана. Есть шаблонный класс списка классов из этой иерархии. Я описал гипотетический пример, как класс списка мог бы выглядеть с применением generic-ов, и как это выглядит в C# и С++
    насколько я понял, ты предлагаешь реализовать функциональность generic-ов через TVarRec
    Вот мне и любопытно увидеть реализацию моего гипотетического примера с помощью TVarRec
  • Ketmar © (06.05.08 01:09) [94]
    а можно я скажу, можно? привет, придурки!

    Игорь, Розыч — ну не удаляйте. разве я не прав?

    зыж для остальных: Кэтмар — ламер. это общеизвестный факт.
  • oxffff © (06.05.08 09:05) [95]

    > Игорь Шевченко ©   (05.05.08 23:37) [93]
    > oxffff ©   (05.05.08 21:15) [88]
    >
    >
    > > Я не понял вашего вопроса?
    >
    >
    > Есть иерархия. Она описана. Есть шаблонный класс списка
    > классов из этой иерархии. Я описал гипотетический пример,
    >  как класс списка мог бы выглядеть с применением generic-
    > ов, и как это выглядит в C# и С++
    > насколько я понял, ты предлагаешь реализовать функциональность
    > generic-ов через TVarRec
    > Вот мне и любопытно увидеть реализацию моего гипотетического
    > примера с помощью TVarRec


    вопрос был про TYPE ANY (шаблонные) функции.
  • Polevi (06.05.08 09:27) [96]
    >oxffff ©   (06.05.08 09:05) [95]
    многое можно сделать через ж
    но не нужно
  • Григорьев Антон © (06.05.08 09:34) [97]

    > oxffff ©   (05.05.08 22:34) [91]
    > А может изучить мат. часть?

    Учите. Вам знаний матчасти как раз очень не хватает.

    Берём ваш код и слегка дополняем, чтобы можно было получить какой-то результат.

    type
     TXFUNC=function (const a:TvarRec):TvarRec;
     VarRecArray=array of TVarRec;

    function abc(var List:array of const;func:TXFUNC):integer;
    var
     i:integer;
    begin
     for i:=0 to length(List)-1 do
       LIST[i]:=func(LIST[i]);
     Result:=0;
    end;

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

    function TrickInit(const List:array of const):VarRecArray;
    begin
     Setlength(result,length(list));
     copyMemory(result,@list,sizeof(TvarRec)*length(List));
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    var A:VarRecArray;
       S:string;
    begin
     S:='abc';
     UniqueString(S);
     A:=TrickInit([S]);
     S:='123';  {*}
     abc(A,XSample);
     ASSERT(A[0].VType = vtAnsiString);
     Label1.Caption:=string(A[0].VAnsiString)
    end;



    Функция XSample оставляет переданное ей значение без изменения, поэтому следует ожидать появления в Label1 текста 'abc', который был присвоен переменной S, переданной затем в качестве элемента массива. Тем не менее, на экране появляется непонятно что (проверено в Delphi 7). А вот если убрать строку, отмеченную звёздочкой, будет, как и ожидалось, строка "abc".

    Поясню, что здесь происходит. С помощью UniqueString мы добиваемся того, что значение S хранится в динамической памяти со счётчиком ссылок, равным 1. Когда мы передаём это значение в конструктор открытого вариантного массива, указатель на эту строку тупо копируется как простой указатель, который и сохраняется в нулевом элементе массива A. Механизм подсчёта ссылок при этом не включается. И когда переменной S присваивается другое значение, память, занимаемая строкой, считается свободной, и что там будет располагаться - это как повезёт. А в A[0] при этом сохраняется этот битый указатель, в результате чего мы и имеем проблемы. Кстати, рекомендую попробовать после строки со звёздочкой вставить UniqueString(S) - увидите ещё один интересный эффект :))

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

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

    Конечно, можно в вашу функцию TrickInit добавить контроль за счётчиком ссылок или вообще преобразование, сводящее всё к PChar и ручному управлению памятью. Потребуется ещё куча функций, которые будут в разных ситуациях отвечать за правильное освобождение памяти в нужный момент. Но удобно ли будет пользоваться такой библиотекой с такими наворотами? Да ещё и с учётом того, что для работы с ней подходит не любой тип данных, а специально организованный, и не любая функция, а только специально написанная? Предлагаю вам остановится на таком завершении спора: "В Delphi, сильно извратившись, можно написать библиотеку, которая, при добровольном соблюдении её пользователем кучи ограничений, позволит ему программировать в стиле, похожем на Лисп. Но для решения любой практической задачи будет удобнее писать в стиле Delphi, чем использовать такую библиотеку".
  • euru © (06.05.08 09:34) [98]

    > Alkid ©   (05.05.08 17:22) [76]
    > А на ABAP как mapcar написать? :)))


    Например, можно так:

    form mapcar
        using    in_table  type index table
                 func_name type string
        changing out_table type index table
    .
    field-symbols: <in>, <out>.

      clear out_table.
      loop at in_table assigning <in>.
        append initial line to out_table assigning <out>.
        perform (func_name) in program (sy-cprog)
            using    <in>
            changing <out>
        .
      endloop.
    endform.

  • Игорь Шевченко © (06.05.08 09:35) [99]
    oxffff ©   (06.05.08 09:05) [95]


    > вопрос был про TYPE ANY (шаблонные) функции.


    Переведи пожалуйста, я не понял ответа
  • oxffff © (06.05.08 09:49) [100]

    > Григорьев Антон ©   (06.05.08 09:34) [97]
    >
    > > oxffff ©   (05.05.08 22:34) [91]
    > > А может изучить мат. часть?
    >
    > Учите. Вам знаний матчасти как раз очень не хватает.


    Ну. ну. Может вы все же удостоверитесь и откроете отладчик. И посмотрите на код который генерирует компилятор?

    И прежде чем мне приводить примеры все же изучите мат. часть.
  • oxffff © (06.05.08 10:04) [101]

    > Григорьев Антон ©   (06.05.08 09:34) [97]
    >
    > > oxffff ©   (05.05.08 22:34) [91]
    > > А может изучить мат. часть?
    >
    > Учите. Вам знаний матчасти как раз очень не хватает.
    >
    > Берём ваш код и слегка дополняем, чтобы можно было получить
    > какой-то результат.
    >
    > type
    >  TXFUNC=function (const a:TvarRec):TvarRec;
    >  VarRecArray=array of TVarRec;
    >
    > function abc(var List:array of const;func:TXFUNC):integer;
    >
    > var
    >  i:integer;
    > begin
    >  for i:=0 to length(List)-1 do
    >    LIST[i]:=func(LIST[i]);
    >  Result:=0;
    > end;
    >
    > function XSample(const a:TvarRec):TvarRec;
    > begin
    >  Result:=a;
    > end;
    >
    > function TrickInit(const List:array of const):VarRecArray;
    >
    > begin
    >  Setlength(result,length(list));
    >  copyMemory(result,@list,sizeof(TvarRec)*length(List));
    > end;
    >
    > procedure TForm1.Button1Click(Sender: TObject);
    > var A:VarRecArray;
    >    S:string;
    > begin
    >  S:='abc';
    >  UniqueString(S);
    >  A:=TrickInit([S]);
    >  S:='123';  {*}
    >  abc(A,XSample);
    >  ASSERT(A[0].VType = vtAnsiString);
    >  Label1.Caption:=string(A[0].VAnsiString)
    > end;
    >
    > Функция XSample оставляет переданное ей значение без изменения,
    >  поэтому следует ожидать появления в Label1 текста 'abc',
    >  который был присвоен переменной S, переданной затем в качестве
    > элемента массива. Тем не менее, на экране появляется непонятно
    > что (проверено в Delphi 7). А вот если убрать строку, отмеченную
    > звёздочкой, будет, как и ожидалось, строка "abc".

    А что вы хотите, если вы не знаете работу с типом TvarRec.
    И даже не удосужились не только открыть отладчик, но и внимательно посмотреть [92].

    И copyMemory(result,@list,sizeof(TvarRec)*length(List)) не имеет к этому никакого отношения.

    Тип TvarRec не имеет и иметь не может финализируемых типов.
    Поэтому семантика копирования простая без использования TypeInfo.

    >
    > Поясню, что здесь происходит. С помощью UniqueString мы
    > добиваемся того, что значение S хранится в динамической
    > памяти со счётчиком ссылок, равным 1. Когда мы передаём
    > это значение в конструктор открытого вариантного массива,
    >  указатель на эту строку тупо копируется как простой указатель,

    Это говорит о вашем не знании.
    Код создания массива создает компилятор.
    А то что вы не знаете некоторых нюансов налицо.

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

    var a,b:Tvarrec;

    a:=b;    

    Ничего подобного.

    Финализируемые типы в вариантных записях запрещены. :)
    Поэтому будет простое копирование. :)

    >  который и сохраняется в нулевом элементе массива A. Механизм
    > подсчёта ссылок при этом не включается. И когда переменной
    > S присваивается другое значение, память, занимаемая строкой,
    >  считается свободной, и что там будет располагаться - это
    > как повезёт. А в A[0] при этом сохраняется этот битый указатель,
    >  в результате чего мы и имеем проблемы. Кстати, рекомендую
    > попробовать после строки со звёздочкой вставить UniqueString(S)
    > - увидите ещё один интересный эффект :))

    Проблемы в том, что вы не понимаете что вы делаете. И что делает компилятор. :)

    >
    > Кстати, я вчера задал вам несколько вопросов по поводу ваших
    > предложений, но для ответа вы почему-то выбрали только один
    > из них, скромно умолчав про остальные.
    >

    Я все ваши вопросы ответил. См. внимательно. :)

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

    Ну и кто теперь опять не прав? :)

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

    Это требуется от вас поскольку приведение делает компилятор и вы должны это знать.  :)

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


    C уважением Антонов Сергей. :)
  • Григорьев Антон © (06.05.08 10:05) [102]

    > oxffff ©   (06.05.08 09:49) [100]
    > Ну. ну. Может вы все же удостоверитесь и откроете отладчик.
    >  И посмотрите на код который генерирует компилятор?

    Дык, смотрел ведь :) Копирование указателя увидел, изменения счётчика ссылок - нет. Да и результат работы этого кода говорит сам за себя. Или неизвестно какое значение - это то, что вы хотели получить с самого начала?

    А примеры кода приводите вы. Я привожу примеры того, когда ваше решение работает неправильно.
  • oxffff © (06.05.08 10:10) [103]

    > euru ©   (06.05.08 09:34) [98]
    >
    > > Alkid ©   (05.05.08 17:22) [76]
    > > А на ABAP как mapcar написать? :)))
    >
    >
    > Например, можно так:
    >
    > form mapcar
    >     using    in_table  type index table
    >              func_name type string
    >     changing out_table type index table
    > .
    > field-symbols: <in>, <out>.
    >
    >   clear out_table.
    >   loop at in_table assigning <in>.
    >     append initial line to out_table assigning <out>.
    >     perform (func_name) in program (sy-cprog)
    >         using    <in>
    >         changing <out>
    >     .
    >   endloop.
    > endform.


    Спасибо за пример.
    Мне тоже нравится понятие field-symbols
    (которые по сути являются typed ref) на ABAP.
  • oxffff © (06.05.08 10:18) [104]

    > А примеры кода приводите вы. Я привожу примеры того, когда
    > ваше решение работает неправильно.


    Решение правильное. Нужно знать работу компилятора с TvarRec.

    Проблема не в коде TrickInit (и кокретно не в CopyMemory).
    а в том, что TVarrec являясь вариантной записью не может содержать финализируемые типы.
    И разработчики Delphi не написали Compiler magic функций которые обрабатывают семантику этого типа.
    В отличии от variant.

    Проблема в том что компилятор при приведении делает это грубо, а именно в строке
    A:=TrickInit([S]);

    Посмотрите внимательно. Что будет при передаче по значению
    function abc(List:array of const);
    Будет простое копирование на стек. Никакой обработки Vtype в отличии от variant
  • oxffff © (06.05.08 10:20) [105]

    > Дык, смотрел ведь :) Копирование указателя увидел, изменения
    > счётчика ссылок - нет.

    Так устроен Delphi. И на это вы натыкатесь еще до входа в функцию TrickInit. :)
  • Григорьев Антон © (06.05.08 10:21) [106]

    > oxffff ©   (06.05.08 10:04) [101]
    > Тип TvarRec не имеет и иметь не может финализируемых типов.

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

    > Это говорит о вашем не знании.
    > Код создания массива создает компилятор.
    > А то что вы не знаете некоторых нюансов налицо.
    >
    > Вы наверно думаете, что если вы напишите то будет использован
    > механиазм копирования typeinfo.
    >
    > var a,b:Tvarrec;
    >
    > a:=b;    
    >
    > Ничего подобного.

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

    > Проблемы в том, что вы не понимаете что вы делаете. И что
    > делает компилятор. :)

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

    > Ну и кто теперь опять не прав? :)

    Вы. Потому что вы привели код, позиционируя его как эквивалент Лиспа и не указав дополнительных ограничений. А он эквивалентом не является, так как не умеет работать со строками.
  • oxffff © (06.05.08 10:25) [107]
    to Григорьев Антон ©  

    Вот пример.

    function abc2(list:array of const):integer;
    begin
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    begin
    abc2([1,2,'asd','asdasd']);
    end;

    cм. копирование в теле abc2 при создании копии.
    Анализа на Vtype нет, а отличие от variant (у которых есть compiler magic).
    Такова семантика TvarRec.
  • Григорьев Антон © (06.05.08 10:26) [108]

    > oxffff ©   (06.05.08 10:18) [104]
    > Решение правильное. Нужно знать работу компилятора с TvarRec.

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

    > Посмотрите внимательно. Что будет при передаче по значению
    >
    > function abc(List:array of const);
    > Будет простое копирование на стек. Никакой обработки Vtype
    > в отличии от variant

    А я как сказал? o_O

    Я так и писал, что будет простое копирование (точнее, я назвал его не простым, а тупым, но сути это не меняет). Более того, я это знал заранее, ещё до написания этого кода, и специально писал его таким образом, чтобы наиболее наглядно это продемонстрировать.

    Теперь выдохните, подумайте и напишите, в чём именно вы хотите меня убедить.
  • oxffff © (06.05.08 10:45) [109]

    > Григорьев Антон ©   (06.05.08 10:26) [108]
    >
    > > oxffff ©   (06.05.08 10:18) [104]
    > > Решение правильное. Нужно знать работу компилятора с TvarRec.
    >
    >
    > Правильное решение - это то, для которого чётко указаны
    > границы применимости. Вы ничего не написали про ограничения
    > на работу со строками - откуда я мог знать, понимаете ли
    > вы, что ваш пример с ними работать не будет, или нет. Вот
    > и написал, что не будет.

    Мой пример будет работать, если вы знаете как устроен Delphi.

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

    Напоминаю вам ваш пост

    Григорьев Антон ©   (05.05.08 22:12) [90]
    Будете использовать CopyMemory с автоматически финализируемым типом?


    TvarRec - имеет простую семантику копирования.

    Поэтому ситуацию которые вы смоделировали относится к TvarRec, а не к моей реализации.

    >
    > > Посмотрите внимательно. Что будет при передаче по значению
    >
    > >
    > > function abc(List:array of const);
    > > Будет простое копирование на стек. Никакой обработки Vtype
    >
    > > в отличии от variant
    >
    > А я как сказал? o_O
    >
    > Я так и писал, что будет простое копирование (точнее, я
    > назвал его не простым, а тупым, но сути это не меняет).

    А зачем был ваш вопрос про CopyMemory?  :)

    > Более того, я это знал заранее, ещё до написания этого кода,
    >  и специально писал его таким образом, чтобы наиболее наглядно
    > это продемонстрировать.

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

    >
    > Теперь выдохните, подумайте и напишите, в чём именно вы
    > хотите меня убедить.


    Я вам написал три варианта решения.

    Кстати как там ваше домашнее задание? см. выше
  • Alkid © (06.05.08 10:48) [110]

    > oxffff ©   (06.05.08 09:05) [95]

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

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

    Я всё это к чему веду - есть такие вещи, которые должны быть либо поддержаны на уровне самого языка, либо должны быть выброшены и стоит программировать без них. Функции высшего порядка в общем виде, например.
    Не потому, что из невозможно промоделировать, а потому что полученное решение не будет иметь production quality.

    В качестве примера из реальной жизни расскажу, как у нас в конторе некоторые сетлые умы решили забацать свой сборщик мусора для С++. Он даже работал. Но для корректной работы с ним надо было прекрасно разбираться в целом зоопарке смартпоинтеров, изобретённых для его поддержки. А если кто-то где-то ошибался, то вся система нагибалась разом, причём очень трудно было обнаружить, кто и где неправильно что сделал. А программистов много, приходят новые. Кто-то и где-то обязательно налажает.
    А ведь сборщик мусора - это один из базовых сервисов платформы, о котором не надо особо задумываться. Понятно, что он не должен усложнять программирование и служить источником ошибок.

    Так же и тут. Реализовывать функции высшего порядка или хотя бы mapcar в общем виде на Delphi смысла нет, овчинка не стоит выделки. Будет как с тем сборщиком мусора - да, они это сделали, но потом требовалось такое количество магических пассов и приседаний, что бы с ним правильно работать, что лучше было бы ограничиться гораздо более простым и специализированным решением.
  • oxffff © (06.05.08 10:57) [111]

    > Alkid ©   (06.05.08 10:48) [110]


    Никто не спорит.

    Было утверждение, что нельзя. Я показываю как можно.
    То что это костыли никто не спорит. Да это костыли.
    Но ходить худо бедно можно.  :)
  • 31512 (06.05.08 11:00) [112]

    > oxffff ©   (06.05.08 10:57) [111]

    - Доктор! У меня заворот кишок!
    - Ничего страшного! Проглотите вот эту палочку.
  • Игорь Шевченко © (06.05.08 11:01) [113]
    Вот в паскале есть тип string, в C (и в С++) его нету. Много лет разные умы с разной степенью успеха измышляли различные способы работы со строками, подобные работе с ними же в паскале.

    И все равно, на обложке издания написано "Британская энциклопудия", то есть, работать так, как в паскале, не получается.

    Это я к тому, что работа со строками прекрасно переводится на язык команд процессора.
  • Alkid © (06.05.08 11:08) [114]

    > Было утверждение, что нельзя. Я показываю как можно.

    Не совсем. Цитирую:

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

    В рамках такой общности, как в Лисп - нет.


    То, что ты предложил по общности не дотягивает. Это всё же более специальный случай, ибо не на все функции применим, а только на те, которые TVarRec принимают :)
  • Alkid © (06.05.08 11:15) [115]

    > Вот в паскале есть тип string, в C (и в С++) его нету. Много
    > лет разные умы с разной степенью успеха измышляли различные
    > способы работы со строками, подобные работе с ними же в
    > паскале.
    >
    > И все равно, на обложке издания написано "Британская энциклопудия",
    >  то есть, работать так, как в паскале, не получается.
    >
    > Это я к тому, что работа со строками прекрасно переводится
    > на язык команд процессора.

    Кстати да. Те же яйца, но меньше. Как ты ни бейся, а сделать так, что бы выражение "bla-bla-bla" + "bu-bu-bu" на С++ занималось конкатенацией строк, а не сложением указателей, не выйдет.
  • oxffff © (06.05.08 11:23) [116]

    > Alkid ©   (06.05.08 11:08) [114]
    >
    > > Было утверждение, что нельзя. Я показываю как можно.
    >
    > Не совсем. Цитирую:
    >
    > > вы хотите сказать, что на дельфи этого сделать невозможно?
    >
    > >  не понимаю.
    >
    > В рамках такой общности, как в Лисп - нет.
    >
    > То, что ты предложил по общности не дотягивает. Это всё
    > же более специальный случай, ибо не на все функции применим,
    >  а только на те, которые  принимают :)


    Вариант на TVarRec самый простой и менее гибкий.
    Я кстати еще написал 2 варианта решения.
    Например на variant, работу с которым можно расширить посредством новых типов используя TcustomVariant.
  • Игорь Шевченко © (06.05.08 11:25) [117]

    > Я кстати еще написал 2 варианта решения.
    > Например на variant, работу с которым можно расширить посредством
    > новых типов используя TcustomVariant.


    а свой вариант с иерархией я увижу ?
  • crux (06.05.08 11:26) [118]
    Игорь Шевченко ©   (06.05.08 11:01) [113]

    Вы немного искажаете действительность. Как вам должно быть прекрасно известно, в стандартной (sic!) библиотеке С++ есть тип string, предоставляющий все необходимые абстракции, которые позволяют обращаться со строками как со встроенным типом. Кроме того, интерфейс строк включает в себя интерфейс вектора из той же стандартной библиотеки.
    А вот интересно, есть ли в паскале стандартная возможность конкатенации строк, посредством добавления в конец (append), позволяющая добиться линейной сложности в этом деле?
  • Игорь Шевченко © (06.05.08 11:33) [119]
    crux   (06.05.08 11:26) [118]


    > Вы немного искажаете действительность. Как вам должно быть
    > прекрасно известно, в стандартной (sic!) библиотеке С++
    > есть тип string, предоставляющий все необходимые абстракции,
    >  которые позволяют обращаться со строками как со встроенным
    > типом


    то есть, я могу написать
    string foo;

    foo = "foo" + "bar";

    ?
  • Григорьев Антон © (06.05.08 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 (06.05.08 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 © (06.05.08 11:40) [122]

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

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

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

    И не надо никакого хакинга, битов, байтов и т.п. ООП в чистом виде.
    Вот только писать в таком стиле замучаешься :)
  • Alkid © (06.05.08 11:42) [123]

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

    Дык, об этом и речь. Конструктор вызывать приходится явно. Это "протечка абстракции" в терминологии Джоэля Спольски. Со стрингами, конечно же, это фигня, не проблема. А с mapcar`ом уже нет.
  • Игорь Шевченко © (06.05.08 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 (06.05.08 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 © (06.05.08 12:10) [126]

    > crux   (06.05.08 11:59) [125]

    Кто же спорит?
    Однако это уже иллюстрация к тому, то *точно* воспроизвести некоторые абстракции одного языка на другом не всегда получается. И это, кстати, крайне примитивный случай - строки в двух очень похожишь по идеологии языка.
  • oxffff © (06.05.08 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 © (06.05.08 12:39) [128]
    To Григорьев Антон ©

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

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


    Я работаю с TVarRec и знаю семантику копирования этого типа, которая выполняет поэлементное копирование. Поэтому при работе с этим типом ответственность за LifeTime лежит на программисте.
    Поэтому эти претензии не ко мне, а к Хейлсбергу.
  • Игорь Шевченко © (06.05.08 12:57) [130]
    crux   (06.05.08 11:59) [125]

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

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

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

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

    Это одна сторона медали. Другая сторона заключается в том, что вот работаешь, работаешь с каким-нибудь string в С++ (QString в Qt - вот кстати любят разные разботчики своих фремворков наворотить своих "особенных" причмочек для работы со строками), а потом надо тебе воспользоваться некой функцией, а она, собака, только char* понимает. И начинаются выкрутасы... Ну никак не получается паскалеподобная работа со строками.
  • Григорьев Антон © (06.05.08 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. А решения, которое работало бы и с простыми типами, и со строками без обёрток вы так и не показали.
  • Григорьев Антон © (06.05.08 13:32) [133]

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

    TVarRec - это внутренняя кухня хранения списков. Если вы не можете предложить такой метод работы со списками, который позволяет программисту не думать о внутренней кухне, а работать на более высоком уровне абстракции, значит, вы не можете предложить столь же общего решения, какое даёт Лисп. Что и требовалось доказать.
  • Пробегал2... (06.05.08 13:34) [134]
    Игорь Шевченко ©   (05.05.08 21:06) [86]
    Эт ты сказки рассказывай где-нибудь еще. Ты тут личность давно известная, повадки твои тоже


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

    Если вы судите о том, спорил ли я или нет лишь по моему нику - да на здоровье. Я предлагаю делать анализ на основании сказанного, а если вы перечитаете сказанное - я нигде не спорил. А уж как вам там хочется думать - ваше право.
  • Пробегал2... (06.05.08 13:37) [135]
    oxffff, ну ты действительно не прав. Ты вместо выдачи универсального решения выдал ограниченное решение и объяснил ПОЧЕМУ оно ограниченное. Но кому нужно это объяснение? Решение не является общим и универсальным - и неважны причины, все, оно уже не такое как в LISP.

    Или надо доказать, что в LISP тоже есть ограничения в решении.
  • crux (06.05.08 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 © (06.05.08 15:22) [137]

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

    Тут не было таких утверждений. Было утверждение, что работа со строками в С++ и в Паскале реализована немного по-разному и из-за особенностей языка С++ реализовать её ТОЧНО ТАК ЖЕ, как в паскале нельзя. Так что к совести предлагаю ещё прикладывать внимательность прочтения :) Большего не утверждалось.
  • Игорь Шевченко © (06.05.08 15:29) [138]
    crux   (06.05.08 14:45) [136]


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


    Такой, как в Паскале - факт, отсутствует :) Я все-таки рекомендую читать весь пост, а не отдельные буквы.
    Аналогично прошу пардону за препирательство
  • 31512 (06.05.08 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 © (06.05.08 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... (06.05.08 16:10) [141]
    Игорь Шевченко ©   (06.05.08 12:57) [130]
    Но на этом форуме у посетителей наблюдается одна похожая болезнь, они не вникают в смысл дискуссии и начинают ловить блох в конкретных словах конкретных постов конкретных авторов


    Игорь, вы кстати этим же страдаете. Частенько вы выдираете из страничного поста некую фразу и опровергаете ее, хотя ее правдивость на весь смысл поста может практически и влияния не оказывать, то есть это не ключевой момент.
  • oxffff © (06.05.08 16:11) [142]

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


    Если вы находитесь на кухне в гостях, то соблюдайте правила этого дома.
    :)
  • Игорь Шевченко © (06.05.08 16:25) [143]
    Пробегал2...   (06.05.08 16:10) [141]

    Читаем правила форума долго и внимательно. Не удивляемся потом репрессиям.
  • Игорь Шевченко © (06.05.08 16:30) [144]
    oxffff ©   (06.05.08 16:09) [140]


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


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

    Кстати, аналогичная фигня, но гораздо проще для понимания - это функции с переменным числом аргументов. В С они встроены в язык, реализация их на Delphi прямо скажем, затруднительна.
  • Григорьев Антон © (06.05.08 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 © (06.05.08 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 ждет меня.
  • Григорьев Антон © (06.05.08 17:13) [147]

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

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

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

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

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

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

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

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

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

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

    Просто в дельфи нету необходимости в такой фишке, так как есть array of Variant и array of const
  • wicked © (06.05.08 17:40) [149]

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

    ровно наоборот - в делфи придумали array of Variant и array of const, потому что нету функций с переменным числом аргументов
  • Игорь Шевченко © (06.05.08 17:48) [150]

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


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

    Кстате, вот writeln - она истинно с переменным числом. Значит, необходимость в фишке таки есть ?
  • oxffff © (06.05.08 17:57) [151]

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


    Нет с лиспом я не знаком.
    Однако, что такое closures и анонимные функции знаю.
    Closures - это объект управляемой кучи.
    анонимные функция - функция объявленная по месту, а фактически указатель на нее.
    НО честно говоря не вижу особых препятствий для реализации. Однако поскольку нет GC, то управлять временем жизни closure придется вручную.
    Я честно говоря по данному вопросу веду диалог в newsgroup по реализации анонимных методов в Delphi for win32 анонсированных недавно.
  • oxffff © (06.05.08 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 © (06.05.08 18:18) [153]

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

    Познакомься :)
    Для расширения кругозора всяко полезно будет.
  • Пробегал2... (06.05.08 19:03) [154]
    Удалено модератором
  • oxffff © (06.05.08 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 © (06.05.08 20:41) [156]

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


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

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

    Там как раз используется аналог closure в виде сохранения Machine State, во всяком смысл тот же - захват внешних переменных.
  • Григорьев Антон © (07.05.08 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 (07.05.08 09:49) [158]
    Прочитал про ЛИСП и подумал про себя : круче клиппера языка нету :)
    Мона писать свои операторы (расширять язык - я так сделал для оконного вывода и печати), мона исполнять любые выражения из строки. Причем не только числовые. Есть массивы переменной размерности. Все остальное мона прикрутить.
    Потом еще подумал : а в делфи при желании мона прикрутить практически тоже самое.
  • ANB (07.05.08 09:50) [159]
    Да, а на скл сортировка пишется в одну строку :)
  • 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.007]