Обновить

Комментарии 26

brain surgery for dummies

Дело привычки конечно, но код на rust читается так себе.

Смотря с чем сравнивать и какой код сравнивать. Шаблоны и прочее метапрограмирование нигде не читается хорошо. Линейный код в виде цепочек обычно чище, будь то Java или плюсы или как тут - в Rust.

НЛО прилетело и опубликовало эту надпись здесь

Метапрограммирование — ну, дженерики норм

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

Метапрограммирование на основе рефлексии в Haskell емнип можно сделать нормальным, но хаскелл среднестатистическому программисту в принципе читать сложнее. Даже условная Scala или Erlang в этом плане попроще будут. Но в среднем без предварительного переобучения в ФП языки довольно сложно, т.к. классические приёмы управления потоком программы растворяются в других концептах.

НЛО прилетело и опубликовало эту надпись здесь

Как раз минимальный синтаксис

когда xs в вашем patP что-то там do это ни разу не даёт пояснений о предметной области - это что-то про авторизацию, про обработку контейнеров или про рисование крестиков-ноликов на экране. Чем плохи одно-двубуквенные переменные кажется многие объясняли уже не единожды, чем плоха польская нотация - тоже. Но при этом это нормальная практика хаскеля.

В погоне за математической генерализацией, примеры бизнес логики растворяются в этих абстрактных байндингах типов. Например, без бОльшего ковыряния в документации сходу догадаться про назначение тех же 'NoSourceUnpackedness,'NoSourceStrictness,'DecidedLazy из доки по вашей ссылки на мой взгляд не представляется возможным. Зачем и почему у типа появились какие-то перегрузки операторов? Зачем вообще необходимо иметь примеры раскрытия типа в примерах, а не в тех разделе где-нибудь рядом с Generic Representation Type?

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

С чтением эрланга у меня мало опыта,

Ocaml, Lean 4? У последнего вроде тоже зав.типы есть, но код там всё же ближе к обычному и проще догадаться, что будет происходить в произвольно выбранной строчке.

НЛО прилетело и опубликовало эту надпись здесь

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

Template Haskell 

хаскельный аналог макросов. С рефлексией и работой на типах, я так понимаю.

 структуре из сумм, произведений и ещё пары мелочей

вот этот момент не очень ясен- суммы-произведения на типах же, правильно? Это типа как в расте если хочется безопасного мультитрединга, то нужно в ограничения делать наSend+Sync, то есть буквально конъюнкция типов для местного верификатора. А что из себя представляет произведение в таком случае? Автосгенерённые сочетания для все вариантов перестановок, для пущей коммутативности?

НЛО прилетело и опубликовало эту надпись здесь

То, что Rust делали С++ники, наложило неизгладимый отпечаток!

Там ещё и монады ненастоящие :D

Кстати, не нашёл ни одного полезного случая когда нужны завтипы. Ведь они могут что-то доказать только когда число (длина массива и т.п.) известна на стадии компиляции. А это прям редко, чаще это то что пришло снаружи.

Проверить в рантайме пришедшее снаружи и затем передать проверенное в код с завтипами?

да, но завтипы тогда избыточны
достаточно как в typescript refinement-типа (brand-типа) - тип с токеном, токен выдан рантайм проверкой 

type Aes256Key = Uint8Array & { __brand: "Aes256Key" };

declare function makeAesKey(bytes: Uint8Array): Aes256Key;

function encrypt(key: Aes256Key, data: string) {
  // Здесь НЕ надо проверять длину! 
  // Тип гарантирует: key.length === 32
}

// Использование:
const rawKey = getKeyFromNetwork(); // Uint8Array
if (rawKey.length !== 32) handleError();
encrypt(makeAesKey(rawKey), "secret"); // "Доказали" рантаймово

Но можно случайно потерять handleError() и вызвать makeAesKey(rawKey) с невалидными данными, наверное?

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

function double(n: number | null): number {
  if (n == null) {
    throw new Error('no null pls');
  }
  // Здесь typescript понимает, что уже доказано,
  // что n не может быть null
  return n * 2;
}

В этом примере не завтипы, но, надеюсь, суть моей мысли вы поняли

НЛО прилетело и опубликовало эту надпись здесь

Для человека, в целом знакомым с программированием но малознакомым конкретно с Rust - да.
Если же добавить в определение задачи условие о том, что человек должен быть знаком с технологий, код на которой пытается понять то сравнение получится сильно не в пользу того же C++. Особенно с хайповым в последние 10-15 лет template-only подходом и его наигрязнейшими хаками.

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

По мне, так очень хорошо Rust читается.

Главное, что сигнатуры функций не врут и ошибка входит в контракт (сигнатуру). Жаль, IO эффекты не проверяются компилятором на уровне сигнатур, но хорошим тоном весь IO делать асинхронным что видно в сигнатуре.

Мусорить в контрактах (лайфтаймы всякие) не надо без необходимости и они будут читаемы.

В сравнении с процедурным Си, или с тем же C# выглядит не очень, имхо.

Если писать на раст в процедурном стиле на раст то конечно.

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

+1 я бы на месте разработчиков Раста изменил немного синтаксис/стмволы заимствования, вместо &mut , использовать другой символ…

Конечно, не хочется обижать автора статьи, но первая её часть читается как «Вредные советы» Г. Остера. Когда осознаёшь, что автор всерьёз предлагает клонировать всё подряд, кроме пары базовых случаев, становится страшно.
Это делает Ваши программы на Rust не просто менее производительными, чем они могли быть. Это делает их значительно менее производительными, чем программы на языках со сборщиком мусора. Постоянные и бездумные копирования данных более, чем нивелируют тот бонус производительности, который даёт AOT-компиляция в машинный код. Играть в кошки-мышки с borrow checker'ом постоянно и ненужно: написать мало-мальски сложную программу на одних только заимствованиях едва ли получится, но есть ведь способы успокоить borrow checker, избежав копирования данных: всякие там RefCell и счётчики ссылок.

Аргумент про растущие тактовые частоты и дешёвую оперативную память – очень странный. Оптимизация до сих пор имеет место и до сих пор полезна и важна. Другой вопрос, который меня беспокоит: зачем вообще Вы пытаетесь использовать инструмент, которым не только не умеете эффективно пользоваться, но и отказываетесь учиться, опуская руки и прикрываясь за смирением с тем, что Вы посредственный программист? Раз уж Вы так хотите прибедняться и называете себя посредственностью, почему не возьмёте инструмент под стать – что-нибудь попроще, без borrow checker'а, без лайфтаймов, со сборщиком мусора?

Спасибо за развернутый комментарий! Обратите внимание на теги к статье.

Нет. Копировать структуры в раст легко и дешево. Внутри функции компилятор сам выведет без копирования. А параметры в функции лучше передавать по значению, как в Паскале. Потом разберётесь и будете оптимизировать.

Раст полезен не только производительностью. Он помогает доказывать утверждения (бизнес правила) в типах и корректность выражений используя pattern match и конечные автоматы.

Делал 3 пета в этом году. И каждый раз когда выкручиваешь на максимум одно из требований, то лучшим оказывается Раст

  • Высокая параллельность обработки и вообще high load

  • Критичность ошибок, необходимость более надёжных средств, чем просто тесты

  • Жёсткие сроки: на раст больше уйдёт на проектирование (прогнозируемое время), но доказательство корректности / отладка (самое непредсказуемое по времени) будет гораздо короче

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации