LINUX.ORG.RU

D, Go и Rust, взлетит ли что-нибудь?

 , , , ,


4

8

Привет, LOR. На данный момент в окружающее пространство уже некоторое время накатывает следующая мысль: «Разработчикам прикладного ПО, использующим в своей практике Си и C++, крайне необходимо облегчить жизнь, избавив от ошибок с памятью и предоставив удобные механизмы для параллельного программирования». Одни адепты, этакие Базаровы от программирования, предлагают воплощать задумку с помощью новых языков: D, Go и Rust. Другие же, коих пока явно больше, всячески не желают выходить из своей зоны комфорта, предлагая включать необходимое в новые стандарты уже используемых инструментов.

Как думаешь, садиться ли уже сейчас за изучение одного из убийц Си/C++, чтобы через 5 лет не оказаться на обочине индустрии, или же все продолжит идти в старом русле с незначительными вливаниями новшеств?

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

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

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

кому такой нужен? людям нужен «эксперт» по оракл дб или «эксперт» по scala+akka или «эксперт» по java+spring или «эксперт» по javascript/angularjs

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

кому такой нужен?

Тасщемта всем. А ««эксперт» по оракл» это рабочий на конвеере

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

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

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

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

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

panic! валит только текущий поток. Автор racer пользовался этим, потому что разборщик синтаксиса выдавал именно панику на невалидный код. Вот так пишешь код, а IDE память отжирает и отжирает.

