LINUX.ORG.RU

Бьёрн Страуструп выбирает борщ: «С++ почти так же быстр как Haskell»

 , , , ,


13

10

В дополнение к предыдущему посту о сферах применимости С++ и шедевральному посту об ооп (в данный момент продолжающегося обсуждением топологии Скотта).

(credits: гугля материалы о лиспе, случайно наткнулся на вот такой пост в ЖЖ, откуда я невозбранно изъял множество текста для написания этого сообщения.)

Итак, виновник торжества, этот пдф: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3449.pdf

Автор С++, преподобный Страуструп, и команда отчаянных друзей-борщевиков пишут новую библиотеку для диспетчеризации по типам с помощью внешней интроспекции. Это либа, написанная на шаблонах С++x11, и называется Mach7 (почти как вот эти няшные автомобильчики)

Вот, собственно, что так хочет видеть в крестах сам преподобный Бьорн:

int eval (const Expr& e)
{
    Match(e)
    Case(const Value& x) return x.value;
    Case(const Plus& x) return eval (x.e1)+eval(x.e2);
    Case(const Minus& x) return eval(x.e1)−eval(x.e2);
    Case(const Times& x) return eval(x.e1)∗eval(x.e2);
    Case(const Divide& x) return eval(x.e1)/eval (x.e2);
    EndMatch
}

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

struct Expr { virtual int eval () = 0; };
struct Value : Expr { ⋯ int eval (); int value ; };
struct Plus : Expr { ⋯ Expr& e1; Expr& e2; };

но более открытый (читай: расширяемый) дизайн заключается в другом:

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

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

Насколько быстро теперь работает? Говорят, примерно как OCaml или Haskell:

Библиотека реализована как стандартный C++11 код с шаблонным мета-программированием и несколькими макросами. Оно работает примерно также быстро, как эквиваленты на OCaml или Haskell, и даже иногда приближается по быстродействию или даже становится быстрее написанного руками C++ кода, который использует Visitor дизайн-паттерн.

Ну это хорошо, что так быстро, как OCaml или Haskell. Вопрос, зачем при таком раскладе использовать C++, замнём для ясности.

Но дальше вообще прелесть идёт: критика паттерна Visitor!

Библиотека Mach7 и идеи в ней были мотивирована нашим неудовлетворительным опытом работы с различными C++-ными фронт-эндами и фреймворками для анализа программ. Проблема была не с самими фреймворками, но с фактом, что мы должны были использовать шаблон проектирования Visitor для того, чтобы смотреть, обходить и обогощать абстрактные синтаксические деревья целевых языков. Мы нашли Visitor-шаблоны неподходящими для прямого выражения логики приложения, удивительно сложными для обучения студентов, и часто более медленными, чем решения для обхода, написанные вручную. Вместо них, пользователи опирались на динамические приведения типов во многих местах, часто многоуровневые, таким образом предпочитая более короткий, более ясный, и более прямой код, нежели чем Visitor'ы. Соответствующий проигрыш в производительности был обычно незамечаем до более поздних стадий кодирования, когда уже было поздно что-то менять.

Ну можно поздравить C++, теперь можно на нём отдельные вещи писать почти так же коротко, ясно и почти так же быстро, как на OCaml.

В пдф по ссылке присутствуют графики сравнения перфоманса Хацкеля и Крестов, начертанные самим преподобным Бьорном, очень рекомендованные к просмотру для тех, кто еще не готов отречься от старых убеждений и перейти на новые.

Заметим, что не только Страуструп раскаялся в прошлом. Кармак с энтузиазмом рассказывает, как с головой погрузился в Haskell и Scheme, объясняет, почему хаскель невероятно крут и почему сегодня он бы, вероятно, сделал QuakeScheme вместо QuakeC. Он пишет на хаскеле порт wolf3D. (видео на ютубе — Quakecon 2013, обсуждение в толксах)

Пора задуматься о жизни, господа и дамы крестопоклонники.

★★★★☆

Последнее исправление: stevejobs (всего исправлений: 1)

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

См. Бьёрн Страуструп выбирает борщ: «С++ почти так же быстр как Haskell» (комментарий) На самом деле, под использованную автором формулировку можно подвести любой вопрос на тему «а как это работает» и «как бы Вы реализовали...»

На примерах «с бабочками» с ними, что-ли, собеседования проводить? Чай не в группу коррекции отбираем.

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

Где ты здесь студентов увидел?

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

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

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

geekless ★★
()
Последнее исправление: geekless (всего исправлений: 1)
Ответ на: комментарий от AlexM

На одном из собеседований таких, как Вы выразились, «рубистов» контрольным в голову был вопрос «сколько будет 2^8».

