LINUX.ORG.RU

into_rust() — скринкасты по Rust. Доступно видео с RustConf 2016.

 , rustconf, ,


7

5

into_rust() — это плод годовой работы Николаса Мацакиса, одного из основных членов команды разработчиков Rust, и представляет из себя хранилище обучающих скринкастов по данному языку программирования. Обучение строится вокруг принципа работы с памятью в Rust: владение и заимствование.

На сайте (на момент написания новости) уже представлены следующие скринкасты:

На будущее запланированы следующие темы:

  • Structs and enums;
  • Threads;
  • Traits;
  • Named lifetime parameters;
  • Aliasing and mutability.

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

Также стали доступны видеозаписи с прошедшей 10 сентября первой конференции по Rust — RustConf 2016.

Для просмотра доступны:

>>> Подробности

★★★★★

Проверено: Shaman007 ()
Последнее исправление: sudopacman (всего исправлений: 8)

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

Это еще зачем?

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

претензии к Rust-оманам

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

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

Разница между плюсовыми enum'ами и растовыми огромна.

Ну это вообще разные вещи. Очень странно, что Rust-овые enum-ы вы, во-первых, упоминаете в отрыве от pattern-matching-а, и, во-вторых, сравниваете с C++ными enum-ами, а не union-ами.

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

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

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

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

Я видел такие фичи лет 15 назад в документации к Lisp-подобному языку Curl. Хорошо работает на примерах к функциям из stdlib.

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

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

Но вот в примерах к прикладным библиотекам уже сложнее.

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

Плюс вопросы к деплойменту этого всего дела в Web-е

Не понял. При чём тут веб?

передачи документации заказчиками

А что там передавать? cargo doc генерирует статический сайт. Кликаем по index.html и готово.

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

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

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

Вот, блин, кусок из документации, которую пишу прямо сейчас:

so_5::launch( []( environment_t & env ) {...},
  []( environment_params_t & params ) {
    params.exception_reaction( shutdown_sobjectizer_on_exception );
    ...
  } );
Дабы преобразовать этот кусочек во что-то компилируемое, пришлось бы писать include, функцию main, заменять чем-то многоточия и т.д.

Не понял. При чём тут веб?

Документацию, случаются, публикуют в Web-е. И не всегда с возможностью запуска каких-то скриптов на стороне http-сервера.

cargo doc генерирует статический сайт.

Вот этот сайт архивируется и архив отсылается клиенту.

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

пришлось бы превращать пример в полноценную программу

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

пришлось бы писать include, функцию main

В плюсах - да. В Rust - нет. В доке не нужно писать main и прочее.

Документацию, случаются, публикуют в Web-е. И не всегда с возможностью запуска каких-то скриптов на стороне http-сервера.

У раста это из коробки. Для всех либ в репе есть автодокументация: https://docs.rs/

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

Если я правильно понимаю (лень мотать тред вверх), примеры использования могут использоваться как юнит тесты. Эти запускаемые примеры на каких исходных данных тестируются?

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

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

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

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

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

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

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

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

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

А давайте вместо вымышленных диалогов посмотрим на то, что было на самом деле:

И? Чем отличается от того, что я описал? У меня складывается впечатление, что вы вообще не паритесь о смысле написанного, вам важно хоть что-то ответить. Я вам уже раз 5 написал, чем именно обработка ошибок в расте лучше - вы это игнорируете и хотите что-то узнать непременно от меня и непременно про паники. И я не могу врубиться, что конкретно.

Это все, что вы соизволили сказать про особенности работы с паниками в Rust-е. Более плотно данную тему мне довелось пообсуждать с RazrFalcon и red75prim, а не с вами.

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

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

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

while(!tasks.empty())
{
    for(auto& task: tasks)
    {
        if (task->isComplete())
            continue;
        if (task->needSplitting())
            nextTasks.push_back(task->split());

        nextTasks.push_back(std::move(task));
    }
    tasks.clear();
    std::swap(tasks, nextTasks);
}
Это на моём уровне знания C++, возможно можно и получше через какой-нибудь copy_if. Ну и, опять же, напоминаю, что в реальном коде этот цикл будет работать не по таскам, а по неким данным, которые в этом же цикле и будут обрабатываться, так что в реальности код будет длинее.

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