Печалька. :( Надеюсь, это решение временное.

Предлагалось, кстати, сделать panic! unsafe.

Предлагается вообще много всякого. Присоединяюсь к тому, что это бессмысленно.

ozkriff
()

садиться ли уже сейчас за изучение одного из убийц Си/C++,

Надо писать на Java и тогда вы будете в мейнстриме и через 5, и через 10, и через 30 лет.

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

Вот, допустим, ответ на SO по теме разговора - http://gamedev.stackexchange.com/a/46427 . Там и битсквидовские посты тоже упоминаются. Может, SO для тебя не такой пустой звук? :)

>> А можно более развернуто?

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

Игровые движки - специфическая задача? Ты серьезно? Как раз типичная для плюсов область применения.

... и на 100500% уверенные в собственной правоте.

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

Так вот мне не понятно, откуда здесь религия берется.

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

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

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

О чем ты? Какой «тот же уровень безопасности» в коде без исключений? Зачем он? Или обрабатываем-пробрасываем ошибку, или грохаем приложение. Вот и вся «гениальная» мысль из вышеупомянутой серии постов.

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

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

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

Вот, допустим, ответ на SO по теме разговора - http://gamedev.stackexchange.com/a/46427 .

ОМГ я сделался не Ъ и сходил по ссылке. Столько тяжелого бреда я давно не читал. Если кратко пересказать «делайте хуже, лишь бы не с исключениями.».

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

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

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

Столько тяжелого бреда я давно не читал.

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

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

Доказать мне, почему по ссылке полный бред, а я (и еще куча людей) ошибаются?

Потому что все твои решения, как и той макаки, которая накалякала статью на SE сводится к тому, что «АААААА исключения!! ОНИ ЖЕ ТЯЖЕЛЫЕ!! давайте вместо этого будем писать 100500 проверок везде и в каждой функции. Пох, что это будет медленнее, зато мы НЕ ИСПОЛЬЗУЕМ исключения!!!». Идиоты, которые пытаются изобрести путь «без исключений» в языке, в котором такой механизм есть и любая сущность МОЖЕТ кинуть исключение, ничуть не лучше идиотов, которые суют try catch в каждую строчку.

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

О чем ты? Какой «тот же уровень безопасности» в коде без исключений? Зачем он? Или обрабатываем-пробрасываем ошибку, или грохаем приложение. Вот и вся «гениальная» мысль из вышеупомянутой серии постов.

Сударь, подумайте на досуге, например, о реализации чего-то вроде Boost.MultiIndex (контейнера, в котором индексацию элементов можно осуществлять по нескольким независимым ключам). Или in-memory database, где к табличке нужно добавить несколько независимых друг от друга индексов.

Такие штуки реализуются в виде нескольких контейнеров, спрятанных от пользователя. Добавление элемента в MultiIndex (или insert into в in-memory БД) будет требовать модификации всех этих контейнеров. Допустим, при вставке нового значения в i-й контейнер происходит ошибка. Что нужно делать с уже модифицированными (i-1) контейнерами?

Это определяется гарантией безопасности:

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

Строгая гарантия сродни транзакционности: возникновение ошибки в процессе операции откатывает все ранее сделанные изменения.

Применительно к примеру с MultiIndex/in-memory-db это означает, что если в i-й внутренний контейнер вставка не прошла из-за ошибки, то нужно откатить вставки в (i-1) предшествующие контейнеры.

В псевдокоде с исключениями это может быть выражено, например, так:

void multi_index::insert( T value )
{
  for( auto c = indexes_.begin(), end = indexes_.end(); c != end; ++c )
  {
    try {
      c->insert_item( value );
    }
    catch( ... ) {
      while( c != indexes_.begin() )
      {
        --c;
        c->remove_item( value );
      }
      throw;
    }
  }
}

В случае с кодами возврата у вас встанет точно такой же вопрос: в каком состоянии вы оставите MultiIndex/in-memory-db — с нарушенными инвариантами или нет. Если инварианты вы собираетесь сохранить, то вам придется делать что-то вроде этого в псевдокоде:

ret_code multi_index::insert( T value )
{
  for( auto c = indexes_.begin(), end = indexes_.end(); c != end; ++c )
  {
    ret_code r = c->insert_item( value );
    if( OK != r )
    {
      while( c != indexes_.begin() )
      {
        --c;
        c->remove_item( value );
      }
      return r;
    }
  }
  return OK;
}

На мой взгляд, тот же фрагмент автопортрета Фаберже, только в профиль. Да еще с опасностью того, что если вы забудете проверить код возврата у insert_item, то в случае ошибки ваш MultiIndex останется в некорректном состоянии.

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

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

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

Да еще с опасностью того, что если вы забудете проверить код возврата

Я вот только месяц назад ковырял такой вот код. Только там еще печальнее было, там «откат» нужен был 5 сущностям и выглядело это как бесконечная лесенка из лесенок условий. Ну и бага была в логической ошибке, просто потому что 24 (!!!) проверки в одной операции вставки и писатель просто перепутал знак.

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

--c;
c->remove_item( value );

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

На мой взгляд, тот же фрагмент автопортрета Фаберже, только в профиль.

Рантайм упростился.

Да еще с опасностью того, что если вы забудете проверить код возврата у insert_item

Компилятор напомнит (в Rust, не в Си++).

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

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

Обычно вещи вроде remove_item реализуют так, чтобы исключения не выбрасывались. Равно как и из деструкторов. Если же это не так, то обращение к remove_item так же можно обернуть в try...catch. Если этого не сделать, то multi_index останется с нарушенными инвариантами.

А для того, чтобы разработчику было проще разобраться что к чему, в C++ введен nothrow.

Рантайм упростился.

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

Компилятор напомнит (в Rust, не в Си++).

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

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

Почему разработчика должна интересовать сложность рантайма используемого им языка программирования?

потому, что иначе получается PHP-макака

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

На мой взгляд, тот же фрагмент автопортрета Фаберже, только в профиль.

Рантайм упростился.

Почему разработчика должна интересовать сложность рантайма используемого им языка программирования?

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

В течении большей части из них мне доводилось пользоваться компиляторами с поддержкой исключений

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

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

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

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

Это твой опыт. У какого-нибыдь ветерана Гугла он другой. У Шустрика - третий.

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

Однако, сильно сомневаюсь, что большинство ратующих за коды возврата вместо исключений в C++, работают именно в таких специфических условиях. Если же условия не специфические, а обычные, то отказ от исключений выглядит как следование каким-то религиозным догмам. Особенно если учесть, что качество реализации механизмов исключений за последние 20 лет серьезно выросло, а накладные расходы на поддержку исключений, снизились. А так же то, что разработчики уже накопили достаточно опыта и те же понятия уровней гарантии безопасности исключений возникли как раз из этого накопмленного опыта. А так же то, что развитие C++ делает работу с исключениями (а так же с их обработкой) все проще и проще.

eao197 ★★★★★
()
Ответ на: комментарий от eao197
impl<K: Hash + Eq + Clone, V: Clone> Database<K, V> {
    pub fn insert(&mut self, key: &K, value: &V) -> Result<(), &`static str> {
        self.try_insert(key, value)
            .map_err(|(err_str, index)| {self.clear_after_error(index, key); err_str})
    }
    fn try_insert(&mut self, key: &K, value: &V) -> Result<(), (&`static str, usize)> {
        for (index, table) in self.tables.iter_mut().enumerate(){
            match table.insert(key.clone(), value.clone()) {
                Err(err_str) => return Err((err_str, index)),
                _ => ()
            }
        }
        Ok(())
    }
    fn clear_after_error(&mut self, table_index: usize, key: &K) {
        for table in self.tables.iter_mut().take(table_index) {
            table.remove(key);
        }
    }
}
anonymous
()
Ответ на: комментарий от anonymous

