Как стать автором
Обновить
0
0
Иван Удовин @wilcot

Пользователь

Отправить сообщение

Пост об утилите на 10 простых строчек, да и еще с ошибками в одном предложении ("простую версия"). Зачем, для кого, почему...

Нужно считать по байтам:
2(порт источника)+2(порт назначения)+4(номер последовательности)+4(номер подтверждения)+1(длина заголовка и часть резерва).

На расте невыразимо

Верно. Хотя можно сделать что-то альтернативное, но это все же не то, что вам надо:

trait Foo {
    fn foo(&self);
}

fn do_smth(v: impl Foo) {
    v.foo();
}

Для enum конечно еще придется попотеть, чтобы интерфейс Foo руками реализовывать не пришлось:

// А еще надо реализовать сам derive(Foo).
#[derive(Foo)]
enum MyEnum {
    A(TypeA), // TypeA реализует Foo
    B(TypeB), // TypeB реализует Foo
}

В любом случае, да, в Rust подобное невыразимо. Плохо ли это? Лично мне такая возможность в C++ и не нравится, так как за нее нужно платить. Например, чтением сотен строк непонятных ошибок, с чем я периодически сталкиваюсь и могу застрять на часок другой.

Вообще, на тему достоинств и недостатков различных моделей дженериков (а у Rust и C++ они различаются) есть хорошая статья.

Это уже какой-то антипаттерн.

Возможно, хотя встречается и не сказать что редко.

я уж промолчу что вы свой Option на расте написать не сможете

Точно не смогу? Вроде смог:

enum MyOption<T> {
    Some(T),
    None,
}

enum MyEnum {
    Int(i64),
    NullInt(MyOption<i64>),
}

fn do_smth(v: MyEnum) {
    match v {
        MyEnum::Int(v) => {}
        MyEnum::NullInt(MyOption::Some(v)) => {}
        MyEnum::NullInt(MyOption::None) => {}
    }
}

Вообще, то что вы привели это хардкоженные в компилятор вещи,

Хорошо, удаляем MyEnum::NullInt(OptionI64::None) :

error[E0004]: non-exhaustive patterns: `MyEnum::NullInt(MyOption::None)` not covered
  --> src/main.rs:73:11
   |
73 |     match v {
   |           ^ pattern `MyEnum::NullInt(MyOption::None)` not covered
   |
note: `MyEnum` defined here
  --> src/main.rs:67:6
   |
67 | enum MyEnum {
   |      ^^^^^^
68 |     Int(i64),
69 |     NullInt(MyOption<i64>),
   |     ------- not covered
   = note: the matched value is of type `MyEnum`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
   |
75 ~         MyEnum::NullInt(MyOption::Some(v)) => {},
76 +         MyEnum::NullInt(MyOption::None) => todo!()
   |

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

и тут даже не нужен визит,

Да, в этом примере может и не нужен, но это уже из-за того что пример построен на стандартных enum-ах.

в visit компилятор заставит обработать все случаи

Интересно увидеть, как будет выглядеть ошибка. Сколько сотен строк с объяснениями как компилятор пытался подставить типы в шаблоны, да ничего не вышло. Вполне возможно что в современном C++20 это выглядит читаемо, поэтому интересно увидеть какой-нибудь такой пример.

Мне интересно, как будет выглядеть на variant+visit такой простой пример:

fn do_smth(v: Result<Option<i64>, String>) {
    match v {
        Ok(Some(v)) => {}
        Ok(None) => {}
        Err(v) => {}
    }
}

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

Например как будет выглядеть ошибка, если я удалю ветку с Err(v) => {}:

error[E0004]: non-exhaustive patterns: `Err(_)` not covered
   --> main.rs:12:11
    |
12  |     match v {
    |           ^ pattern `Err(_)` not covered
    |
note: `Result<Option<i64>, std::string::String>` defined here
   --> /home/user/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/result.rs:502:1
    |
502 | pub enum Result<T, E> {
    | ^^^^^^^^^^^^^^^^^^^^^
...
511 |     Err(#[stable(feature = "rust1", since = "1.0.0")] E),
    |     --- not covered
    = note: the matched value is of type `Result<Option<i64>, std::string::String>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
14  ~         Ok(None) => {},
15  ~         Err(_) => todo!()
    |

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

Может не надо так? Выглядит как:

unsafe {
    // Пишем очередную новость про то, как очередной
    // студент написал очередной курсач.
}

Сразу видно, где происходит отстрел конечности.

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

Насчет второго примера не понимаю, в чем претензия? В том, что круглые скобки не используются? Мне так наоборот, бывает непривычно уже эти круглые скобки писать :) На том же C++ такой же цикл пишется так:

for (int i = 1; i < 10; i++) {
    // ...
}

А некоторые любят ++i писать, даже споры из-за этого бывают, что быстрее. Аналогично "if expr {}" как-то уже приятнее выглядит чем "if (expr) {}". Кажется дело привычки.

Насчёт 3 примера тоже не понятно. Вроде стандартный синтаксис (например, в том же python вполне нормально написать a, _ = f1(42)), чтобы развернуть tuple.

Может вам не нравится, что вместо конструкции var a = b; пишется просто a := b? Интересно узнать, чем же привычный для других языков синтаксис тут внезапно стал жутким.

Применение bogosort здесь не очень удачное, так как в случае параллельного выполнения результат получается случайным по отношению к количеству операций. Раз так «быстро» предлагается сортировать, то лучше что-ли через next_permutation делать, сложность получится та же, O(n!) для n различных значений, но результат уже будет более предсказуемым .

Писатель канала все ещё (1.20) не способен узнать о закрытии канала.. Даже специально добавлено в документацию. В итого, лепим дополнительные каналы, иные методы взаимодействия, обрамляем всё это мьютексами.. Доколе? :)

Зачем писателю канала нужно знать о закрытии канала, если именно писатель должен его закрывать?

Читаем:

Note: Only the sender should close a channel, never the receiver. Sending on a closed channel will cause a panic.

Для этого не нужна какая-то специальная библиотека, в большинстве библиотек для роутинга есть мидлваре, которое перехватывает панику, логирует ее и возвращает 500-ку

Если в обработчике хоть где-то используется оператор go, то middleware вас не спасет.

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

В идеальном мире так и работает. Но речь идет про реальный мир, где люди могут совершать ошибки (и да, когда они выявляются их стараются исправить). Еще бывают баги в хардваре, или совершенно случайно флипнется бит. Да и покрыть тестами программу - дело не простое. К примеру, вы можете прочитать как достигали 100% покрытия бранчей в библиотеке sqlite: https://www.sqlite.org/testing.html

Если вам не хочется читать много текста, то вот этого будет достаточно для понимания:

As of version 3.39.0 (2022-06-25), the SQLite library consists of approximately 151.3 KSLOC of C code. (KSLOC means thousands of "Source Lines Of Code" or, in other words, lines of code excluding blank lines and comments.) By comparison, the project has 608 times as much test code and test scripts - 92038.3 KSLOC.

Если у вас произошла паника в горутине (не в основной), то отсутствие recover приведет к падению всего приложения. Это не всегда хорошо. К примеру, у вас бекенд с несколькими маршрутами в API (/users/, /posts/ и т.д.), и так вышло, что в каком-то из обработчиков маршрутов (возможно в том, который используется крайне редко) разработчик допустил ошибку и произошел выход за пределы массива/слайса (обратите внимание, что в таком случае приложение скорее всего сможет продолжить работу). В результате, если полениться и не обработать такую панику, то пострадает вся функциональность. Если клиенсткое приложение в случае ошибки будет повторять запрос, то бекенд будет лежать и не подниматься. А еще ситуацию может усугубить например то, что бекенд будет подниматься не моментально, так как, к примеру, ему понадобится инициализировать кеши или еще что-то. В итоге из-за такого бага вы получите большой Downtime, который можно было бы избежать. Я ни в коем случае не выступаю за необходимость использования подобных библиотек (так как это очень тонкая обертка над стандартной библиотекой), но ни в коем случае не стал бы называть это антипаттерном. Особенно вариант обработки паники, с дальнейшим пробрасыванием ее в ожидающую горутину в качестве ошибки (см. WaitAndRecover).

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

  1. Самостоятельно делать обработку паник в горутинах.

  2. Использовать стороннюю библиотеку.

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

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

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

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

Оставляйте, пожалуйста, ссылки на источники. Как указал X, согласно Y и т.д.

Да, спасибо. Картинка меняет ситуацию

Статья оставила двоякое впечатление. С одной стороны в ней приведена логика работы с абитуриентами, перечни запросов и даже произведён расчёт стоимости содержания такой системы. С другой стороны она совершенно оторвана от реальности. И это становится понятно, когда читаешь заголовок (а дальше в этом убеждаешься). Я пока не смог представить ситуацию, где может взяться миллиард абитуриентов. Ладно там миллион, максимум 10 миллионов. Хотелось бы понять, чем мотивирована такая постановка задачи. Если это как теоретическая задача по архитектуре, то к чему расчеты потребляемого железа и стоимости? Это надо делать, хотя бы оценив реальную производительность каждого компонента по отдельности (даже оценки той же PostgreSQL нет).

Каждый раз при вызове функции вычисления синуса перебирать все файлы и отправлять?

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

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

Если приложение смогло взять значения секретов, то почему вредоносный код в том же приложении не сможет? Да, некоторые файлы не удастся прочитать, но нужные наверняка будут прочитаны с успехом. А логи врядли помогут, так как скорее всего приложение не будет логгировать попытку прочитать какой-то файл. Теоретически так можно защитится, но давайте посмотрим с практической стороны.

Однако, если вы запущены в serverless-окружении - то ничего вы и не получите ни из каких файлов.

А откуда по вашему приложение возьмет секреты (env переменные, файлы, аргументы запуска)? Ну да ладно, допустим ни один из этих вариантов не подошел. Но вот вариант с отправкой того де coredump вполне может оказаться рабочим. Не знаю, почему вы его проигнорировали.

Например:

  1. Отправить содержимое файлов в популярных каталогах: /etc, /var…

  2. Сделать core dump и отослать его.

1

Информация

В рейтинге
Не участвует
Откуда
Могилев, Могилевская обл., Беларусь
Дата рождения
Зарегистрирован
Активность

Специализация

Backend Developer