• Авторизация


Lisp 25-08-2012 02:18 к комментариям - к полной версии - понравилось!


Lisp, всё-таки, уродский язык. Когда я пишу на нём, постоянно плююсь в его сторону -- просто монстр, а не язык. Но хуже того, когда я пишу не на Lisp'е, я просто бешусь: все остальные дураки, и такие мудаки языки, такое ощущение созданы не для того, чтобы писать программы, а хрен знает для чего.

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

Понравилась пара фишек из boost. Особенно format: долбаный стауструповский метод вывода, прям как writeln в сраном паскале -- совершенно непрактичен. Но boost::format поднимает возможности форматированного вывода C++ на совершенно другой уровень. Если написать десять тыщщ строк нечитабельного C++ кода, то, быть может, можно даже дотянуть его до lisp'овского format'а. По-крайней мере, в C++ есть практически всё что надо для этого: и rtti, и... А, ну да, generic'ов нету, но с учётом статической типизации в 99% случаев хватит и тупенькой перегрузки функций. А, ну да, и rtti не работает на примитивные типы. Но, в общем, и синтаксис форматной строки тупо спиззжен из C -- и это, пожалуй, единственный серьёзный промах разработчиков boost::format. В C этот синтаксис до ужаса примитивен, его хватает для C, в котором нет стандартных типов кроме int, но C++-то ведь покруче будет. Кстати, над обсуждением производительности format в официальной я ржал дольше всего: кого интересно ебёт насколько быстро работают такого рода функции? Все они используются исключительно в user-interface коде, которому насрать на производительность, поскольку у юзера с производительностью всё равно хуже чем у самой медленной реализации format.

Столкнулся с задачкой -- эдакая проходная задачка, надо данные из одного формата (неудобного для меня) перегнать в другой формат. Мне абсолютно при этом было похер сколько времени это преобразование форматов будет производиться. Ну совершенно насрать. Пускай хоть неделю -- главное чтобы не вручную. В результате я полдня возился: из списка отрезков прямых, с координатами, надо было вычленить замкнутые пути. В лиспе, я б загнал этот список в структуру типа список, и потом бы преобразовывал бы этот список (местами in-place, местами создавая новые по мотивам существующих) до тех пор, пока не получил бы в список циклов (каждый из которых опять же был бы списком) и отдельных отрезков (тоже списков). В этом же долбаном C++ явно стандартные библиотеки писались на всю голову больным страуструпом, который не думал ни о чём кроме производительности, и если, блин, рандомный доступ к элементу списка менее эффективен нежели рандомный доступ к элементу массива, значит список не будет иметь операции nth, или в терминах C++ это называется operator[]. Да плевать как называется -- всё равно не будет. Писать самостоятельно этот оператор влом, ну думаю я тогда массив запользую вместо списка. Но как-то я не подумал, что раз в массив вставлять элемент в середину менее эффективно чем в список, то значит массив не будет иметь операции insert... А поскольку не существует линейно упорядоченной структуры, в которую вставлять было бы столь быстро как в список, а рандом-акцесс был бы столь же быстр как в случае с массивом, то C++ не имеет контейнера который бы имел одновременно и insert и operator[]. И при этом C++'овый insert -- это убиться об стену, ему, пилять, итераторы подавай для указания места куда втыкнуть новый элемент надо, просто номера позиции ему мало. То есть даже если меня ниипёт производительность работы кода в данный момент и если мне интересна лишь скорость написания кода, то C++ сделает всё, чтобы заставить меня думать об этой производительности, забивая на скорость написания. Такое ощущение, что для C++ не существует ни одного профайлера, и все бутылочные горлышки C++ программеры ищут просматривая строку за строкой одного сорца за другим, и выискивая всё, что может давать пенальти производительности. Язык C, кстати, в этом смысле более дружелюбен, на нём можно писать забивая на производительность, выигрывая на этом человекочасы.

И в C++ везде так. Ещё до того, как я начал с графами возиться, я писал парсинг XML. Чёт по липовской памяти, я взялся писать SAX парсер: он эффективнее, чем создание DOM модели, а пишется вполпинка. Но то что на лиспе влезает в 50 строк кода и полчаса работы, в случае с C++ выливается в 200 строк и часа четыре. И как раз в процессе написания этого парсера я пришёл к выводу, что мне маловато будет просто переменной хранящей состояние, думаю мне нужен стек. Завёл стек, перехерачиваю весь код под использование стека. Красиво, думаю, выходит. До лаконичности лиспа не дотягивает, но ничётак. И вдруг, ЁПТВАЮМАТЬ, выясняется, что в стек невозможно заглянуть под верхний элемент не снимая этого верхнего элемента со стека: а мне это просто ппцкак необходимо, потому что xml файлик там был спроектирован ещё хуже чем STL, и его распарсить ориентируясь только на локальный контекст было невозможно. Ну вот спрашивается: и нахер такой стек нужен? Даже в системный стек я могу заглянуть глубоко-глубоко, вплоть до фрейма функции libc_start_main добраться, и для этого мне не нужен Lisp, я могу это сделать даже в долбаном C++. А в какой-то сраный библиотечный стек из пидорской STL хуй заглянешь.

Отдельный разговор -- это методы STL-контейнеров типа pop, pop_front, pop_back... Вот какая моча ударила в голову изобретателю этих методов, когда он им в качестве возвращаемого значения приделал void? В результате, там где я мог бы уложить всю логику работы цикла в заголовок for, я вынужден писать while, потому что если пихать в заголовок for все необходимые телодвижения для вынимания одного элемента из контейнера в локальную переменную, то заголовок цикла превращается из заголовка цикла в какую-то непристойность.

Естественно нельзя умолчать про то количество букоф, которое требует любое мал-мальски полезное действие в C++. Мне нужен цикл по массиву -- объявляй переменную типа итератор, но имя типа этого итератора -- это хрен знает что и сбоку бантик. Надо конечно отдать должное макросу foreach из boost, он подчастую спасает, но, сука блядская, не всегда, лишь тогда, когда итерации перебирают элементы последовательно, и на каждой итерации достаточно доступа ровно к одному элементу.

А срань эта с множественным значением возвращаемым из функции? Либо объявляй структуру, либо трахайся пиши десять тысяч букоф подставляя типы в шаблон pair или tuple. Причём объявление структуры-то, пожалуй, потребует меньше буков, нежели typedef на инстанциацию шаблона pair. Я при этом так и не понял: может ли C++ провести декомпозицию тупла. Судя по некоторым фразам в гугле, сложилось впечатление что может, но уточнять уже сил не было.

Но, отвлекаясь от C++ и возвращаясь к Lisp, замечу, что примерно аналогичные эмоции я испытываю при попытке связаться с любым языком. Такое ощущение, что нет программистов, кроме Lisp-программистов, которых в общем устраивает их язык, и поэтому они не сочиняют других языков. А всё остальное население земного шара просто не представляет, даже приблизительно, каким должен быть язык программирования, чтобы на нём можно было бы писать программы. Поэтому они сочиняют один язык за другим, понаплодили уже туеву хучу, но никак не могут создать что-нибудь пристойное.
вверх^ к полной версии понравилось! в evernote


Вы сейчас не можете прокомментировать это сообщение.

Дневник Lisp | rgo - Дневник rgo | Лента друзей rgo / Полная версия Добавить в друзья Страницы: раньше»