На недостатки раста указали вполне аргументированно

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

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

Что не так с

Во-первых это будет очень неэффективно. Во-вторых RazrFalcon, если я правильно понял, считает итерирование с одновременным изменением чем-то плохим и потенциально опасным. Потому мне и интересно как он решает такие задачи.

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

Чем отличается от того, что я описал?

Отсутствием хоть какой-нибудь конкретики.

И я не могу врубиться, что конкретно.

Это очевидно. И очевидно почему.

Что в мысли «перенос из одного вектора в другой» непонятно?

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

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

Типа за последние 20 лет изменилось то, что память больше не ресурс?

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

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

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

Во-первых это будет очень неэффективно.

Почему?

И, насколько я понял, претензия формулировалась как «нет эффективного метода remove»?

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

Почему?

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

И, насколько я понял, претензия формулировалась как «нет эффективного метода remove»?

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

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

Знаете, мне уже просто интересно, дебилизм здешних защитников Rust-а уже достиг дна или он еще способен копать вглубь?

Выше RazrFalcon утверждал, что в примерах кода для Rust-а не нужно париться ни про include (т.е. use), ни про main, ни про что-нибудь еще. Смотрим в доку по частям Rust-овой stdlib:

use std::io::prelude::*;
use std::net::TcpStream;

{
    let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap();

    // ignore the Result
    let _ = stream.write(&[1]);
    let _ = stream.read(&mut [0; 128]); // ignore here too
} // the stream is closed here
Ба, что это? Неужели use?

Про то, какова цена этого «теста» можно и не спрашивать. Он ведь ничего хорошего не покажет, если на локалхосте никто не слушает на порте 34254.

Или вот еще прекрасное:

use std::net::{SocketAddrV4, TcpStream, UdpSocket, TcpListener, Ipv4Addr};

fn main() {
    let ip = Ipv4Addr::new(127, 0, 0, 1);
    let port = 12345;

    // The following lines are equivalent modulo possible "localhost" name
    // resolution differences
    let tcp_s = TcpStream::connect(SocketAddrV4::new(ip, port));
    let tcp_s = TcpStream::connect((ip, port));
    let tcp_s = TcpStream::connect(("127.0.0.1", port));
    let tcp_s = TcpStream::connect(("localhost", port));
    let tcp_s = TcpStream::connect("127.0.0.1:12345");
    let tcp_s = TcpStream::connect("localhost:12345");

    // TcpListener::bind(), UdpSocket::bind() and UdpSocket::send_to()
    // behave similarly
    let tcp_l = TcpListener::bind("localhost:12345");

    let mut udp_s = UdpSocket::bind(("127.0.0.1", port)).unwrap();
    udp_s.send_to(&[7], (ip, 23451)).unwrap();
}
Тут не только use, тут еще и main. Зачем же он здесь? Гуру RazrFalcon же сказал, что main не нужен!

И это, блин, еще общеупотребительный классы. Как быть с какими-нибудь более специфическими вещами? Например, с классами для работы с SQL-ными СУБД (формирование prepared statement, выполнение запроса, получение параметров результата запроса, извлечение результатов)? Или классов для работы с каким-нибудь внешним оборудованием?

Неужели в Rust-е это все волшебным образом решается без моков, обвязок, интеграционного тестирования и пр.вещей, до которых софтостроение дошло за 70 лет своего развития?

Остается еще раз повторить: с такими друзьями Rust-у и враги не нужны.

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

чтоб удалить по индексу - надо пробежаться от начала списка до нужной позиции

Я думаю, там просто помечается элемент вектора.

Если претензия имелась в виду от меня

Да.

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

Я думаю, там просто помечается элемент вектора.

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

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

Приведённые примеры - это именно примеры, там no_run стоит.

Настоящие тесты в документацию не включены:

    #[test]
    fn listen_localhost() {
        let socket_addr = next_test_ip4();
        let listener = t!(TcpListener::bind(&socket_addr));

        let _t = thread::spawn(move || {
            let mut stream = t!(TcpStream::connect(&("localhost",
                                                     socket_addr.port())));
            t!(stream.write(&[144]));
        });

        let mut stream = t!(listener.accept()).0;
        let mut buf = [0];
        t!(stream.read(&mut buf));
        assert!(buf[0] == 144);
    }

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

Но это не про Раст против С++, а про разные подходы к проектированию.

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

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

Да, да, да. Rust, он же не про это. В нем же нет интерфейсов, который получают мутабельные ссылки и возвращают мутабельные ссылки. И с инкапсуляцией, как в одной из тем с пеной у рта доказывали, в Rust-е все нормально.

Ну хватит уже стучать снизу. Мне аж жалко Rust становится. Заменой современного C++ он не станет. Но как замена plan old C очень хорош. Зачем же вы его так дискредитируете?

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

Чем отличается от того, что я описал?

Отсутствием хоть какой-нибудь конкретики.

И я не могу врубиться, что конкретно.

Это очевидно. И очевидно почему.

Чотаржу. Это надо постараться, пожаловаться на отсутствие конкретики и отказаться конкретизировать.

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

facepalm. Потребление памяти - это просто смешно. Сколько у вас тасков будет? Миллион? Ну ок, на 4-8 мегабайта больше. Только надо помнить, что дек при каждом удалении из произвольного места сдвигает в среднем 1/4 дека. Какова вероятность, что среди миллиона тасков окажется, ну например, 16 завершённых? Нагрузка на память в 4 раза выше на каждую итерацию, получается.

Поведение при выбрасывании эксепшена такое же как у вас: при выходе за пределы скоупа контейнер грохнется вместе со всеми тасками. Этот вариант неприемлем? Тогда давайте сравнивать возможность восстановления. Вот поймали вы эксепшен снаружи цикла и хотите попытаться снова. Что у вас? дек, про который известно, что где-то внутри находится таск в некорректном состоянии, который при следующем вызове точно так же скорее всего кинет исключение. Что есть у меня? 2 вектора, в одном из них первый ненулевой элемент является проблемным. Я бы сказал, возможность восстановления эквивалентна.

В чем современность-то? В расходе дополнительной памяти?

Про память ответил выше, причём могли бы сами догадаться, если уж такой знаток дека. А про то, что не так с вашим вариантом ответил тут. Скажите, вы так и дальше будете маятником, сначала требовать вместо объяснения код, а потом требовать вместо кода объяснение?

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

Что-то вы слишком разошлись. Посчитайте до 10, выпейте воды. Это всего-то два разных языка. Как-то не очень хорошо выглядит, когда вы мой единственный пост с примером кода называете «доказывал с пеной у рта».

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

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

Как бы оба правы, о чем спор? Или я уже потерял суть?

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

Это надо постараться

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

Ну ок, на 4-8 мегабайта больше.

Ну память же не ресурс, конечно же.

Только надо помнить, что дек при каждом удалении из произвольного места сдвигает в среднем 1/4 дека.

Это вы сейчас про конкретную реализацию deque говорите?

Но даже если и так, то deque легко меняется на list. Тут ведь не это главное, а то, что кто-то обосрался на счет итераций, в которых нельзя менять контейнер.

Тогда давайте сравнивать возможность восстановления.

Давайте. В моем варианте контейнер с тасками вообще не нужно восстанавливать. Про геморр с вашим вариантом можно вообще не упоминать.

Я бы сказал, возможность восстановления эквивалентна.

Да вы тут уже много чего фееричного наговорили. От вас не убудет.

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

Или я уже потерял суть?

Суть именно в этом. Проблема в том, что про надобность писать exception-safe код Rust-оманы почему-то не понимают.

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

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

Было бы очень неплохо, если бы собеседники здесь читали, что им пишут оппоненты. А именно:

И с инкапсуляцией, как в одной из тем с пеной у рта доказывали, в Rust-е все нормально.

Речь не про ваш единственный пост с примером кода. А про недавнюю тему, в которой был ожесточенный спор на счет инкапсуляции в Rust-е. Где с пеной у рта кричали обе стороны.

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

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

То есть eao197 не указывал? Или что ты этим своим выпадом в мой адрес хотел сказать?

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

Было бы очень неплохо, если бы собеседники здесь читали, что им пишут оппоненты

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

Проблема в том, что про надобность писать exception-safe код Rust-оманы почему-то не понимают.

Ладно. Давайте на пальцах, вот код: https://play.rust-lang.org/?gist=eecdd3dab36cdcbc5091fad126aa5dd8&version...

Вставьте куда-нибудь panic!() (кроме drop), чтобы программа вывела неверный результат обработки, или внешний ресурс не закрылся.

Про откат транзакций пока не говорим.

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

Про откат транзакций пока не говорим.

Так ведь речь именно что про откат транзакций.

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

Это типичная ошибка, которая проявляется как при использовании исключений, так и при использовании кодов возврата. Только почему-то акцент делают на «неявности» исключений.

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

Иначе нарушаются инварианты для разделяемых данных.

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

Впрочем, с подходом immutabity by default откат транзакции можно свести к такому:

#[derive(Debug, Clone)]
struct Clonable {}

fn process(v: &Clonable) -> Result<Clonable, ()> {
    Ok(v.clone())
}

fn update(v: &mut Clonable) -> Result<(), ()> {
    *v = try!(process(v));
    Ok(())
}

ценой копирования и повышения расхода памяти, конечно.

Только почему-то акцент делают на «неявности» исключений.

Так у вас целый фреймворк, для обеспечения корректного отлова и обработки исключений, где явно нужно указывать, что с исключениями делать. Можно сказать - цена для за «неявность» исключений. Я не говорю, что это плохо. В конце-концов, заставить проверять возвращаемые значения в С++ в отличии от Раста нельзя.

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

В конце-концов, заставить проверять возвращаемые значения в С++ в отличии от Раста нельзя.

let str_types = msg.get("messageTypes").unwrap().as_array().unwrap().into_iter().map(|json_type| {
	                    json_type.as_str().unwrap()

В данном случае автора заставили проверить значения или нет?

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

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

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

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

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

У меня нет такого фреймворка.

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

unwrap() это тоже проверка возвращаемого значения. Да и grep unwrap просмотреть легче, чем рассматривать все результаты в grep function_name1, grep function_name2, ...

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

Ну тогда и в С++ можно завернуть результат в экзмепляр класса с методами unwrap и unwrap_or и кидать исключение, если что.

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

то оказывается, что в Rust-е те же самые грабли, что и в C++.

https://habrahabr.ru/post/312128/

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

Не вы случайно писали? Так что граблей в Расте поменьше.

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

Не вы случайно писали?

Я.

Так что граблей в Расте поменьше.

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

Точно так же, если вы не откатываете в Rust-е транзакционные операции по модификации разделяемых данных (как можно увидеть вот здесь), то вы все равно получаете проблемы.

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

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

Ага. И стандартную библиотеку переписать. Дерзайте.

Зачем? Они минимальная и все что надо можно сделать поверх, скрыв детали реализации. Это у вас, если надо удалить элемент из LinkedList, предлагают искать на помойке альтернативу.

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

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

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

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

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

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

unwrap() это тоже проверка возвращаемого значения.

А чем такая «проверка» отличается от непойманного исключения?

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

На современных процессорах с их многоуровневыми кэшами, место у LinkedList и так рядом с помойкой

Ясно.

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

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

Оба принципа ущербные. Для ниш, в которых толкаются локтями C, C++ и Rust более актуален вопрос «Насколько просто сделать что-то нетривиальное и насколько сложно при этом отстрелить себе ногу?»

Современный C++ позволяет делать нетривиальные вещи, при этом есть возможность обезопастить себя от отстрела ног. Но только за счет дисциплины и тщательно подобранных библиотек и практик кодирования.

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

Проблема с обсуждением достоинств Rust-а состоит в том, что ваша сторона, зачастую, настаивает только на том, что «C++ старое говно, поэтому все новое нужно писать на Rust, поскольку он лучше по определению». Но как только речь заходит о действительно важных и сложных вещах, вместо выслушивания противоположной стороны вы (может не вы лично, а Rust-оманы вообще) просто повторяете «С++ старое говно...» снова и снова.

eao197 ★★★★★
()
Последнее исправление: eao197 (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.