LINUX.ORG.RU

Ответ на: комментарий от tailgunner

> Пepeфopмyлиpyю oтвeт: тoгo, ктo xoчeт, чтoбы eгo пpoгpaммы нe тopмoзили.

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

> Tы cpaвнивaл быcтpoйдeйcтви Python+psyco c SBCL?

У тебя есть какие-то свои тесты? Ссылки в студию.

> Coвepшeннo oбъeктивный.

Объективный, это не зависящий от человека. А у тебя совершенно субъективная оценка.

ugoday ★★★★★
()
Ответ на: комментарий от tailgunner

> Ты сравнивал быстройдействи Python+psyco с SBCL?

Можно сравнить Python с cLisp-ом. А рязве psyco не накладывает никаких ограничений? (в смысле - откомпилирует любой питоний код)

> Совершенно объективный. Лиспа я не знаю, а Питон - знаю. Ты, наверное, быстрее напишешь на Лиспе, чем на Питоне.

Этот "совершенно объективный" аргумент "совершенно объективно" характерезует тебя лично (и только), и совершенно не является аргументом в локальной теме - сравнении языков. Посему, просто не должен был появиться ;)

yyk ★★★★★
()
Ответ на: комментарий от yyk

> А рязве psyco не накладывает никаких ограничений? (в смысле - откомпилирует любой питоний код)

50%. Либо откомпилирует либо нет. В реальности если может откомпилировать, то ускоряет, если не может, то работает как и работало бы.

Средняя питоновская программа, т.е. без вычислений и т.д. ускоряется раза в два. Числодробильня типа crc8 ускоряется раз в 100 или больше.

Правда работает только на x86, но я на других архитектурах питон и не гоняю.

Непонятно почему его в стандартный питон не включат. :-(

redvasily
()
Ответ на: комментарий от ugoday

> А вот с императивным не получится. Ибо тебе придётся вручную управлять памятью, вычислять адрес указателя,

Всего этого нет в Java. Итак, это у нас декларативный язык? Или функциональный

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

S-выражениям и рекурсии тоже нет аналогов в естественных языках.

Итак, вы о чем вообще?

anonymous
()
Ответ на: комментарий от yyk

> А определить в этом-же файле этот Source filters (а не подключать его) и тут-же его использовать - слабо?

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

> И не на диалекте, "порожденном воспаленным мозгом автора Something", а на том, что твой собственный "воспаленный мозг" захочет? ;)

Нет никаких причин (кроме лени и бессмысленности самого процесса), которые мешали бы мне или кому бы то ни было писать сорс-фильтры.

anonymous
()
Ответ на: комментарий от ugoday

> Если кто-то хочет, чтобы его программы не тормозили и не жрали память сверх меры, то он не выбирает питон.

В shootout SBCL по памяти слил в разы :D

>> Tы cpaвнивaл быcтpoйдeйcтви Python+psyco c SBCL?

>У тебя есть какие-то свои тесты? Ссылки в студию.

Ссылок на результаты shootout - нету.

>> Coвepшeннo oбъeктивный.

>Объективный, это не зависящий от человека.

Написание программ - это деятельность человека. Любые оценки, зависящие от человека, не являются объективными. Следовательно, любые оценки, связанные с написанием программ, не являются объективными. Я тебя правильно понял?

tailgunner ★★★★★
()
Ответ на: комментарий от ugoday

> > Moя пpoгpaммa нa Питoнe бyдeт быcтpoй.

> Относительно руби быстрой, а относительно лиспа медленной.

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

Остальные 10 все равно надо писать на строготипизированных компилируемых языках (типа C++ или там (для пуристов) OCaml-е), ибо 50%-70% потерь на лисп - неприемлемы. Сюда относятся OS, низкоуровневые библиотеки, базы данных.

anonymous
()
Ответ на: комментарий от anonymous

Ага, вот анонимный брат подогнал результаты с Psyco, спасибо. По скорости Питон всё равно сливает в основном :(, хотя в некоторых тестах и выигрывает. По памяти - картина обратная ;)

Но я рад, что у нас весь вычислительный код в Numeric Python :)

tailgunner ★★★★★
()
Ответ на: комментарий от yyk

У меня вот такой вопрос к лисперам и др. (где др. не обязательно друзья лиспа):

