LINUX.ORG.RU

Пару мыслей о c++ и скобках

 


2

2

Сидя в раздумьях, пришел к интересным мыслям:

1. С++ — это на самом деле не столько язык, сколько инструмент для создания ваших собственных языков. Его элегантность заключается отнюдь не в простоте (слова С++ и простота режут слух своим явным противоречием), а в его потенциальных возможностях. За каждой уродливой проблемой прячется какая-нибудь умная идиома, изящный языковой финт, благодаря которому проблема тает прямо на глазах. Проблема решается так же элегантно, как это сделал бы настоящий язык типа Smalltalk или Lisp, но при этом ваш процессор не дымится от напряжения, а на Уолл-Стрит не растут акции производителей чипов памяти. С++ — вообще не язык. Это мировоззрение или наркотик, меняющий способ мышления.

2. Ревнители частоты языка часто нападают на С++. Они полагают, что высшее достижение современной цивилизации — язык, построенный исключительно из атомов и скобок. По мнению этих террористов от синтаксиса, если простую переменную с первого взгляда невозможно отличить от вызова функции или макроса — это вообще не язык, а шарлатанство для развлечения праздной толпы. К сожалению, теория расходится с практикой. В реальной жизни толпа платит лишь за то, чтобы видеть языки, в которых разные идеи выглядят по-разному. «Простые и последовательные» языки никогда не пользовались особым успехом за стенками академий, а языки с блочной структурой овладели массами. Стоит ли этому удивляться? Ведь компьютерные языки приходится изучать и запоминать, а для этого используется то же серое вещество, с помощью которого мы изучаем и запоминаем естественные языки. Попробуйте-ка назвать хотя бы один естественный язык без существительных, глаголов и скобок! Я бы не рискнул. Все наши познания в лингвистике говорят о том, что эти «плохие» особенности только ускоряют изучение компьютерного языка и делают его более понятным. i++ во всех отношениях действительно понятнее, чем i:=i+1, а x=17+29 читается лучше, нежели (setq x(+17, 29)). Речь идет не о строении компьютерного языка, а скорее о нашем собственном строении. Все уродства С++ — это в основном наши уродства. Когда вы научитесь понимать и любить его странности, когда перестанете беспокоиться о математической стройности, будет сделан ваш первый шаг к достижению элегантности в С++.

Ну если C++ «инструмент для создания ваших собственных языков», то напиши на нём конструкцию

with_finalize {
   some_code1();
   some_code2();
} finalize {
   some_final1();
}

Должно превращаться в что-то вида

{
  class __tmpclass10050042 {
     ~__tmpclass10050042() {
        some_final1();
     }
  } __tmp10050042;
  some_code1();
  some_code2();
}

производимые имена не должны конфликтовать с окружающим кодом.

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

i++ во всех отношениях действительно понятнее, чем i:=i+1, а x=17+29 читается лучше, нежели (setq x(+17, 29))

Эскобар, помоги нам опредлить, что понятнее и что читается лучше!

mentalmenza
()

Все уродства С++ — это в основном наши уродства. Когда вы научитесь понимать и любить его странности, когда перестанете беспокоиться о математической стройности, будет сделан ваш первый шаг к достижению элегантности в С++.

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

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

Зачем finally? Ведь деструкторы объектов, созданных на стеке между throw-catch будут вызванны и смогут сделать то, что ты хотел бы сделать unwind-protect или там finally

knowledge_seeker
() автор топика
Ответ на: комментарий от mashina

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

knowledge_seeker
() автор топика
Ответ на: комментарий от arturpub

С++ интригует своими явными противоречиями. Его гибкость легко превращается в главный источник ошибок. За возможности его расширения не приходится расплачиваться скоростью или объемом кода. Он элегантен в одних руках и опасен в других, прост и сложен одновременно. После нескольких лет работы вы так и не можете решить, восхищаться им или проклинать. Да, настоящий знаток понимает все концепции, лежащие в основе языка и склоняющие чашу весов в его пользу. Эти концепции не видны с первого взгляда; чтобы понять их, необходимо в течение нескольких лет пытаться решать совершенно разные задачи. Некоторые архитектурные парадигмы лучше всего соответствуют конкретным языковым решениям. Их неправильное сочетание обернется хаосом, а правильное — элегантностью.

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

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

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

Зачем finally? Ведь деструкторы объектов, созданных на стеке между throw-catch будут вызванны и смогут сделать то, что ты хотел бы сделать

{
   string s;
   try_finally {
     Process1 p1;
     Process2 p2;
     s = p1.run();
     s = p2.run();
  } finally {
     show_message << "Process result: " << s;
  }
}   

