Как стать автором
Обновить
55
0
Константин @kstep

Инженер-программист

Отправить сообщение
Формально это не исключения, а просто дополнительный сахар для паттерн матчинга на Result с ранним возвратом. Дальнейшее развитие макроса try! по сути. Хотя лучше бы они, ИМХО, работали над HKT и монадическими комбинаторами.
Ну ломает она очень небольшое количество пакетов, в 99% случаев никто это не почувствует.
Да и изменения там в принципе только исправляют некорректное поведение языка: раст позволял делать вещи, которые не должен был позволять делать в принципе.
Особенно радует поддержка кастомных билд скриптов на расте, что позволяет делать такие вещи, как при сборке lua53 (скачивание исходников языка в сборке проекта) или моего systemd-cron-next (генерация systemd юнитов из handlebars-шаблонов).

Понятно, что для скриптовых языков это всё не новость (pip, npm, rake...), но от компилируемого языка такой прелести лично я джва года давно ждал.
SDL bindings, по отзывам, одни из самых лучших.
Для меня это больше хобби, в основном мои проекты выросли из необходимости что-то с чем-то синтегрировать и автоматизировать для себя, поэтому в основном это обёртки вокруг разных API: mpd, pocket, vkrs,…
Из чуть более известного — systemd-crontab-generator, a.k.a. systemd-cron-next.
В C++ сложности точно такие же, только неявные. Здесь тебе компилятор говорит, что ты не прав, в подобном случае С++ промолчит и даст выстрелить в ногу. Опять же, если всё делать правильно, то в C/C++ ты передашь вместо среза пару указателей или итераторов, либо указатель и длину строки. Здесь всегда одна сущность — срез. ИМХО, в расте как раз проще.
Перемещение при передаче значения в другую функцию, это побайтное копирование структуры в стек (что может быть выоптимизированно llvm, но не самим растом). Понятно, однако, что в случае String будут копированы только указатели всякие и служебная инфа, данные на куче останутся на месте.

Но тут речь не про это. Если вы читали внимательно, в статье говорится про строки, и для того, чтобы передать строковый литерал в функцию, которая принимает String, его нужно разместить в куче преобразовав в String (to_string(), to_owned(), into() — что больше нравится), а это копирование данных. Про это речь.
Всё так, но не так.

1) Метод Into::into принимает self по значению, это верно. По значению можно передавать только Sized типы, потому что для передачи по значению размер типа должен быть известен при компиляции. Так что stepik777 тут не прав, это не искусственное ограничение, для него есть объективная причина.
2) Googolplex не совсем прав по поводу того, что типажи, у которых есть методы, принимающие self по значению — не object-safe. Если на сам типаж нет ограничения `trait TraitName: Sized`, то он может оказаться object-safe даже с методами, которые принимают self по значению, просто компилятор потребует, чтобы такие методы содержали в сигнатуре ограничение where Self: Sized. См. например типаж Iterator, который object-safe, но у него есть методы, принимающие self по значению doc.rust-lang.org/src/core/iter.rs.html#376.
3) Я сам ошибся, когда говорил, что генерик параметр в трейте Into мешает ему быть object-safe, не мешает. Просто компилятор попросит конкретизировать тип при приведении к трейт-объекту, чтобы T в Into был конкретным типом. То есть нету типаж-объекта &Into<T> где T какой-то параметр, но может быть типаж-объект &Into<u32>.

По итогу stepik777 по большому счёту прав, что Into<T> не может быть типаж-объектом только из-за ограничения на Sized для всего типажа, если бы только ограничения на весь типаж не было, а только метод into имел сигнатуру fn into(self) -> T where Self: Sized, то сделать такой типаж-объект, конкретизировав параметр T, было бы можно. НО это не имело бы никакого смысла, так как вызвать на таком типаж-объекте единственный метод into было бы невозможно в принципе, так как он принимает self по значению, так что использование такого типаж-объекта было бы абсолютно бессмысленно.
Вот пользовательский тип может быть unsized только если unsized-поле единственное unsized поле и последнее в списке полей. Но только к трейту Deref и deref coercion это не имеет никакого отношения.
Здесь это не важно абсолютно, Deref<Target=T> преобразует заданный объект в &T, его метод `deref(&self) -> &Self::Target` принимает self по ссылке, поэтому unsized или sized тут Self и Self::Target не играет никакой роли.
Хм, возможно. Просто я как-то привык к определённому значению слова «наследование» в ООП, а тут оно имеет несколько иное значение, поэтому пришлось мысленно выбирать другой термин для более точного понимания, так что я сам привык думать про эту концепцию в расте как о «требовании» или «ограничениях на тип», чтобы не путать с наследованием как его понимают в классическом ООП.
А так же Arc<TraitName>, и вообще любой тип, реализующий Deref<Target=TraitName>.
Да, конечно. Но тут не хотелось бы заострять внимание на deref coercion, так как речь не про неё, а про повторяющиеся преобразования.
Тут специально делается акцент на происходящих переходах значение-ссылка-значение, поэтому выбран самый явный метод.
Аналогично, тоже их очень жду. Пока просто обхожусь тем, что есть (ассоциированные типы).
Для полноты картины, некоторые типажи можно использовать в качестве типов (так называемые «типажи-объекты», а типажи, которые можно использовать как объекты называются «объектно безопасными» (object safe)), но только по указателям (вроде &Display), т.к. их размер не известен во время компиляции. Но типаж Into<T> к таким не относится, т.к. принимает тип-параметр.
Возможно, когда-нибудь. Но пока так.
Copy наследует Clone

Скорее не «наследует», а «требует», потому что это типаж, а не класс, а типажи не наследуют, а накладывают ограничения по типы, для которых их реализуют. И если бы Copy наследовал Clone, то выходило бы, что явно говорить, что надо реализовать Clone, было бы не нужно (ведь его функционал уже включён в Copy), а он именно требует, поэтому для каждой реализации Copy надо явно реализовать Clone.
Ну не совсем, как я понял. Здесь всё же решена более простая задача: фактически сравнение кусочков изображений с одним эталонным изображением, без разбора на конкретные символы и их распознавания.
Заметьте, против самого питона ничего не имею, сам долго на нём писал, и язык во многом замечательный. Но ФП в нём очень тяжеловесно именно из-за устройства лямбд (длинное ключевое слово, ограничение на только одно выражение в лямбде).
И был бы это вариант питона. И пришлось бы для использования лямбд писать длинющее ключевое слово, так что ФП превратилось бы в боль, а потом его постоянно везде читать. И стал бы lambda выглядеть lamba код на расте lambda примерно вот так lambda lambda lambda. И плакали ли бы мы кровавыми слезами каждый раз при чтении функциональных конвейеров из map/filter/and_then.

Нет, спасибо. ИМХО именно наличие этого ключевого слова в питоне тормозит развитие ФП в нём. Лямбда — легковесная структура, предназначенная для частого использования, и должна выглядеть и читаться легковесно.

Информация

В рейтинге
Не участвует
Дата рождения
Зарегистрирован
Активность