Как говорил мой преподаватель по аналитической геометрии, когда оставалось только раскрыть все (аналитические символьные, не числовые) выражения, чтобы получить желаемый результат теоремы: «дальше бухгалтерия осталась.» А потом просто записывал окончательный результат :)

Это я к тому, что «бухгалтерия» и математика - вещи иногда сильно разные. Математик не обязан знать, чему равно 2^8. Не его барское это дело. Что касается программистов, то там надо смотреть. Системные кулхацкеры обычно знают. Прикладник может и не знать заранее.

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

1) Под «деталями реализации» подразумевалось устройство конкретно array.sort на конкретной платформе. Вообще, спрашивать это имело бы смысл, если бы это не был ruby
2) «Интересные алгоритмические задачи» интересны в первую очередь математикам. Хакинг компьютерного софта и математика — это не одно и то же. То, что их якобы запихали под один термин «computer science» еще ничего не значит. Вряд ли рубист-хакер будет математиком, очень вряд ли «интересные алгоритмические задачи» будут интересны для него хоть сколько-нибудь.
3) Новую сортировку ты изобрести не сможешь.
4) Новую реализацию — тоже (скорее всего, всё что ты придумаешь, уже написал кто-то гораздо более умный давным-давно)
5) Приведение задачи к виду, пригодному для обработки готовыми алгоритмами — более дешевая операция, чем придумывание новых алгоритмов
6) Из этого вывод, что чем дрючить людей сортировками и «интересными алгоритмическими задачами», гораздо более правильный критерий оценки — дать человеку в руки компьютер с интернетом, и попросить решить реальную задачу на реальных условиях. Способы, которыми он может достичь результата, могу поразить :3

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

На примерах «с бабочками» с ними, что-ли, собеседования проводить?

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

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

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

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

Может, гипотетический рубист охеренно разбирается в алгоритмах,

Такое, конечно, нечасто бывает, но случается. И некоторых из них нам даже удалось к себе заманить.

но работодатель никогда об этом не узнает, потому что тупой.

Вот тут, собственно, и вопрос: работодатель действительно тупой, или он в лице своей зондеркоманды своих собеседователей не удосужился обернуть свой интерес в «яркую привлекательную оболочку»?

Потому что, повторюсь, с моей точки зрения, данный вопрос - элементарный вопрос на чистую алгоритмику, не столько способ вытянуть из человека какие-то сокровенные знания, сколько заставить его порассуждать логически и, если так можно выразиться, «алгоритмически», посмотреть, как он будет доводить до ума свою первоначальную идею.

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

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

Этюды давайте решать :)

Э-э-э, ты считаешь, порог вхождения ниже? А чем выше порог, тем громче вопли на несправедливость оценок.

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

1) Под «деталями реализации» подразумевалось устройство конкретно array.sort на конкретной платформе. Вообще, спрашивать это имело бы смысл, если бы это не был ruby

А, ну, ладно, приношу извинения.

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

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

Впрочем, и такой способ практикуется, пару часов назад отбушевала, тыкскыть, летняя программистская школа. Студенты за две недели занятий/работ почти реализовали следующую версию нашего продукта ;-) Ну, не совсем, конечно ;-) И всего-то ценой бесплатной кормёжки всякими няшками и нервным тиком у товарища - их преподавателя.

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

Ни. Это только та сторона ума, которая ответственна за анализ. Ум заметно многограннее.

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

Методика в данном случае одна - на как можно более простых и не требующих специальных знаний и примерах понять, способен ли человек разобраться и решить незнакомые ему задачи, от анализа входных данных и ограничений до чёткого изложения своих придумок. Причём, в процессе нужно обращаться с человеком как можно мягче и осторожнее, потому как «психология», «стресс».

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

AlexM ★★★★★
()
Последнее исправление: AlexM (всего исправлений: 1)
Ответ на: комментарий от AlexM

Чгря, сортировка в моём понимании является настолько чистой алгоритмикой, что мне затруднительно придумать, какие там могут быть «детали реализации»

Если говорить о рубях, то любые, начиная от стоимости вызова операции сравнения и заканчивая особенностями алгоритма на конкретной реализации транслятора. Фишка же в том, что все они несущественны. (Пока конкретная задача явным образом не покажет обратное!) Более того, во многих случаях несущественно даже O() алгоритма. Как часто производительность типичного приложения на руби упирается в скорость сортировки? Примерно никогда. Критичные по времени сортировки выполняет СУБД.

Программирование — это, как ни крути, прежде всего практическая деятельность, называемая обычно скучным словом «работа». И чтобы обнаружить что-то полезное о свойствах соискателя, надо посмотреть, как он работает. Это гораздо больше о человеке скажет, чем задавание бессмысленных вопросов.

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