Чей деструктор должен вызывать show_message?

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

мании величия

Это немного есть. Я занимаюсь своим делом профессоинально, всегда находясь в курсе последних, ещё не стандартизированных решений на c++:

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

knowledge_seeker
() автор топика
Ответ на: комментарий от Jetty

иногда бывает. Не все же знают что там не так.

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

Смысл finally в том, чтобы убедиться, что не смотря ни на что, созданные в try объекты уничтожались правильно (скажем, закрывали файловые дескрипторы), так? C++ это умеет, всё зашибись

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

Лол, так и скажи, что С++ обосрался даже finally изобразить, зачем юлить?

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

В реальном коде такого не встретишь..

anonymous
()

Элегантность C++ в том, что писать на нём очень просто, но сначала нужно из него выбросить всё ненужное и написать вместо плохого нужного своё и хорошее же.

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

Смысл finally в том, чтобы убедиться, что не смотря ни на что, созданные в try объекты уничтожались правильно (скажем, закрывали файловые дескрипторы), так? C++ это умеет, всё зашибись

нет, не так. Замени, например, в этой логике закрытие файлового дескриптора на fsync()/fdatasync(). Это тоже сделать можно через RAII, но нужно дополнительно кодить.

mashina ★★★★★
()

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

Язык С++ в корне отличается от всех предыдущих языков программирования. Эти языки отличались друг от друга техническими характеристиками, в то время как в С++ основными характеристиками являются характеристики глобально-этические. Именно поэтому он обладает гармонией, следовательно предохраняет жизнь программистов от стрессов и депрессий

Б.Страуструп, отрывки из доклада о прошлом и будущем С++

anonymous
()

А на самом деле...

Всё это паста из книги Джеффа Элджера «Цепепе фо рил програмерс». Очень интересная книга. Там написано про то, как вместо того, чтобы, собственно, программировать, изобретать всякие там мудрые указатели и прочую фигню. К тому же автор пухнет от собственного ЧСВ и уважает только труп страуса:

Наконец, хочу поблагодарить Бьярна Страуструпа (Bjarne Stroustrup) за то, что он изобрел такой странный язык. О простых, последовательных языках типа SmallTalk неинтересно не то что писать, но даже думать. Если бы в С++ не было всех этих тихих омутов и загадочных правил, пропала бы благодатная почва для авторов, консультантов и прочих личностей вроде вашего покорного слуги. Бьярн, я люблю твой язык... Честное слово, люблю — как Черчилль любил демократию. С++ — худший объектно-ориентированный язык... но остальные еще хуже.

knowledge_seeker
() автор топика
Ответ на: А на самом деле... от knowledge_seeker

Собственно, впечатление такое, что на самую простую фигню c++ кодерам приходится писать тонны кода (который мог бы быть автоматически генерированным, на худой конец). Часть 1, глава 3 («Шаблоны и безопасность типов»), например.

knowledge_seeker
() автор топика
Ответ на: комментарий от arturpub

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

В этом весь лор.

anonymous
()

настоящий язык типа Smalltalk или Lisp
частоты языка

Вы - тролль.

next_time ★★★★★
()

Это не значит, что некоторые элементы дизайна не заслуживают критики.

ados ★★★★★
()

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

Это про Ruby что-ли? При чём тут лисп?

из книги Джеффа Элджера

Он же нуб, зачем ты его читаешь. Ну а цитировать его вообще стрёмно в приличном обществе.

Сидя в раздумьях

Это была твоя ошибка. Старайся впредь в такой просак не попадать.

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

Вот код из реального проекта (weblocks-dev/src/request-handler.lisp)

(unwind-protect
        (let* ((timings nil)
               (*timing-level* 0)
               (*timing-report-fn* (lambda (name real cpu)
                                     (setf timings (acons name (list real cpu *timing-level*) timings))))
               (result (timing "handle-client-request"
                         (call-next-method))))
          (dolist (timing timings)
            (dotimes (i (cadddr timing))
              (write "  " :escape nil))
            (finish-output)
            (format t "~A time (real/cpu): ~F/~F~%" (car timing)
                    (cadr timing) (caddr timing)))
          result)
        (webapp-update-thread-status "Request complete/idle"))

То есть

try {
   // вызвать все обработчики запроса
} finally {
   // обновить состояние webapp
}

А на C++ приходится для этого придумывать именованный(!) класс.

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

можно точно так же написать функцию:

#include <iostream>
using namespace std;

template<typename T, typename U> inline
void unwind_protect( T protect, U cleanup )
{
    try
    {
        protect();
    }
    catch(...)
    {
        cleanup();
        throw;
    }

    cleanup();
}