self.try_insert(key, value)
.map_err(|(err_str, index)| {self.clear_after_error(index, key); err_str})

Во-первых, это еще одно подтверждение того, что о сохранении инвариантов объектов нужно думать даже при работе с кодами ошибок.

Во-вторых, это ну просто пипец какой офигенный прогресс по сравнению с C++. Читабельность, лаконичность и понятность кода улучшилась прям в разы.

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

Зачем врать? Базовая гарантия означает сохранность инвариантов. Конкретное состояние, в котором будет объект, не определено, но он будет валидным.

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

Базовая гарантия означает сохранность инвариантов. Конкретное состояние, в котором будет объект, не определено

Инварианты сохраняются, а состояние не определено? Шизофренично, но пусть так.

При работе с кодами возврата инварианты сохранять не нужно?

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

Инварианты сохраняются, а состояние не определено? Шизофренично, но пусть так.

Не определено, в каком из валидных состояний будет объект. Если инварианты не соблюдены, то гарантии нет никакой.

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

Какой ад. Я так и не понял, какие такие плюшки заставили отказаться от исключений и обрекать программистов на вот это вот...

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

Автор racer пользовался этим, потому что разборщик синтаксиса выдавал именно панику на невалидный код

Кстати, автор racer работает над переработкой парсера по этому поводу: Work towards a non-panicing parser (libsyntax) #23857.

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

... В случае с кодами возврата у вас встанет точно такой же вопрос: в каком состоянии вы оставите
MultiIndex/in-memory-db — с нарушенными инвариантами или нет. ...

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

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

Это не «апелляциями к «авторитетам»», просто не вижу смысла повторять то, что уже хорошо описано в статьях. И я так и не понял, каких конкретно элементарных вещей я, по-твоему, не понимаю :( .

... а еще с опасностью того, что если вы забудете проверить код возврата ...

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

... это ну просто пипец какой офигенный прогресс по сравнению с C++. Читабельность, лаконичность и понятность кода улучшилась прям в разы.

Как выше писал, лаконичность страдает, а вот понятность - улучшается.

А, блин, мне надоело) Ты десятком постов ранее написал «не понятно, откуда здесь религия берется». Я, в основном, на это хотел ответить, а не в подробностях обмусоливать старый срач про исключения.

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

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

Очевидно, что когда исключения противопоставляются кодам возврата, то речь идет о языках, где есть и то, и другое. В данном разговоре о C++. Но, полагаю, аналогичная ситуация будет и в каком-нибудь Ruby или C#. Т.к. в Rust исключений нет, то там и дилеммы такой нет.

И я так и не понял, каких конкретно элементарных вещей я, по-твоему, не понимаю :( .

Вот тех, которые пришлось несколько раз объяснять, прежде чем вы догадались:

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

Ну и вот это:

Только вот я в самом коде сразу видно, когда это надо делать. А с исключениями надо вечно помнить, какая функция что может бросить.

Не правильно. Достаточно знать только о тех функциях, которые не должны бросать исключений (например, swap и деструкторы, а сейчас, может еще и move operator/move constructor, впрочем на счет последних утверждать не буду, т.к. сам еще не разобрался).

eao197 ★★★★★
()
Последнее исправление: eao197 (всего исправлений: 2)
8 февраля 2016 г.
Ответ на: комментарий от tailgunner

Слушай, вот совсем rust не знаю.

Можешь объяснить, как будет в rust происходить обработка такого: открыт файл, перед закрытием файла вызван макрос panic!, файл неплохо бы закрыть.

Компилятор позволит скомпилировать такое? Или руганётся и заставит писать что-то вроде деструктора/продублировать код на закрытие файла?

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

Можешь объяснить, как будет в rust происходить обработка такого: открыт файл, перед закрытием файла вызван макрос panic!, файл неплохо бы закрыть.

AFAIK, File реализует drop (или что-то внутри File реализует drop); drop - это аналог деструктора, panic! вызывает деструкторы.

Компилятор позволит скомпилировать такое?

Да.

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

называть что-то «убийцей си» - глупо. Раст может подвинуть си из системного программирования уровнем «повыше». Для байто*бства и железоспецифичных вещей связка си+асм будет ещё очень долго. Хотя глядя на zinc.rs могу сказать что парням удалось сделать приличной PoC для раста под микроконтроллеры.

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

То есть в расте вручную закрывать файлы не надо?

Сам закроется по панике, либо окончанию зоны видимости (блока)?

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

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

Вообще-то речь шла о Go.

Для байто*бства и железоспецифичных вещей связка си+асм будет ещё очень долго

С этим никто не спорит. Чтобы применение Rust было оправдано, задача должна быть более-менее сложной.

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

То есть в расте вручную закрывать файлы не надо?

Т.е. в Rust файлы автоматически закрываются вызовом drop по истечении срока жизни переменных, которые их представляют. Если этого мало, можно вызывать drop вручную.

Сам закроется по панике, либо окончанию зоны видимости (блока)?

По панике делается раскрутка стека, так что закроется в обоих случаях.

tailgunner ★★★★★
()

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

вы таки думаете, что самая главная их проблема в памяти?

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

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

Это корректно для любого языка, практически.

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

Увы, я пока на C++ только лабаю, так что моё понимание всех этих концепций далеко от идеала.

Deleted
()
Ответ на: комментарий от ckotinko
Главная проблема программирования это не память
...
Главная проблема программирования - это лично ты!
Потому что ты пишешь говно!

Как-то так. А rust по рукам за говнокод бьёт ещё при компиляции.

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

А rust по рукам за говнокод бьёт ещё при компиляции.

Это неправда.

Rust вводит (местами излишние) ограничения на работу с объектами, иногда заставляет явно выписывать время жизни и пр., а потом статически проверяет это дело. Отлавливаются лишь элементарные ошибки. Я пока не понял, насколько это полезно в реальной практике.

А с говнокодом не способен бороться ни один из существующих языков.

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

Что-то последний коммит там был 24 дня назад, а копирайты на сайте вообще 2014 года. Не слишком он живой, вроде бы.

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

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

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

Так если паника раскручивает стек и её можно перехватывать, то чем же она не исключения?

Panic! — аварийное завершение потока. Перехватить можно только в др. потоке.

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

Так если паника раскручивает стек и её можно перехватывать, то чем же она не исключения?

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

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

Я так понимаю, это всё равно, что ловить исключение из main.cpp и при этом не знать тип исключения. Типа мы знаем только, что случилась паника и знаем строчку с которой это вышло, так?

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