TGViewer
Channel Public Channel
Random Rust Dev

Random Rust Dev

@random_rust_dev

Разработка на языке Rust.
Пишу простыни со своими мыслями о Rust и проектах на нем.
Subscribers
472
Photos
188
Videos
59
Links
44

Showing posts older than #237 · Back to latest

Older Posts 20 shown
Post #236 881
  • 😐 4
  • 😁 2
Post #235 752
Как объяснить картинкогенератору, что во время прямого удара ногой в живот подошву не видно?

Я сколько не уговаривал, все равно разворачивает ногу подошвой к зрителю.
  • 😁 8
Post #234 852
Post #233 764
#НеRust
  • ❤ 3
  • 😁 2
  • 💯 1
Post #232 713
Занимался сегодня рефакторингом небольшого крейта gametime.
Сделал чистку всех предупреждений с clippy::pedantic и задокументировал всё, хоть и минимально.

В крейте функционал для работы со временем в играх.
И минимум сложностей.

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

TimeSpan - промежуток между меньшим и большим TimeStampами. Почти как Duration, но лишь u64 наносекунд.

Clock - часы. Связывают монотонный таймер core::time::Instant и TimeStampы. Генерирует ClockStep, на каждый вызов Clock::step, где есть текущий TimeStamp и TimeSpan между текущим и предыдущим.
Предполагается использовать Clock в главном цикле, делать Clock::step в начале каждой итерации и раздавать ClockStep везде, где нужно знать время.

GlobalClock - как Clock, но используют единую для процесса точку отсчета. Требуется std и global_reference фича

ClockRate - часы со скоростью. Использует внешний источник TimeSpan, генерирует ClockStep с указанной относительной скоростью. Без накапливаемой потери точности.
Удобно для контроля времени в симуляции. Паузы, буллет таймы, перемотки. Просто вся симуляция должна использовать ClockStep из ClockRate, а не общего Clock.

FrequencyTicker - генератор тиков с заданной частотой. Использует внешний TimeSpan и возвращает итератор по ClockStep тиков, произошедших в течение этого времени. Без накапливаемой потери точности.

Ознакомиться с кодом можно здесь.
https://github.com/zakarumych/gametime
GitHub GitHub - zakarumych/gametime: Time calculations oriented for games Time calculations oriented for games. Contribute to zakarumych/gametime development by creating an account on GitHub.
  • 🔥 9
Post #230 800
Rust Tip по оптимизации дебажного билда.

В Cargo.toml можно указать, что в dev профиле нужно оптимизировать определенные зависимости.

Такая запись заставит сборщик оптимизировать зависимость foo.

[profile.dev.package.foo]
opt-level = 3


А вот так можно оптимизировать все зависимости разом.

[profile.dev.package."*"]
opt-level = 2


А так будут оптимизировать билдскрипты и процедурные макросы.

[profile.dev.build-override]
opt-level = 3


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

Приятного вам дебага.
  • ❤ 7
  • 👍 2
  • 💯 2
Post #227 691
Пятнично.
Я заметил, что у меня есть почти все ачивки в ER.
И не хватало только пары легендарок и 2х концовок.
И у меня был перс, прошедший базу в Jorney 2, кроме ластов.

Что, ж. Собрал леги (пришлось пройти весь квест Ранни, но на это ушел всего час), завалил ластов.
Бегом в Jorney 3. Взял 2 великие руны (Годрик и Райкард), проскочил Линдел, Напрямик к Огненному Гиганту, заваливая только боссов, что встречались по дороге.
Фарум Азула как нож сквозь масло (Jorney 3 кажется проще чем Jorney 2).
Маликет взят с первого пула, несмотря на небольшой факап с бафанием.
На Всезнайке попотел.
Годфри дал жару еще хлеще, оставил его на утро. Утром с первого пула.
Радагон и Зверь с нескольких пулов.

Я точно мучался на Jorney 2 намного больше.
А ведь за весь Jorney 3 я вкачал че-то типа 240-245. Потому что руны с нескольких боссов профукал на вайпах на следующих.

В целом что хочу сказать.
Elden Ring это одна из лучших игр, в какие я играл. Максимально советую всем любителям помахать мечем.
И не бойтесь сложности, она проще чем Dark Souls.
  • 👍 5
  • 👎 4
  • 🤷‍♂ 2
Post #226 596
Вот еще один Rust Tip

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

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