int main() {
    unwind_protect(
        []() { throw 1; },
        []() { cout << "cleanup\n"; } );
}

если хочешь можешь макросы добавить:

#define protect(...) unwind_protect( [&]() { __VA_ARGS__; }
#define cleanup(...) , [&]() { __VA_ARGS__; } );

int main() {
    protect(
        cout << "test\n";
        throw 1;
    )
    cleanup(
        cout << "cleanup\n"
    )
}
wota ★★
()
Последнее исправление: wota (всего исправлений: 1)
Ответ на: комментарий от wota

Прикольно. Новый C++ уже почти можно использовать.

А

int main() {
    int i = 0;
    unwind_protect(
        []() { cout << 1/i; },
        []() { cout << "cleanup\n"; } );
}

скомпилируется? В смысле, область видимости переменной i внутрь этой конструкции попадёт?

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

надо [&] вместо [], в варианте с макросами он сразу есть

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

Что-то такого вида?

#include <iostream>

template <typename T>
struct AtExit
{
    AtExit(T thunk) : thunk(thunk) {}
    ~AtExit() { thunk(); }
private:
    T thunk;
};

template<typename R, typename T, typename U>
inline
R unwind_protect(T protect, U cleanup)
{
    try
    {
    	AtExit<U> make(cleanup);
        return protect();
    }
    catch (...)
    {
        throw;
    }
}

int main()
{
    unwind_protect<void>([]{ std::cout << "A"; },
                         []{ std::cout << "B"; });
}
Я С++11 знаю плохо, но от явного указания возвращаемого значения, думаю, никак не избавиться. Скажите спасибо неявным кастам.

ilammy ★★★
()

а в его потенциальных возможностях.

Слабенько там с возможностями.

Miguel ★★★★★
()

ТС цитирует Элджера в переводе, а в комментах разворачивается лиспосрач. Эталонный вброс. Зачёт.

Очередное свидетельство, что лоропони ничего не читают и ничего не знают.

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

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

Собственно, впечатление такое, что на самую простую фигню c++ кодерам приходится писать тонны кода (который мог бы быть автоматически генерированным, на худой конец).

Просто на самом деле кресты — это такой кривой, испохабленный недохасскель, реализованный в синтаксисе от кросплатформенного ассемблера.

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

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

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

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

Прекрасное подтверждение утверждению «i++ во всех отношениях действительно понятнее, чем i:=i+1».

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

Есть, например, BOOST_SCOPE_EXIT.

Там хаки:

GCC 3.3 cannot compile Boost.ScopeExit inside a template (c) http://www.boost.org/doc/libs/1_50_0_beta1/libs/scope_exit/doc/html/scope_exi...

Хотя в целом согласен, при наличии замыканий нужен один шаблонизированный класс на все случаи: template <typename T> struct AtExit ...

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

Есть, например, BOOST_SCOPE_EXIT.

Там хаки:

Только вчера опять попробовал использовать этот BOOST_SCOPE_EXIT. Компилятор пробливался простынёй ошибок. Думаю, ну что там может такого быть? Посмотрел в код - там чёрт ногу сломит. Прогнал через препроцессор с ключом -dD - там гора препроцессорного кода, хрен поймёшь что откуда берётся. Бросил всё и написал тривиальный класс с деструктором, в котором всё что надо происходит. Пиздец, товарищи, как такое говно в буст пропустили?

Вообще, за BOOST_PP надо убивать. Читать и отлаживать код, в котором используется BOOST_PP (например BOOST_SCOPE_EXIT) невозможно.

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

Собственно, впечатление такое, что на самую простую фигню c++ кодерам приходится писать тонны кода (который мог бы быть автоматически генерированным, на худой конец). Часть 1, глава 3 («Шаблоны и безопасность типов»), например.

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

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

Книжка-то старая. Её сейчас нужно подальше засунуть и не доставать.

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

Это быдлокодерам оно никогда не требовалось. Так им ни раньше эту книжку читать не было необходимости, ни сейчас.

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

Чей деструктор должен вызывать show_message?

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

alexeiz
()

Сидя в раздумьях, пришел к интересным мыслям:

...

2. Ревнители частоты языка часто нападают на С++. Они полагают, что высшее достижение современной цивилизации — язык, построенный исключительно из атомов и скобок. По мнению этих террористов от синтаксиса, если простую переменную с первого взгляда невозможно отличить от вызова функции или макроса — это вообще не язык, а шарлатанство для развлечения праздной толпы. ...

Джефф, перелогиньтесь.

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