Pull to refresh
30
0
Станислав Ткач @DarkEld3r

Rust developer

Send message

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

Это главная причина, почему я не люблю раст - приходится думать не над задачей, а над тем, можно ли победить в данной ситуации borrow checker, и если можно, то как.

Ну а это скорее следствие относительной низкоуровневости языка. Если хочется максимально на предметной области сосредоточиться, то язык GC всегда будет лучше так как позволяет игнорировать разные "мелочи". Так-то в С(++) тоже приходится много в голове держать, просто компилятор не бьёт по рукам.

Может да, может нет, если дефолтные настройки удачнее выбраны.

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

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

Вижу здесь противоречие. Если мы хотим как можно сильнее ускорить написание первой версии, но брать библиотеки выгоднее. А уж потом если проект выстрелит и библиотека помрёт, то можно будет писать свой велосипед.

А в чём проблема использовать немного unsafe при необходимости? В реализации на С ведь будет то же самое только неявно.

Что есть в Go, чего нет в Rust? Могу предположить, что только концепция каналов.

В расте есть каналы.

Так ведь пункт 3 как раз про это?

Точно не окупилась? А на что тогда Colony Ship сделали?.. Да, разработчик говорит, что от продаж последней зависит их дальнейшая судьба и это может стать их последней игрой, но думал, что Age of Decadence продалась не так плохо. Конечно, по меркам такого инди проекта. Вообще читал множество интервью с Винсом и у меня сложилось впечатление, что он как раз не разработчик. Но могу и ошибаться: на их форум всего пару раз заглядывал и особо не вникал сколько у них человек сейчас и кто чем занимается.

Если что, Age of Decadence покупал до релиза, после - нескольким знакомым в подарок. И Colony Ship три раза купил. И даже Dungeon Rats куплена.

статическая типизация

Так это плюс, а не минус.

трейты для чужих структур реализовывать нельзя

Чужие трейты. И то если очень хочется, то через враппер можно. Да, неприятно и некрасиво, но можно.

Можно подсмотреть как это сделано, например, в мире C#.

Так в расте тоже пытаются. Скажем, дофига усилий ушло (и продолжает идти) на то чтобы асинхронный рантайм/экзекьютор мог быть внешним и подменяемым. Просто команда у языка не такая большая и ресурсы ограничены, заниматься всеми вопросами сразу никак не получится. Да, если завалить из деньгами, то станет лучше. И то с нюансами. Скажем, за С++ стоит много корпораций с деньгами, но (или скорее именно по этой причине) договориться им бывает непросто. Если же контроль над языком у какой-то одной корпорации, то совсем не факт, что это хорошо, особенно если рассматривать не сиюминутную пользу, а промежуток хотя бы в 5-10 лет.

Если что, у clap кроме дерайв-макросов есть и интерефейс через билдеры. То есть, макросами обмазываться не прям обязательно.

Да, скорее озадачивает отсутствие каких-то казалось бы базовых вещей в стандартной библиотеке.

Для языка "общего назначения" базовые вещи - это понятие очень растяжимое. С одной стороны, удобно когда не надо искать и выбирать зависимости. С другой - у джавы так в стандарной библиотеке появились AWT и Swing, которыми, насколько я знаю, не то чтобы сильно пользуются. Опять же, когда зависимость подключается в одну строчку, то не такая это и проблема.

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

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

Что стандартные библиотеки на go, что на питоне справлялись с этим отлично.

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

Может я не совсем понял суть претензии, но кажется, что она в большей степени заключается в том, что нужной реализации не нашлось в стандартной библиотеке. Да, есть такое - автор хоть и говорит, что стандартная библиотека огромна, но я бы сказал, что она наоборот минималистична и у этого есть свои преимущества. Скажем, я помню времена когда ещё не было серде и все пользовались другой библитекой (rust-serialize или что-то в таком духе). В общем, на серде перешли не зря и если бы изначальная сериализация была в std, то это было бы печально. И так со многими другими вещами: порой кажется, что это прям совершенно базовая штука, почему бы не предоставлять её из коробки, а потом придумывают что-то получше.

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

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

Автор пишет, что у них были "технические причины" выбрать раст. Очень может быть, что в их случае JS как раз не работал.

Да да очередная защита не понятно кого не понятно от чего

Eсли разрешить реализовать "чужие" трейты для "чужих" типов, то не ломающие (по semver) изменения очень даже смогут ломать компиляцию. Было бы совсем не весело получать сломанный билд при обновлении зависимостей, причём зависимости сами по себе ничего плохого как бы и не изменили.

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

use lib_a::SomeTrait for crate::MyType, lib_b::AnotherType;

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

я даже не могу из за этого организовать СВОИ типы по разным модулям потому

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

а их не для каждого типажа можно создать.

Всё-таки пример несколько синтетический. Ну и вот так вот можно:

trait TraitA {
    fn a() where Self: Sized;
}

trait TraitB: TraitA {
    fn b(&self);
}

struct A {}

impl TraitA for A {
    fn a() {}
}

impl TraitB for A {
    fn b(&self) {}
}

fn main() {
    let a: &dyn TraitA = &A {};
}

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

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

А понадобиться может если мы не хотим везде передавать целую структуру, если нужно модифицировать только отдельные поля:

let mut s = S { a: 1, b: 2 };
foo(&mut s.a, &mut s.b);
// foo(s.get_a(), s.get_b());

Да, пример максимально синтетический и мне проблема тоже кажется преувеличенной.

Симпатично, правда не уверен, что правильно понял вот этот пример:

class Foo {
  val a // Int автоматически инферрится из геттера 
    get() {
      return 2
    }
}

Тут будет сгенерирован сеттер, который будет устанавливать значение a, но прочитать значение будет нельзя так как всегда будет возвращаться 2?

Спасибо, я почему-то думал, что сгенерятся как раз getMyInt/setMyInt.

По большому счёту согласен, но в целом с "целенаправленным изменением апи" не всё так просто. Не зря есть штуки вроде cargo-semver-checks - порой случайно сломать публичное апи легче, чем кажется.

В D нечто подобное есть(@property), но более многословное. В С# немного "наоборот": там вызывать всё-таки get/set приходится, зато сахар для объявления, кажется, наиболее короткий.

Но, помимоо этого вы можете сделать:

И? Чем плоха возможность делать impl dyn Trait?

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

Можно эту разницу увидеть на примере?

Основное ограничение трейтов, которое приходит мне в голову: нельзя из dyn Child перейти к dyn Parent. Хотя может когда-то и сделают.

Information

Rating
Does not participate
Date of birth
Registered
Activity