Не забудьте при генерации Rust кода устанавливать корректные Span-ы. Это поможет пользователю макроса найти причину ошибки.

Так же существует множество надстроек, что делают процедурные макросы вовсе тривиальными. Хотя каждая обладает своими ограничениями.
  • ❤ 10
  • 👍 6
Post #225 556
Запоздалый Rust Tip.

Используйте impl AsRef<T>, impl AsMut<T> и impl Into<T> в аргументах, когда ожидается, что вызываться функция будет удобнее с автоматической конверсией без потери выразительности API.

Но только если T это не дженерик. Иначе придется его явно указывать.

Классический пример это AsRef<Path> аргументы в std всюду, где нужен &Path, потому что удобно вызывать со строковым литералом. При этом на вызывающей стороны не возникает вопросов, куда там оно сконвертируется.

Еще хороший пример - impl Into<EnumType>, где для вариантов есть отдельный тип, который конвертируется в этот вариант. Концептуально они должны быть одним и тем же.

Использовать ли impl Trait или объявить generic, дело вкуса по большей части. Единственная разница в невозможности явно указать тип. Если вы ожидаете, что пользователю функции когда-то понадобится явно указать тип - объявляйте, иначе можно и с анонимным.
  • 👍 6
  • 👏 1
  • 💯 1
Post #224 595
Понедельничный Rust Tip.

Простой совет для невыспавшихся за выходные.

Старайтесь не добавлять трейт баунды в объявление типа.
Любой T: Trait потребуют добавить этот баунд во все имплы и функции, кроме случаев, где вместо T будет конкретный тип.

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

Конечно иногда придется. Например если вы используете ассоциированный тип в объявлении полей.
  • 👍 6
Post #223 621
Rust Tip для тех, кто кодит ночью (или прочитает утром)

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

Семейство Fn использует специальный синтаксический сахар, и мы обязаны писать так:
Fn(A, B, C) -> R, аналогично синтаксису функций, только без имен аргументов.
Вместо Fn<Args, Output=R>, где Args - тьюпл с типами аргументов, так как эта форма нестабильна.

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

Итак по порядку. 🧵
  • 👍 10
  • 🤝 1
Post #222 546
Сорвалась сессия в ДнД.
Второй раз подряд.
Вывод: нельзя лить в прод в пятницу. Инциденты на работе мешают спасать мир.
  • 😁 10
  • 💯 4
Post #221 587
Любой ieee754 формат с плавающей точкой содержит:
0% натуральных чисел.
Столько же отрицательных целых.
200% нулей.
И 0% остальных рациональных чисел.
  • 😁 14
  • 👍 2
Post #220 564
Шутки, которые нельзя перевести лучше не переводить.

- this^2 = -1. Is this real?

- Assuming multiplications in t*h*i*s are commutative, than it's equivalent is shit, and shit is getting real!
  • 👍 14
  • 🔥 1
Post #219 563
  • ❤ 10
  • 🥰 7
  • 🔥 4
  • 😁 1
Post #218 665
Известно, что файлы - самураи. Потому что у файла нет цели, только путь.
  • 😁 17
  • 🤯 9
  • 🔥 3
  • ⚡ 1
Post #217 597
Rust Tip выходного дня.

Rust это крутой язык, но отдыхать очень важно.
Лучше не тратить на петы все выходные.
Постарайтесь выйти на прогулку.
После выгорания программировать на Rust становится сложнее.
  • 🤝 20
  • 🔥 6
  • ❤ 3
  • 👎 3
  • 👍 2
  • 💯 2
Post #216 695
Rust Tip для начинающих

Реализуя Iterator, снабдите его кастомной реализацией size_hint, nth, count, last и fold, если они могут быть лучше чем реализованный в трейте.

size_hint по-умолчанию возвращает (0, None), что значит от нуля до бесконечности. Его можно перегрузить почти всегда.

nth по-умолчанию просто вызывает next n+1 раз. Если итератор может прыгнуть - кастомная реализация будет кстати.

count по-умолчанию итерируется до конца и подсчитывает. Если размер известен заранее, то стоит перегрузить count. А еще реализовать ExactSizedIterator

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

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

К сожалению трейты из метода try_fold еще недоступны на stable, так что его перегрузить не получится.

Но можно еще посмотреть на то что бы перегрузить all и any.

Удачного вам итерирования!
  • 👍 25
Post #215 494
  • 👍 8
  • 😁 7
  • ❤ 3
  • 👎 1
  • 🤝 1
Older posts →
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →