А это самый главный вопрос и есть при промышленном программировании. Какой язык позволяет сделать проект быстрее и лучше, тот и выбирается для применения.
>в том, чё нужно изготавливать нужные контейнеры вручную вместо >использования готовых?
Поясни поджалуйста как твой ответ соотносится с предыдущей фразой.
Ты неоднакратно заявлял что отсутствие лишних сущностей -- преимущество.
Вот кусок кода. На питоне там нет ни одной лишней сущности, на лиспе целых две. Вместо того чтобы это нормально обсудить ты выдёргиваешь фразы из контекста и отвечаешь на другие части моего сообщения.
> ладно, попробуй. Вот такая конструкция например: "a.name < b.name || a.size < b.size",
> почему в твоей нужно было её заводить вручную а лисповае итак справилось?
Ну, собственно, потому, что в C++ совершенно справедливо не определяется
никаких отношений упорядочения для пользовательских типов.
И не менее справедливо требуется, чтобы такое отношение было определено для типов, являющихся ключами таблицы.
Опять же, то, что в языке нет встроенной абстракции, и то, что он не может ею оперировать - это разные вещи. В лиспе тоже где-то в недрах библиотеки написано что-нибудь вроде того же (хеш-функцию от списков он же не от господа бога получает).
> Или например обращение к элементу хеша по определённому ключю
> _разное_ для тово чёбы добавить директорий туда и извлечь имеющиеся там?
Это неправда. Ты о чем вообще? И класть, и доставать можно
operator[]. Плюс есть разные другие методы. Плюс есть итераторы.
> Почему утя в проге многчисленные size_t, а лисповое без них обходицо?
Потому что у лиспа dynamic typing, а у C++ - static. Это не лучше и не хуже, а просто по-другому.
Кстати, если уж быть совсем строгим, там должно быть off_t (на linux, например, они разные).
> а в лисповом однин хватило "вернуть элементы, удовлетворяющие условью:..."?
Ну если взять boost::lambda - то на C++ будет так же. Не очень красивый синтаксис у нее, да - но таки работает.
Плюс можно было сделать функтор шаблонным, типа так:
template<class TBinaryPredicate> struct test_file_locations {
size_t n;
TBinaryPredicate P;
test_file_locations(size_t N) : n(N) {};
bool operator()(pair< FileId, set<string> > p) {
return !P(p.second.size(), n);
}
};
И потом использовать как:
remove_copy_if(files.begin(), files.end(),
insert_iterator<FileDist>(files_with_2_locs, files_with_2_locs.begin()),
test_file_locations< equal_to<size_t> >(2));
где equal_to можно заменить на less, greater, <whatever>.
Да, вот то, что в STL нету copy_if - это таки баг языка, приходится лишний раз предикат инвертировать.
> программа работает просто замечятельно. Потому что добавление
> происходит алгоритмом обхода дерева каталохов, где повторений нету.
А потом мы добавим в алгоритм обхода разрешение симлинков, и кю.
Короче, тезис о превосходстве лиспа "на порядки" лично мною отвергается. Даже не в разы.
> Добавить в язык альтернативную ОО систему, примерно такую как в первых редакциях С++ (он же С с классами).
Это очень biased, знаешь ли, в сторону лиспа. Потому что дизайнеры C++ и Python специально прибили ОО-систему гвоздями, чтобы она была у всех одинаковая, а не как в Tcl (или Perl). Ну и при разработке C++ уделяли некоторое внимание производительности, поэтому там нельзя нормально сделать "другой" method dispatch. Зато тот, что есть - очень быстрый (особенно по сравнению с CLOS).
А лисперы этого не сделали, реализвав ее средствами метопрограммирования.
> Это покажет гибкость, расширяемость и абстрагируемость ЯП.
> > Логически они будут одинаковы. И на C оно будет такое же, логически
> почему же они тогда не? Готов выклать прогу, логическая длина которой такая же как лисповой, на той же задаче с файлами?
Я утверждаю, что за исключением необходимости реализации некоторых примитивов, не существующих в стандартной библиотеке, сишная программа логически эквивалентна лисповой (особенно если переделать предикат на шаблоны, как я сделал тремя постами выше).
Синтаксически, она, разумеется, сложнее - за счет явной типизации в основном, - но когда ты заменишь файлы на URL-и начнешь искать дубликаты в базе поисковой системы, ты поймешь, что оно нужно не просто так, а для достижения производительности. Потому что работать день и работать неделю - это две большие разницы.
(нет, я не думаю, что программа типа такой справится с 30-ти терабайтной базой Яндекса или не-знаю-уж-какого-размера базой гугля) - но общее соотношение будет типа такого.
> Реализуеш тип специально для своей задачи => не существует достаточно абстрактново готового, который удалось бы использовать, и созданный тоже недостаточно абстрактен, ибо в другой задаче придёцо реализовать _другой_ тип.
Не-а, не так. Любой хаскеллоид тебе расскажет, что много типов под разные задачи - это хорошо и правильно. Главное, чтобы алгоритмы были type-agnostic, и в моей программе это так (ну, кое-где нужно было бы шаблоны добавить - я ж это не для продакшена писали вообще не старался).
А определение типа - это еще и документация. Твоя программа как раз низкоуровневая - она ничего не знает про файлы, она оперирует "списками длиной два из числа и строки", которые непонятно чему соответствуют. А в моей прямо на C++ написано, что "мы идентифицируем файл парой <имя, размер>".
Да, кстати, в этой конкретной задаче я таки мог воспользоваться прямо готовым pair<string, off_t> - для нее все нужное уже есть (operator<, в смысле).
Вот интересно стало, а чем тебе русское слово 'предвзято не угодило? Что ты хотел сказать заменив его английским переводом?
> Потому что дизайнеры C++
Возьми чистый С.
> и Python
Я вот чего-то не пойму. То говорят, что на С++ и змеюке можно легко реализовать любой уровень абстракции, то говорят, что что-то у них гвоздями прибито. Ведь либо одно, либо другое. Либо можно расширить ЯП, либо можно только производить операции над числами.
> очень быстрый (особенно по сравнению с CLOS).
sbcl и cmucl по скорости обгоняют змеюку, как будто у неё вместе с объектной системой хвост к полу прибит гвоздями. Ссылки на тесты я давал выше.
> Я вот чего-то не пойму. То говорят, что на С++ и змеюке можно легко реализовать любой уровень абстракции, то говорят, что что-то у них гвоздями прибито. Ведь либо одно, либо другое. Либо можно расширить ЯП, либо можно только производить операции над числами.
Поясняю. Расширение ЯП и реализация абстракций это непересекающиеся вещи, например в питоне (или C++) я не могу расширять ЯП, но я могу реализовать любой уровень абстракции, благодоря тому что я могу не только производить операции над числами, но и производить операции над объектами.
Кстати, ты выше по топику говорил что если писать на лиспе в ублюдочно-императивном стиле, то выходит фигня. Теперь я вижу что действительно выходит фигня. А в каком стиле надо писать на лиспе чтобы фигня не получалась?
Кстати, хорошее замечание. Вот как PyPy доделают так сразу появится компилируемый питон, и мы тогда догоним и перегоним и CMUCL и SBCL и icc и фортран :-)
> _Любого_ уровня абстракции _нигде_ нельзя реализовать
Может быть. Неважно. Просто получается, что в лиспе достижим гораздо более выскоий уровень абстракции, с высоты которого питон не далеко ушёл от ассемблера.
> В интерпретации или компиляции?
А хрен его знает. Кажется в интерпретации. Сходи по ссылкам и посмотри.
> Вот интересно стало, а чем тебе русское слово 'предвзято не угодило? Что ты хотел сказать заменив его английским переводом?
Да ничем. Просто у меня "забывание слов", а читаю я последнее время больше по-английски. За две секунды русское слова вспомнить не получилось ;)
> Возьми чистый С.
Ну на plain C будет коряво, естественно. Я, собственно, готов согласиться с тем (и даже так и говорил), что Lisp - идеальный полигон для языкостроения, ибо самомодифицируется. Другой вопрос, что на практике это ненужно - проще взять готовое что-то, лишенное ограничений лисп-наследия. Т.е., нивапрос, lazy evaluation на Lisp сделать сильно проще, чем на C - но я лучше сразу Haskell возьму.
Аналогично с объектной системой - для меня необходимость писать на лиспе - недостаток CLOS, перевешивающий все его достоинства. Если мне не хватит перла (что сомнительно) или плюсов - я возьмусь за Smalltalk скорее.
> > _Любого_ уровня абстракции _нигде_ нельзя реализовать
> Может быть. Неважно. Просто получается, что в лиспе достижим гораздо более выскоий уровень абстракции, с высоты которого питон не далеко ушёл от ассемблера.
Пока что это голословные утверждения, что и было доказано сравнением программок про файлы.
Метапрограммирование не является необходимым для абстрагирования, а всего лишь поставляет синтаксический сахар. Пускаясь в сомнительные аналогии, C++ - это сладкий чай, Python или Ruby - это сироп, а Lisp - лимонный сок, но в комплекте с заводом по производству сахарина...
> Метапрограммирование не является необходимым для абстрагирования, а всего лишь поставляет синтаксический сахар.
В Лиспе все его метапрограммные конструкции имеют привычный синтаксис Лиспа - гирлянды скобочек и токенов (вариант переписывания парсера не рассматриваем, ибо мошенничество).
> В Лиспе все его метапрограммные конструкции имеют привычный синтаксис Лиспа - гирлянды скобочек и токенов (вариант переписывания парсера не рассматриваем, ибо мошенничество).
Ну, на самом деле это не совсем так: в принципе, можно оставить одни токены (ну, две скобочки в начале и в конце не считаются ;). Какой-нибудь псевдокобол или псевдобейсик так можно реализовать.
Вот и реализуй уровень абстракции, на котором существуют классы и объекты.
> А в каком стиле надо писать на лиспе чтобы фигня не получалась?
Создаёшь барьеры абстракции. Самый низкий уровень --- имеющиеся типы данных/действия над ними. Следующий уровень --- композиция из имеющихся, скрывающая реализацию. И так далее. В идеале ты доходишь до такого состояния, что фактически лисповая прога является подстрочным переводом с человеческого описания алгоритма. Например алгоритм обхода графа формулируется так:
делаешь шаг
если результат достигнут, то всё.
если результат не достигнут, делаешь ещё шаг
если шагать некуда, то делаешь шаг назад.
если дошагал назад до исходной точки, то ничего
И идеальная лисповая прога на конечном уровне должна быть сформулирована так же (только на английском и со скобочками). И реализовать свой, и понять/изменить чужой алгоритм будет легко.
>А хрен его знает. Кажется в интерпретации. Сходи по ссылкам и посмотри.
Я когда-то давно смотрел, была интерпретация. Это не очень интересно - у меня прги на Питоне в основном исполняют Сишные либы :) А для осталного есть psyco
> P.S. А какого уровня абстракции в лиспе нельзя реализовать?
Напиши-ка мне доказыватель теорем, или переводчик с естественного языка...
Мощность языка все равно ограничена базовыми понятиями, а они у нас пока что у всех одинаковые (ибо, как я уже говорил выше, лямбда-исчисление и машина Тьюринга эквивалентны).
> Создаёшь барьеры абстракции. Самый низкий уровень --- имеющиеся типы данных/действия над ними. Следующий уровень --- композиция из имеющихся, скрывающая реализацию. И так далее. В идеале ты доходишь до такого состояния, что фактически лисповая прога является подстрочным переводом с человеческого описания алгоритма.
Отличное описание. Применимо не только к Лиспу и функциональному программированию, но и процедурному, и объектно-ориентированному, и к другим языкам ;)
> И идеальная лисповая прога на конечном уровне должна быть сформулирована так же (только на английском и со скобочками). И реализовать свой, и понять/изменить чужой алгоритм будет легко.
И ровно то же самое можно сказать про питон или C++. Только в первом случае это будет много коротких строчек, а во втором - много угловых скобочек. И Шо?
> Вот и реализуй уровень абстракции, на котором существуют классы и объекты.
Еще раз: на нормальных языках нет веозможности манипулировать синтаксисом. Хотя, если тебе не лень будет приписывать что-то типа invoke для вызова и defmethod для опеределения метода, и заключать имена классов и методов в кавычки - то тогда это не очень сложно (ну, для простой ОО-системы типа явовской) даже на plain C. Писанины довольно много, правда (строк так тысяча, я думаю - не пробовал), а сложности - никакой. Пользы - еще меньше.
>> В Лиспе все его метапрограммные конструкции имеют привычный синтаксис Лиспа
>Это фигня, главное, что вся моща лиспа будет доступна из того что ты наметопрограммировал.
Я к тому, что вот здесь - одно из ограничений уровня абстракции. Если мне нужен язык с другим синтаксисом, Лисп этого не может (вариант с перекрыванием парсера не рассматриваем).
> Отличное описание. Применимо не только к Лиспу и функциональному программированию, но и процедурному, и объектно-ориентированному, и к другим языкам ;)
Аха. Называется проектированием снизу вверх. Тока одна беда есть: если сильно увлечься, то можно никогда не добраться до цели. Похоже, в Лиспе именно так и происходит.
> Какие недостатки ты нашёл в CLOS, которые перевешивают его достоинства (кроме скорости)? Или опять "не привычно"?
Тела методов придется писать на лиспе, и императивную обвязку (без которой - никуда, хотя бы - прочитать-выдать данные, или обслуживать запросы, или еще чего) - тоже. А я не хочу. Я лучше Class::MOP перловый заюзаю...
> Та самая. Только твои сведения устарели - когда я смотрел, уже всего в 10 раз. Начальный этап разработки...
Вот как раз неделю назад играл с этим PyPy. Откомпилённый бинарник pypy-c по результатам PyStone у меня отставал от обычного питона раз в 5. То есть можно считать, что чистый C по сравнению с RPython'ом даёт выигрыш в 5 раз. С одной стороны, неплохо, но с другой стороны, RPython - это далеко не Python. :) И тот же OCaml, при сравнимых возможностях, думаю, всегда будет быстрее.
> Я к тому, что вот здесь - одно из ограничений уровня абстракции. Если мне нужен язык с другим синтаксисом, Лисп этого не может (вариант с перекрыванием парсера не рассматриваем).
Не догнал. Какой язык даст тебе изменение синтаксиа? И почему перекрывание парсера не рассматриваем? Тогда от CL останется LISP CAR CDR. Так что это "одно из ограничений уровня абстракции" во всех остальных языках, а лисп дает тебе хоть какую-то возможность "выпрыгнуть" из этого. А ты ещё и не доволен :)
> Аха. Называется проектированием снизу вверх. Тока одна беда есть: если сильно увлечься, то можно никогда не добраться до цели. Похоже, в Лиспе именно так и происходит.
Неа, в лиспе чаще идут "сверху вниз", но таки да - иногда до конца не доходят :)
> Такую возможность дает любой язык, на котором можно написать парсер.
Но ни один язык не даст тебе "это" клеить в любом месте в любое время, хоть внутри единственной функции, где этот-же синтаксис и будет использоваться... +debug + stepping - короче "как до Пекина раком..."
Мне казалось, что входом компилятора в PyPy планируется _любое_ подмножество Python, в том числе и полный Python. RPython - это язык реализации самого PyPy.
Я в курсе. А ты реализуй ещё раз. Может GvR расчуствуется выкинет свою реализацию и возьмёт твою?
> А разве это не императивщина?
Я придерживаюсь такой терминологии: если заостряется внимание на том что нужно делать, то это декларативщина, а если на том как мы это будем делать, то императивщина. Естественно любая реальная прога будет содержать как декларативную, так и императивную составляющую. Приведённый алгоритм декларативен, так как он состоит из фраз уровня 'делай шаг, а не 'вычисли адрес указателя.
> В случае лиспа нет "твоего языка" - это всё по-прежнему лисп!!!!! Ну, дошло?!
Да что ты такой эмоциональный? Нет, не дошло. Пример - я реализовал парсер Си, и подключил его в Лисп. Насколько я понимаю, ядро Лиспа просто вызовет мой парсер в нужный момент, и парсер отдаст ядру странслированный код на Лиспе. Так? Если да, то ядро не видит кода с Сишным синтаксисом вообще, о каком debug на уровне Си-кода можно говорить?