5) Приведение задачи к виду, пригодному для обработки готовыми алгоритмами — более дешевая операция, чем придумывание новых алгоритмов

Опять же, более дешёвая для чего? Если решение существует в единственном экземпляре на сервере, в котором 64 ядра и я уже не знаю сколько памяти (последний раз, я слышал, было за сотню гигабайтов), то да, чем быстрее придумаешь, тем, наверное, лучше. Генетические алгоритмы в реальной жизни, тыкскыть.

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

А насчёт того, нужна ли рубистам математика - есть такая хреновина как редмайн... :)

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

Как часто производительность типичного приложения на руби

Хвала богам, что у нас нет нужды в создании типичных приложений на руби :)

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

То есть ваши приложения упираются в скорость Enumerable::sort()? Тогда у меня плохие нвоости, вы выбрали не тот язык. :)

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

А вообще, повторюсь, речь не о сортировке как таковой, а о том, чтобы «придумать и реализовать алгоритм, а потом оценить его сильные и слабые стороны». Если есть способы проверить это лучше и надёжнее, буду рад услышать.

Вообще, вопросы подобной методологии лучше, наверное, обсуждать в другом треде. Здесь лучше вернуться к тому, что С++ почти догнал по производительности Хаскель ;)

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

Эм-м-м, да, смешно получилось. Видишь, кто на кого учился ;)

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

«придумать и реализовать алгоритм, а потом оценить его сильные и слабые стороны». Если есть способы проверить это лучше и надёжнее, буду рад услышать.

Дать реальную задачу и посадить за компьютер, имеющий доступ в интернет.

Здесь лучше вернуться к тому, что С++ почти догнал по производительности Хаскель ;)

...а по выразительности — Брейнфак.

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

дешёвая для чего?

емнип, array.sort — это нативный код, который делает quicksort, который в худшем случае преключается на three pivot quicksort, при сильной рекурсии — на пирамидку. Т.е. его сложность в среднем n log n, в худшем - n^2, что простой человеческой интуицией называется «достаточно быстро». Вряд ли можно написать что-то такое, что повысило бы эти показатели в общем случае, как минимум потому, что написанный руками код будет ненативным. Т.е. ответ «достаточно дешевая для всего», и это всё что нужно знать по данному поводу =)

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

Дать реальную задачу и посадить за компьютер, имеющий доступ в интернет.

Повторю - если это будет действительно реальная задача, интересная нам, то сажать нужно будет минимум на пару недель. Наверное, потому что «типичные задачи на руби» нам неинтересны. Если сажать на неинтересную нам задачу, да с готовым решением на хабрахабре, то это вообще какое-то издевательство, как над собеседователями, так и над собеседуемым, перевод времени в нуль. Гуглить мы и сами умеем, у меня персонально специальный сертификат имеется.

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

...а по выразительности — Брейнфак.

Та ла-адна.

AlexM ★★★★★
()
Последнее исправление: AlexM (всего исправлений: 1)
Ответ на: комментарий от AlexM

Если вам нужен такой человек, который будет работать в предметной области, где «разбираются всего 5 человек на глобусе, из которых трое - это я, мой босс и мой кот» — то как-то странно спрашивать про общеизвестные алгоритмы на собеседовании. Там у вас совсем другие соискатели будут, с которыми у вас найдётся о чем поговорить.

Если же цель оценить общий уровень подготовки обычного кодера, то подойдёт любая реальная задача предметной области. Например, для веба это может быть «представьте, что у вас есть Ruby, но нет никаких фреймворков, вам нужно сделать вот такой простой сайт, имеющий вот то-то, то-то и еще вон то; набросайте архитектуру веб-приложения, поясните какие технологии вы будеет использовать, продемонстрируйте работу компонент на макете из двух страничек».

В итоге вы будете знать: какие есть навыки у человека в области проектирования ПО; какие технологии предметной области ему известны (или насколько хорошо он умеет гуглить); насколько чистый код он пишет; насколько хорошо знаком со стандартной библиотекой языка.

geekless ★★
()

QuakeC кстати это просто скриптовый язык для квейка, не то на чем написан движок., поэтому я поддерживаю Кармака в этом вопросе, scheme всяко лучше чем си подходит для скриптования.

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

QuakeC кстати это просто скриптовый язык для квейка

Очень корявый язык, AFAIK. Значения из функций возвращал через глобальные переменные %) И этот человек говорит «я бы запилил Схему!111».

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

Ну и это. Когда я 4 дня назад говорил, что сама логика крестов подталкивает писать с его помощью кривые велосипедные недохаскели.

Так это же модификация (поправка?) 10го правила Гринспуна.

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

что изменилось в планах на викенд? Хочешь помочь Страуструпу? :3

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

возможно ли написать такой стандарт С++, чтобы Microsoft/Eclipse не смогли написать для него автодополнение

Да, c++98, c++03, c++11, и на подходе c++14.

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

tl;dr: главное качества ума — уметь находить суть явлений.

tl;dr, в двух словах — системный подход.

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

Впрочем, и такой способ практикуется, пару часов назад отбушевала, тыкскыть, летняя программистская школа. Студенты за две недели занятий/работ почти реализовали следующую версию нашего продукта ;-) Ну, не совсем, конечно ;-) И всего-то ценой бесплатной кормёжки всякими няшками и нервным тиком у товарища - их преподавателя.

Осталось ещё заключить контракт на передачу авторских прав вам или попросить опубликовать под MIT, и сможете легально этим пользоваться.

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

Зачем людям, которые не интересуются внутренним устройством языка, это знать или даже запоминать? do-нотация спасёт отца русской демократии.

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

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

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

Благородным донам придется ещё немного подождать, пока я не доем мамин борщ

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

Вы чо, серьёзно? :)

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

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

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

Любопытно. Можно и без статьи — своими словами.

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

Сложно запомнить то, чем редко пользуешься. Я и сам бы вряд ли запомнил, если бы не пользовался им не только для IO, но и для Maybe, Either и трансформеров. Просто притворитесь что вы пишете императивный код, где <- и let — это :=.

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

то как-то странно спрашивать про общеизвестные алгоритмы на собеседовании.

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

Понятное дело, что «в нормальном случае», если перед тобой «программист», а не «пользователь фреймворков», вторая и последующая задачка - заметно интереснее. К некоторым «правильного ответа», наверное, не знаем и мы. Тем с большим удовольствием принимаешь на работу человека, который сумел тебя удивить неожиданностью своего решения.

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

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

Ну в нашем городе тоже, но с первого курса.

quiet_readonly ★★★★
()
Последнее исправление: quiet_readonly (всего исправлений: 1)
Ответ на: комментарий от tailgunner

А вот и я

#include <functional>
#include <iostream>

#include <boost/variant.hpp>

template<class T>
struct V: public boost::static_visitor<void> {
    typedef std::function<void (T &t)> F;
    F _f;

    V (F f) : _f (f) {}
    void operator() (T &t) const { _f (t); }

    template<class U>
    void operator() (U &) const {}
};

template<class ADT>
class M {
    ADT &_value;
    
public:
    M (ADT &value) : _value (value) {}

    template<class T>
    void on (typename V<T>::F f) {
        V<T> v (f);
        boost::apply_visitor (v, _value);
    }
};

struct Foo {
    int foo;
};

struct Bar {
    std::string bar;
};

struct Baz {
    bool baz;
};

typedef boost::variant
< Foo
, Bar
, Baz
> FooBarBaz;

void inspect (const FooBarBaz &fbb)
{
    M<const FooBarBaz> m (fbb);
    m.on<const Foo> ([](const Foo &f) {
            std::cout << "Goot a Foo! " << f.foo << std::endl;
        });
    m.on<const Bar> ([](const Bar &b) {
            std::cout << "Goot a Bar! " << b.bar << std::endl;
        });
    m.on<const Baz> ([](const Baz &b) {
            std::cout << "Goot a Baz! " << b.baz << std::endl;
        });
}

int main (int argc, char *argv[])
{
    FooBarBaz foo (Foo {1337});
    FooBarBaz bar (Bar {"Hello LOR!"});
    FooBarBaz baz (Baz {true});
    inspect (foo);
    inspect (bar);
    inspect (baz);
    return 0;
}

~/sources/adtxx $ ./a.out 
Goot a Foo! 1337
Goot a Bar! Hello LOR!
Goot a Baz! 1
yoghurt ★★★★★
()
Ответ на: комментарий от tailgunner

Ты правда считаешь это аналогом кода в хедпосте?

Я ожидал такой ответ :)

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

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

Просто притворитесь что вы пишете императивный код

Вот этот подход и критиковали.

Deleted
()
Ответ на: А вот и я от yoghurt

Сделайте меня развидеть это.

Все копии стандарта — сжечь, разработчиков boost-а — прогнать ссаными тряпками, Страуструпа и комитет — пустить на удобрения.

ЭТО не имеет права на существование.

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

этого во внутреннем устройстве языка и нет

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

А уж как доставляют истории

Можно хотя бы парочку таких историй?

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