Есть некие данные. И некий набор фунций f1 (x) f2(x,y) f3... . Есть некий алгоритм, который перебирает параметры функций и применяет к данным. Ну и хочется типа на выходе иметь ассоциированный лист с читаемым именем и параметрами вызываемых функций (типа стринговое представление) и полученным результатом.

Т. е. сделать некий макрос типа mydefun, (mydefun mult (x, data) (* x data))) который после напр. (stringify (mult (2, data))) выдает "mult (2)"

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

MXN
()
Ответ на: комментарий от MXN

Не то, чтобы я всё понял, но: любой язык, в котором есть eval("строка"), может такое. Это если втупую.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

>> Главное, что если ты выберешь лисп, то твоя программа будет быстрой, а если питон --- медленной.

> Моя программа на Питоне будет быстрой.

аха, она будет так быстро-быстро тормозить чё больше ничё не будет успевать делать :D

> Причем и написана будет быстрее, чем на Лиспе.

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

bugmaker ★★★★☆
()
Ответ на: комментарий от bugmaker

> а чё посложнее - (выучит лисп+понаписать на ём) будет всё-таки быстрее чем парицо с питоном.

Имеешь личный опыт или просто троллишь?

tailgunner ★★★★★
()
Ответ на: комментарий от redvasily

> в питоновской программе эта фраза звучит как "добавить в базу файлов файл из такой-то директории, с таким-то именем и таким-то размером".

что за бред??????????????? ты стебёсся??????????

> filedb<в базу файлов>.push<запихнуть файл>('<в директории>'/foo', <с именем>'file.txt', <размера>777)

и куды делась остальная чясть кода?

> Лишние сущности (которых нет в нашей задаче): список, хэш.

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

> Это детали реализации, а в начале топика ты докапался до того что в питоновских перестановках использовались индексы.

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

bugmaker ★★★★☆
()
Ответ на: комментарий от tailgunner

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

> Теперь понял.

тычё, ранше не знал чё у питона даже названия своево собственново нету? :D

bugmaker ★★★★☆
()
Ответ на: комментарий от tailgunner

>> а чё посложнее - (выучит лисп+понаписать на ём) будет всё-таки быстрее чем парицо с питоном.

> Имеешь личный опыт или просто троллишь?

и тово и другово понемногу

bugmaker ★★★★☆
()
Ответ на: комментарий от bugmaker

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

>> Теперь понял.

> тычё, ранше не знал чё у питона даже названия своево собственново нету? :D

Не-а, я раньше не знал, что лисперам нравится змеи :-P

tailgunner ★★★★★
()
Ответ на: комментарий от bugmaker

>>> а чё посложнее - (выучит лисп+понаписать на ём) будет всё-таки быстрее чем парицо с питоном.

>> Имеешь личный опыт или просто троллишь?

> и тово и другово понемногу

Ну, в таком разе пишем: "ниасилил Питон" :D

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

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

>>> Теперь понял.

>> тычё, ранше не знал чё у питона даже названия своево собственново нету? :D

> Не-а, я раньше не знал, что лисперам нравится змеи :-P

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

bugmaker ★★★★☆
()
Ответ на: комментарий от tailgunner

>>>> а чё посложнее - (выучит лисп+понаписать на ём) будет всё-таки быстрее чем парицо с питоном.

>>> Имеешь личный опыт или просто троллишь?

>> и тово и другово понемногу

> Ну, в таком разе пишем: "ниасилил Питон" :D

можно даже обобщить: ниасилил различные формы садо-мазо

bugmaker ★★★★☆
()
Ответ на: комментарий от bugmaker

>> Ну, в таком разе пишем: "ниасилил Питон" :D

> можно даже обобщить: ниасилил различные формы садо-мазо

А пробовал? =:-O

tailgunner ★★★★★
()
Ответ на: комментарий от bugmaker

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

Лгешь! Лисперы в основном и пишут на Васиках, Жабах или (если повезло) Си. И мечтают о Лиспе :-P

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

>>> Ну, в таком разе пишем: "ниасилил Питон" :D

>> можно даже обобщить: ниасилил различные формы садо-мазо

> А пробовал? =:-O

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

bugmaker ★★★★☆
()
Ответ на: комментарий от tailgunner

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

> Лгешь! Лисперы в основном и пишут на Васиках, Жабах или (если повезло) Си. И мечтают о Лиспе :-P

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

bugmaker ★★★★☆
()
Ответ на: комментарий от bugmaker

> что за бред??????????????? ты стебёсся??????????

Ты что, тоже знаешь Paranoid Programming Language? Кстати, это штука будет посильнее чем лисп с питоном вместе взятые. И считаешь что чем больше знаков поставить тем более сильный вопрос?????

Отвечаю по существу: НЕТ!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Bugmaker, ты что край решил войти в историю и поддерживать флейм в этом топике любой ценой, пока он не станет Top 1 All Time?

Версию с БД на лиспе покажи, тогда обещаю много флейма со своей стороны. :-)

redvasily
()
Ответ на: комментарий от MXN

Ну пока никто не написал, напишу я вариантик (сорри, что не 
форматирвоано. Набивал прямо в REPL в CLISP):

(defun print-function (func-name &rest parameters) 
         (format t "Function name: ~S~%Parameters: ~S~%Result: ~S~%" 
                        func-name parameters (apply func-name parameters)))

предположим, что в программе где-то были определены функции:

(defun foo (x y) (* x y))

(defun foo1 (x y z) (+ x y z))

Вызываем (print-function 'foo 2 3)

Function name: FOO
Parameters: (2 3)
Result: 6

Вызываем (print-function 'foo1 2 3 4)

Function name: FOO1
Parameters: (2 3 4)
Result: 9

Если хочешь, чтобы другой формат вывода был, то перепиши format. Все.

Zubok ★★★★★
()
Ответ на: комментарий от redvasily

> Ты что, тоже знаешь Paranoid Programming Language?

не

> И считаешь что чем больше знаков поставить тем более сильный вопрос?????

я был сильно удивлён

> Отвечаю по существу: НЕТ!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

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

> Bugmaker, ты что край решил войти в историю и поддерживать флейм в этом топике любой ценой, пока он не станет Top 1 All Time?

да мне пофих, это питоноеды упорные, гнуцо но неломаюцо

> Версию с БД на лиспе покажи, тогда обещаю много флейма со своей стороны. :-)

Для этово нужно читать доку, ибо с дб я из лиспа не работал ранее. Обещяю запостить это как только появицо возможнось, ато в последнее время я нескко занят :(.

bugmaker ★★★★☆
()
Ответ на: комментарий от Zubok

> Ну пока никто не написал, напишу я вариантик (сорри, что не форматирвоано. Набивал прямо в REPL в CLISP):

Только у тебя враппер неправильный - он возвращает не то же самое, что врапнутая функция (а то, что отдает format).

BTW, на перле такое делается даже неинтрузивно, в смысле, говоришь вначале заклинание (довольно длинное, правда, если универсально - у меня модуль в котором оно живет, занимает 90 строк вместе с докой), и дальше в неизмененной проге начинает происходить трассировка вызовов прозрачная...

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

anonymous
()
Ответ на: комментарий от anonymous

>Ежели программа упирается в скорость IO, или базы данных, или сети, или реакции пользователя - то разницы никакой. А это 90% случаев.

>Остальные 10 все равно надо писать на строготипизированных компилируемых языках (типа C++ или там (для пуристов) OCaml-е), ибо 50%-70% потерь на лисп - неприемлемы. Сюда относятся OS, низкоуровневые библиотеки, базы данных.

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

anonymous
()
Ответ на: комментарий от bugmaker

> тогда почему? Я ищё могу поверить, что комуто карявая питонья запись навроде "для шаги в (:докуданадо): медленно(я(сделать, шаг),ибо(был,пьян))" вместо лисповово аналога "(шёл я долго (ибо был пьян))"

На лиспе это, скорее,

(ибо (был я пьян) (долго (шел я)))

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

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

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

anonymous
()

Анонимные братья, зарегиструйтесь. Или хоть подписывайтесь.

А то это выглядит, как раздвоение анонимной личности.

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

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

Сходи на shotout и сравни SBCL с лидерами. До D и даже C++ ему далеко. Окамлю он поменьше проигрывает, но, имхо, потому, что компилятор более зрелый и вылизанный - его уж 20 лет пишут, блин.

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

По shootout - где-то вдвое. И, замечу, если декларировать все типы, оптимизировать за счет in-place преобразований - то получится C++ с круглыми скобками. Нафик надо-то, чтоб потом геморроиться с никакой интеграцией в unix?

Не, если у вас лисп-машина - тада да, тада конечно. Только вот нету их.

anonymous
()
Ответ на: комментарий от anonymous

> > > STL подглядывать, на тему "а какая у нас семантика

> > а в лиспе всё одинаковое :P

>Дащаз. map-ом простым по хешу разве пройти можно? Фиг, maphash. А вот в STL все алгоритмы работают по итераторам, которые очень generic - главное, чтобы "модель" совпадала, а какой там конкретно тип - пофик.

Согласен. В lisp'е как раз не хватает порой гибкости stl. В lisp'е если я определил новый тип-контейнер, то мне придется писать все эти map, reduce, remove, ... с нуля. И имена у них будут уже другими. Это минус.

С другой стороны удобство многих stl-ных алгоритмов (вроде transform) сильно ограничивается отсутсвием в плюсах хоть сколько-нибудь адекватного аналога lambda.

Также в лиспе нельзя доопределить новый численный тип и перегрузить #'+, #'*, ... для него. К примеру, если мне нужны кватернионы, то складывать их придется уже не с помощью #'+.

anonymous
()
Ответ на: комментарий от tailgunner

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

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

Ну вот еще.

Анонимность - способ избежать предвзятости ;-)

anonymous
()
Ответ на: комментарий от anonymous

>Только у тебя враппер неправильный - он возвращает не то же самое, что врапнутая функция (а то, что отдает format).

Несложно сделать так, чтобы был результат непосредственно функции и формат одновременно. Возвратить результат (apply...) не только в format, но и как результат (print-function...) :)

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

(defun foo (x y) (values (* x y) (+ x y)))

Но все возможные варианты сделать можно.

Zubok ★★★★★
()
Ответ на: комментарий от anonymous

> Согласен. В lisp'е как раз не хватает порой гибкости stl. В lisp'е если я определил новый тип-контейнер, то мне придется писать все эти map, reduce, remove, ... с нуля. И имена у них будут уже другими. Это минус.

Справедливости ради, это ("другие имена") можно излечить макросами, вроде бы. Писать алгоритмы - да, таки придется, имхо.

> С другой стороны удобство многих stl-ных алгоритмов (вроде transform) сильно ограничивается отсутсвием в плюсах хоть сколько-нибудь адекватного аналога lambda.

Угу. boost::lambda - это непонятно для кого сделано, пользоваться невозможно, и тормозит потом при компиляции со страшной силой...

Но, впрочем, ничто не мешает определять функторы с понятными именами рядом. Плюс можно делать шаблонные функторы, если часто приходиться делать "то же самое, но чуть по-другому" (напр., как я сделал в примере с поиcком файлов).

anonymous
()
Ответ на: комментарий от anonymous

> там в явном виде контейнеры не торчат в интерфейс

А в каком торчят?

> Что тебя удивляет? Что абстрактный интерфейс типа из двух функций лучше, чем просто контейнер подходящих встроенных типов?

Абстрактный? Бугога! Давай попробуем запихнуть в нево чёнть другое?

bugmaker ★★★★☆
()
Ответ на: комментарий от anonymous

> В lisp'е если я определил новый тип-контейнер, то мне придется писать все эти map, reduce, remove, ... с нуля.

Можно пример, когда в лиспе понадобился бы новый тип-контейнер? А в питонос++ он нужен _всегда_,

> И имена у них будут уже другими. Это минус.

Кто запрещяет юзать старые?

bugmaker ★★★★☆
()
Ответ на: комментарий от Zubok

> > Только у тебя враппер неправильный - он возвращает не то же самое, что врапнутая функция (а то, что отдает format).

> Несложно сделать так, чтобы был результат непосредственно функции и формат одновременно. Возвратить результат (apply...) не только в format, но и как результат (print-function...) :)

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

Но на любом языке с динамической типизацией (или type inference) - никаких проблем.

anonymous
()
Ответ на: комментарий от redvasily

> Bugmaker, написал тебе я прогу.
> #!/usr/bin/env python

$ python files.py add
Traceback (most recent call last):
File "files.py", line 105, in ?
main()
File "files.py", line 71, in main
filedb.add('/home/vasily/pic/zombieeuiip.jpg', 31558)
File "files.py", line 48, in add
self.flush()
File "files.py", line 42, in flush
sqlalchemy.objectstore.get_session().flush()
File "/usr/lib64/python2.4/site-packages/sqlalchemy/mods/threadlocal.py", line 29, in __getattr__
return getattr(self.context.current, name)
AttributeError: 'Session' object has no attribute 'get_session'

Что не так?

eugine_kosenko ★★★
()
Ответ на: комментарий от eugine_kosenko

> Что не так?

Не знаю. Какая версия sqlachemy?

Проверял на python 2.4.3 и sqlalchemy 0.2.3 и 0.2.6

Ещё нужен pysqlite (у меня 2.1.3)

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

redvasily
()
Ответ на: комментарий от anonymous

>Также в лиспе нельзя доопределить новый численный тип и перегрузить
 #'+, #'*, ... для него. К примеру, если мне нужны кватернионы, то 
складывать их придется уже не с помощью #'+.

Вообще-то можно, но крайне не рекомендуется. Я считаю, что перегрузка 
стандартных операторов -- это зло. Как-то раз svu выступал в споре C 
vs C++ насчет того, как где-то, где он работал, вставали на эти грабли
 (речь шла о большом проекте). Так, а теперь LISP.

Я точно не смотрел, разрешена ли перегрузка стандартных операторов в 
стандарте или это implementation feature. Изначально в SBCL и CLISP 
(где я попробовал) это заблокировано (что правильно), но можно 
разблокировать принудительно:

*(defun < (x y) (+ x y))

STYLE-WARNING: redefining < in DEFUN

debugger invoked on a SYMBOL-PACKAGE-LOCKED-ERROR in thread #<THREAD "initial thread" {A7BF489}>:
  Lock on package COMMON-LISP violated when setting fdefinition of <.
See also:
  The SBCL Manual, Node "Package Locks"
  The ANSI Standard, Section 11.1.2.1.2

Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [CONTINUE      ] Ignore the package lock.
  1: [IGNORE-ALL    ] Ignore all package locks in the context of this operation.
  2: [UNLOCK-PACKAGE] Unlock the package.
  3: [ABORT         ] Exit debugger, returning to top level.

(PACKAGE-LOCK-VIOLATION #<PACKAGE "COMMON-LISP">)
0] 0

<
* (< 1 2)

3
* 

Zubok ★★★★★
()
Ответ на: комментарий от bugmaker

>Можно пример, когда в лиспе понадобился бы новый тип-контейнер?

Легко. Например, я пишу продвинутую библиотеку обработки графов. Например, мне часто надо обрабатывать множество инцидентных дуг и/или смежных узлов. Но я не хочу привязывать способ кодирования графов к какому-либо встроенному типу. Например лисповый однонаправленный список и vector меня не устраивaют из-за медленного remove. Hashtable тоже меня может не устроить из-за бОльшего оверхеда и/или если мне нужно позволять кратные дуги. Если мне важна производительность, то встроенные типы в чистом виде не подойдут.

В таком случае правильное решение: сделать абстрактный тип --- множество дуг/узлов, определить операции над ним, и иметь возможность пользовать разную реализацию (в том числе и ultimate-performance) этого абстрактного типа.

Что касается юзания map, reduce, ... для других операций, то одних лишь макросов тут недостаточно. Надо значала сделать (shadow 'map), и затем уже либо макросами (что не очень хорошо), либо своей реализацией map + define-compiler-macro для случаев, когда обрабатываем встроенные типы.

anonymous
()
Ответ на: комментарий от anonymous

> Что касается юзания map, reduce, ... для других операций, то одних лишь макросов тут недостаточно. Надо значала сделать (shadow 'map), и затем уже либо макросами (что не очень хорошо), либо своей реализацией map + define-compiler-macro для случаев, когда обрабатываем встроенные типы.

Этот-же подход можно юзать и для #'+.

anonymous
()
Ответ на: комментарий от redvasily

> Bugmaker, написал тебе я прогу.

Я хоть и не бугмакер и даже не лиспер, но тоже решил попробовать свои
силы. Результаты примерно следующие:

(asdf:operate 'asdf:load-op 'clsql-sqlite3)
(in-package clsql)
(locally-enable-sql-reader-syntax)

(def-view-class file () 
  ((id   :type integer 
         :db-kind :key
         :db-constraints :primary-key
         :initarg :id)
   (dir  :type (string 1000) 
         :initarg :dir)
   (name :type (string 1000) 
         :initarg :name)
   (size :type integer 
         :initarg :size))
  (:base-table files))

(setq metadata 
   (connect '("files.db") :database-type :sqlite3 :if-exists :old))

; Uncomment this to see DB transactions
; (start-sql-recording :type :both)

(if (not (table-exists-p 'files))
   (create-view-from-class 'file))

(defun make-file (full-name)
  (make-instance 'file
      :dir  (directory-namestring full-name)
      :name (file-namestring full-name)))

(defun get-file (full-name)
  (cond ((caar (select 'file
                       :where [and 
                                 [= [slot-value 'file 'dir] (directory-namestring full-name)]
                                 [= [slot-value 'file 'name] (file-namestring full-name)]
                              ])))
        (t (make-file full-name))))

(defun add-file (full-name size) 
   (update-records-from-instance (progn (setq f (get-file full-name))
                                 (setf (slot-value f 'size) size)
                                 f)))

(defun del-file (full-name)
  (delete-instance-records (get-file full-name)))

(defun del-file2 (full-name)
  (delete-records 
        :from [files] 
        :where [and 
                  [= [dir]  (directory-namestring full-name)]
                  [= [name] (file-namestring full-name)]
               ]))

(defun print-sel-files (&optional (condition [>= [N] 0]))
  (progn (print (if (string= (sql condition) (sql [>= [N] 0])) "All files" (sql condition)))
         (print-query [select [f2 dir] [f1 name] [f1 size] [f1 N] 
                         :from "(select name, size, count(*) N from files group by name, size) f1, files f2"
                         :where [and 
                                   [= [f1 name] [f2 name]] 
                                   [= [f1 size] [f2 size]]
                                   condition
                                ]
                         :order-by '(([N] :desc) ([f2 dir] :asc))
                      ]
                      :titles '("DIR" "NAME" "SIZE" "COUNT"))
         (terpri)))

(defun main (action)
  (cond ((eq action :add)
         (add-file "/home/vasily/pic/zombieeuiip.jpg" 31558)
         (add-file "/home/vasily/zombieeuiip.jpg" 31558)
        
         (add-file "/home/vasily/pic/sars.jpg" 19311)
         (add-file "/home/vasily/sars.jpg" 19311)
         (add-file "/home/vasily/junk/sars.jpg" 19311)
       
         (add-file "/home/vasily/pic/pic6.jpg" 29638)
         (add-file "/home/vasily/pic/pic8.jpg" 17577))
    
        ((eq action :delete)
         (del-file2 "/home/vasily/pic/zombieeuiip.jpg"))

        ((eq action :select)
         (print-sel-files)
         (print-sel-files [> [N] 2])
         (print-sel-files [<> [N] 2])
         (print-sel-files [< [N] 3]))))

Конечно, не шедевр, но как для начинающего, ИМХО, неплохо. Ибо
намешано в кучу и лисп, и его классы, и биндинг к clsql и sqlite (я
работал только с MySQL). Кроме того, так и не понял, как работает
sqlachemy в Питоне (тоже до сих пор с этим не работал), поэтому
постарался следовать не букве, а духу.

Увы, так и не понял, как получить значения параметров командной
строки, и как вообще вызывать . Поэтому сделал функцию main, которая
принимает один из трех символов -- :add, :delete и :select.

Кроме того, не получилось завести автоматическое удаление записей по
экземпляру, посему пришлось сделать две функции удаления записей --
правильную (del-file) и "обходняк" (del-file2). То есть, если
следовать документации, то достаточно del-file, который удаляет
запись через экземпляр. Однако, при обращении к базе clsql формирует
безусловный "DELETE FROM FILES", и таблица, понятное дело, очищается
полностью. Один или два раза мне удалось получить запрос типа "DELETE
FROM FILES WHERE FILES.ID=NULL", поэтому я решил, что это как-то
связано с формированием первичного ключа объекта, о чем в следующем
абзаце. "Обходное" решение просто строит sql-запрос и выполняет его.

Не знаю, для чего именно тут нужен суррогатный первичный ключ, но я
его тоже создал. По идее, он должен был упростить запрос к базе на
удаление записей, но это у меня не вышло. Поэтому пришлось
использовать актуальный ключ для удаления, что слегка тяжеловесно. К
сожалению, у меня также не получилось запустить автогенерацию
суррогатного ключа. Я так понял, что это фишка sqlite, потому как
если хранилище создать с помощью питоньей программы, то дальше ключи
генерируются автоматически. Но как это записать в виде sql-синтаксиса
для sqlite, а тем более, на clsql, я так и не понял. Может быть,
знающие товарищи меня просветят.

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

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

eugine_kosenko ★★★
()
Ответ на: комментарий от redvasily

> Проверял на python 2.4.3 и sqlalchemy 0.2.3 и 0.2.6
> Ещё нужен pysqlite (у меня 2.1.3)

python 2.4.3-r4
sqlalchemy 0.2.8
pysqlite 2.3.1

Все на Gentoo amd64.

> Дай мыло, скину исходник

eugine dot kosenko at gmail dot com

eugine_kosenko ★★★
()
Ответ на: комментарий от anonymous

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

ну ведь не хотиш, а не неможеш. А в <подставь сам> захотиш, а нету. Придёцо создавать.

> В таком случае правильное решение: сделать абстрактный тип

А зачем тебе _в_этом_ случяе абстрактный тип? Слелай конкретный тип - "супер-пупер-навороченое-граф-с-сверхбыстрым-удалением" и высокоуровневые операции с им: добавить узел, итд.

> Что касается юзания map, reduce, ... для других операций, то одних лишь макросов тут недостаточно.

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

> Надо значала сделать (shadow 'map), и затем уже либо макросами (что не очень хорошо), либо своей реализацией map + define-compiler-macro для случаев, когда обрабатываем встроенные типы.

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

bugmaker ★★★★☆
()
Ответ на: комментарий от anonymous

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

Кстати, тему профилирования лисп-кода мы так и не раскрыли. А то с чего можно узнать, в каком месте нужна декларация типов?

eugine_kosenko ★★★
()
Ответ на: комментарий от anonymous

> По shootout - где-то вдвое. Я не заметил. 30-50% где-то. Да и сам benchmark я бы не назвал нормальным. Только что взглянул на 3 теста.

binary-trees --- явно benchmark explicit malloc/free vs. GC. У них sbcl не намного опережает gcc (который юзает malloc/free). Я у себя немного дооптимизировал CL-версию (там не хватало type declarations) и получил превосходство SBCL над gcc в 2 раза. Этот бенчмарк демонстрирует превосходство GC над malloc/free на некоторых задачах. Надо будет попробовать gcc + boehm gc на этой задаче.

pidigits -- SBCL и gcc пользуют разные алгоритмы. При этом gcc (лидер) пользует длинную арифметику из GMP, а SBCL пользует только fixnum'ы и проигрывает (!) даже Python'у (который, работает через bignum'ы). Верятно, кто-то уже пробовал версию алгоритма с bignum'ами для SBCL и получил плохие результаты, но тогда это показывает только то, что в SBCL херово реализованы операции над bignum'ами, а не слабость всего семейства common lisp'ов.

nsievebits -- хороший (ИМО) целочисленный benchmark с тесными циклами. SBCL проигрывает gcc почти в два раза, что можно объяснить херовым качеством низкоуровневых оптимизаций в SBCL (см. ниже). На такой задаче качественный кодогенератор имеет большое значение.

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

> компилятор более зрелый и вылизанный - его уж 20 лет пишут, блин. Я бы не сказал, что он вылизанный. Одного взгляда на (disassemble ...) достаточно, чтобы понять что сколько-нибудь нормальной низкоуровневой оптимизацией (register allocation, instruction scheduling, etc) там и не пахнет. Интересно бы глянуть на проприетраные реализации.

anonymous
()
Ответ на: комментарий от ugoday

> Возьми cl-sql и модифицируй. Не думаю, что это будет очень сложно.

clsql не парсит sql-запросы, он их генерирует. Это две большие разницы.

eugine_kosenko ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.