LINUX.ORG.RU

Зачем в rust нужно keyword «impl» в параметрах и в возвращаемом значении функций?

 ,


0

7

Ау, растаманы! Почему нельзя вместо

fn f(x: &impl Trait1) -> impl Trait2 

писать

fn f(x: &Trait1) -> Trait2 

? Trait – не first class тип? Это бред, но даже если так: и что? Или может возможен конфликт одинаковых имён структуры и trait? Короче, смахивает на синтаксический оверхед.

UPD. Ну и вдогонку, чтобы дважды не вставать: «we can’t implement external traits on external types» – это не просто дичь, а просто дичь. Ну и аргументация трындец: «Without the rule, two crates could implement the same trait for the same type, and Rust wouldn’t know which implementation to use.». Вот когда конфликт возникнет, тогда и ругались бы на него.

UPD2. fn vs fun – зачем отдельный keyword для лямбд?

★★★★★

Последнее исправление: dimgel (всего исправлений: 3)
Ответ на: комментарий от dimgel

Или ты не растаман, и просто так ответил?

Это клоун, который вообще ни в чём не «ман». Он тут на ЛОРе учится «биты гасить», но зачем-то лезет в каждый тред по программированию хамить и ядом плеваться.

anonymous
()
Ответ на: комментарий от fernandos

Придётся пока без Хайку: видео в 720р не посмотришь, нужного мне софта прикладного нет, да и сеть не поднимется на моей карте от intel, и так далее. Поэтому сразу на Дебиан я поехал.

anonymous
()
Ответ на: комментарий от anonymous

Видел тред на одной странице

Отправляешься в игнор, клоун.

byko3y ★★★★
()

Так и запишем, dimgel никогда не программировал на хаскеле.

anonymous
()
Ответ на: комментарий от hateyoufeel

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

anonymous
()
Ответ на: комментарий от menangen

Да такой дичи и в Раст нет. Это плод воспалённого воображения плюсаря, осилившего Растбук до 9 главы.

meliafaro ★★★★★
()
Ответ на: комментарий от meliafaro

Ну ты же не можешь пройти мимо треда в Development

Кстати, то удобно, так это то, что список, который я тебе отправил, автоматически обновляется!

anonymous
()
Ответ на: комментарий от anonymous

Кнопочку «Вход», для начала, пожалуйста. Все дискуссии продолжим после выполнения этого простого и логичного требования.

meliafaro ★★★★★
()
Ответ на: комментарий от meliafaro

Кнопочку «Вход», для начала, пожалуйста.

Вот тебя заклинило, клоун-параноик, тебе ещё сто раз повторить, что бывают анонимные анонимы? Всё тут правильно говорят, ты клоун ядовитый, неделю назад битовые операции изучал и что такое event loop, но лезешь в каждый тред по программированию гадить.

anonymous
()
Ответ на: комментарий от anonymous

Ненене, анон, так ты ничего не добьёшься. Ну и ТС тоже клоун ещё тот.

Я никогда не понимал людей, которые пытаются в серьёзные технические дискуссии на ЛОРе.

hateyoufeel ★★★★★
()
Ответ на: комментарий от anonymous

Вот тебя заклинило, клоун-параноик, тебе ещё сто раз повторить, что бывают анонимные анонимы? Ну и всё, значит, иди воруй.

meliafaro ★★★★★
()
Ответ на: комментарий от meliafaro

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

anonymous
()
Ответ на: комментарий от anonymous

Ты тот же дятел, который по всем тредам про «дрист» отмечается?

Посмотри внимательно. Я задал пару встречных вопросов, после первого же вопроса ТС начал тыкать мне растбуком и упрекать в том, что я троллю и туплю. Жаль, он меня заигнорил, я теперь так и не узнаю, в какой главе растбука рассказывается про fun. Теперь ещё раз: где именно я себя повёл некорректно?

meliafaro ★★★★★
()

В позиции параметра эти две конструкции эквивалентны:

fn foo<T: Bar>(t: T) {
    /*...*/
}

fn foo(t: impl Bar) {
    /*...*/
}

Так сделали не от большого ума, а потому что кто-то предложил «за компанию добавить и в параметры». ИМХО, зря.

В первую очередь это ввели для случая с возвращаемым значением. Если конкретно: потому что замыкание имеет конкретный тип, но ты его не можешь назвать:

fn foo(a: i32) -> /* ??? */ {
    move |x: i32| a * x
}

impl существует скорее всего из-за семантики:

  • dyn Trait - что угодно, безразмерное.
  • impl trait - что-то одно, конкретное, размерное.

А просто Trait - это класс типпов, а не тип, поэтому возвращать его - какой-то нонсенс.

anonymous-angler ★☆
()
Последнее исправление: anonymous-angler (всего исправлений: 1)
Ответ на: комментарий от anonymous-angler

Справедливости ради, этот синтаксис нигде на практике не используется. В реальном коде ни разу не видел.

meliafaro ★★★★★
()
Ответ на: комментарий от meliafaro

В позиции аргумента не видел нигде, в позиции возвращаемого значения видел и не раз, не не в публичном API.

anonymous-angler ★☆
()
Последнее исправление: anonymous-angler (всего исправлений: 1)
Ответ на: комментарий от anonymous-angler

Они не эквивалентны. Уже выше давали ссылку, одно универсальный тип, другое экзистенциальный. Разница например в том, что в первом случае можно передать параметр через ::<T>, а во втором нельзя.

anonymous
()
Ответ на: комментарий от dimgel

Трейты в расте, не то, что ты от них ожидаешь, от этого и Бангладеш. Попей водицы, попустит. Заходишь с позиции крестошор и требует исправить под крестоманямир. Любое, «ласковый, выйди и зайди нормально», принимаешь, как личное оскорбление. По вопросу, это сахар на угловатоскобочную конструкцию ограничения обобщенного типа трейтами которые он вроде как должен реализовать чтобы все было чики-пуки. Если ты спрашиваешь зачем все это, то для того чтобы сделать борроучекеру приятно и проще, вся многословность раста от проблем нужды выражать и чекать в коде то, что крестописака вынужден постоянно держать в уме, все это маркеры. Ты вроде книгу читаешь, но видимо как-то по диагонали, там это все написано, может не очень подробно, но общую суть дают.

anonymous
()
Ответ на: комментарий от Aswed

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

anonymous
()
Ответ на: комментарий от Legioner

Отличный способ получить говна и быть проклятым потомками.

anonymous
()
А на ЛОР так спокойненько
Среди флуда, модераторов да берез,
Все ругливенько, все спорливенько,
Исключительная благодать.
anonymous
()
Ответ на: комментарий от anonymous

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

dimgel ★★★★★
() автор топика
Ответ на: комментарий от dimgel

Ну то есть низкопробный тролль без знания матчасти? В игнор!!Ё

anonymous
()
Ответ на: комментарий от dimgel

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

это я не тупой на самом деле, это я просто троллил так

anonymous
()
Ответ на: комментарий от anonymous

тс делает вид что не понимает что трейт это не класс

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

Aswed ★★★★★
()
Ответ на: комментарий от anonymous

это я не тупой на самом деле, это я просто троллил так

:)

dimgel ★★★★★
() автор топика
Ответ на: комментарий от dimgel

причём в условиях, когда ничто не мешало сделать синаксис одинаковым (обратное мне не объяснили) – по-прежнему идиотизм.

А dyn Trait тебя не смущает? Да, без impl, как и без dyn можно было обойтись, но сделано так специально: для наглядности, чтобы было трейт это или тип.

Вот когда конфликт возникнет, тогда и ругались бы на него.

Тоже раньше так думал.

Но вообще аргументация следующая: без данного ограничения минорное изменение в библиотеке (реализация трейта - это добавление функциональности, то есть минорное изменение) могло бы ломать твой код.

В моей практике живётся с ограничением вполне нормально, так что может и правильно сделали.

UPD2. fn vs fun – зачем отдельный keyword для лямбд?

Мне тоже интересно откуда взялось fun.

обратное мне не объяснили

Ты всё-таки учебник читаешь - в нём нет смысла разжёвывать почему каждая фича имеет именно такой вид. Ради этого, если правда интересно, можно к конкретным RFC обращаться.

DarkEld3r ★★★★★
()
Последнее исправление: DarkEld3r (всего исправлений: 1)
Ответ на: комментарий от dimgel

Например, pattern matching прям очень порадовал, нормальный stack trace при ошибках в рантайме тоже, но это нифига не бесплатные вещи.

А в чём «платность» паттерн матчинга? Только чур сравнивать эквивалентный код, а не switch по инту со сложным матчем.

Ну и я бы, пожалуй, поставил на то, что в С++ паттерн матчинг рано или поздно завезут.

ЗААААШИБИСЬ надёжность: кто-то в либе случайно впилил unwrap() – и до свидания.

Кто-то случайно в либе впилил abort и до свидания.

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

А в чём «платность» паттерн матчинга? Только чур сравнивать эквивалентный код, а не switch по инту со сложным матчем.

Если сравнивать эквивалентный код, то результат будет эквивалентен. :) Я про то, что PM по классу требует RTTI. Сам я RTTI вообще нигде не использую, так что у меня тот самый switch по инту (точнее enum-у). Классов, по подклассам которых нужна динамическая диспетчеризация – доля процента, а RTTI генерируется для всех классов вообще, и в итоге моя жаба смотрит на размер бинарника, потом смотрит внуть его – и давит.

Кто-то случайно в либе впилил abort и до свидания.

Нет. В плюсовой либе я вместо abort() кину из вспомогательной функции на глубоком уровне вложенности исключение – и точно также забуду про него. Мне не надо помнить на всех предыдущих уровнях про то, что у меня тут может быть ошибка: при обычном плюсовом кодинде RAII вывезет автоматом, даже задумываться не нужно. Кто-нибудь наверху да поймает.

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

Это примерно как жаверы вместо того, чтобы пердолиться, прописывая throws IOException, ..., ... в каждом методе, либо тупо пишут throws Exception вообще везде (что тоже бьёт по глазам, хотя привыкнуть можно), либо бросают ТОЛЬКО unchecked (в т.ч. заворачивают в unchecked приезжающие из стандартной либы checked), либо юзают аннотацию @lombok.SneakyThrows чтобы checked в unchecked не заворачивать (мой любимый способ на жаве), либо переезжают на скалу (авторы которой, посмотрев на эту дичь, сознательно отказались от checked).

Мне тоже интересно откуда взялось fun.

Так. Теперь мне тоже стало интересно, и я-таки нашёл: оно вообще не из раста взялось. Сорри. :) Глупо было читать два туториала по разным языкам одновременно.

dimgel ★★★★★
() автор топика
Последнее исправление: dimgel (всего исправлений: 2)
Ответ на: комментарий от dimgel

при обычном плюсовом кодинде RAII вывезет автоматом

Это который заставляет писать shared_ptr, make_unique и прочее, которое, конечно, не вызывает желания срезать углы и использовать указатель?

red75prim ★★★
()
Ответ на: комментарий от red75prim

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

А во-вторых, мне эти умные указатели в небольшом проекте на сотню тыщ строк потребовались 2 или 3 раза. Всё остальное – автоматика на стеке (а указателями рулит stdlib++).

dimgel ★★★★★
() автор топика
Последнее исправление: dimgel (всего исправлений: 1)
Ответ на: комментарий от dimgel

Если сравнивать эквивалентный код, то результат будет эквивалентен. :) Я про то, что PM по классу требует RTTI.

Дык, в расте нет наследования (объектов), так что и RTTI не нужно. И матчинг по плюсовому variant будет выглядеть заметно страшнее.

Нет. В плюсовой либе я вместо abort() кину из вспомогательной функции на глубоком уровне вложенности исключение – и точно также забуду про него.

Ну почему нет? Мы же говорим «а вдруг кто-то сделает глупость». Ну так, кто мешает аборт воткнуть? Или ладно, возьмём исключения: throw 1. Ну а вдруг?!

Кто-нибудь наверху да поймает.

Ага. И увидит пользователь «неизвестная ошибка, попробуйте снова» и будет счастлив. Правильная обработка ошибок на исключениях тоже не появляется сама собой.

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

Безусловно. Вот только мы выбираем библиотеку обычно с определёнными обещаниями качества. И вероятность получения throw 1 и unwrap из нормальной библиотеки примерно одинакова.

Так же между анврапами и качественными ошибками есть промежуточный вариант: использовать какой-нибудь общий тип ошибок везде (библиотека anyhow или даже тупо Error(String)). В плане написания он местами даже проще, чем лепить везде unwrap. Ну и панику можно перехватить, если что.

В общем, мне кажется, что внезапная паника из нормально библиотеки - это большая редкость.

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

И увидит пользователь «неизвестная ошибка, попробуйте снова» и будет счастлив. Правильная обработка ошибок на исключениях тоже не появляется сама собой.

Где-то выше я давал ссылку на пост Legioner. К тому посту имею добавить:

  1. Мне нужно ровно ДВА класса исключений: UserException(messageForUser) – и все остальные, которые логируются в файл с именем, равным хеш-коду содержимого файла, и юзеру показывается этот хеш-код ошибки. Поскольку «все остальные» в системе уже есть, мне хватает ОДНОГО класса исключений.

  2. Мне нужен ровно ОДИН обработчик исключений – в корневой точке входа, чтобы показывал ошибку юзеру.

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

Так же между анврапами и качественными ошибками есть промежуточный вариант: использовать какой-нибудь общий тип ошибок везде

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

dimgel ★★★★★
() автор топика
Последнее исправление: dimgel (всего исправлений: 1)
Ответ на: комментарий от dimgel

Может для меня это уже вопрос привычки, но правильная обработка ошибок на исключениях – тривиальна.

Ну если нас устраивает перехват всего чего можно на самом верхнем уровне и с записью в лог (или показыванием окошка пользователю), то тогда, конечно, ничего сложного. Но ведь и в расте в таком случае можно воткнуть catch_unwind. С точки зрения «а вдруг что-то откуда-то вылетит» разницы не будет. Но да, это не решает проблему с явностью передачи Result на всех уровнях.

Ну и всё-таки если при написании кода не получится полностью игнорировать обработку ошибок: бывает нужно в конкретном месте решать является ли данная конкретная проблема невосстановимой ошибкой или нет. Или может быть наоборот: библиотечная функция возвращает bool/код ошибки/опциональное значение, а мы с этим ничего сделать не можем и уже сами кидаем исключение. И в этом случае явные Result позволяют реже в доку заглядывать.

Это несколько перекликается с вышенаписанным, но пойнт спора мне кажется был не в количестве разных типов ошибок. :)

Это я к тому, что не обязательно обмазываться анврапами, можно довольно легко сделать «правильную» обработку ошибок. Для приложений (а не библиотек) в таком подходе так и вообще нет ничего плохого.

Но да, сути в плане передачи ошибок это не меняет.

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

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

В этом случае что я с исключением, что ты с Result – будем действовать совершенно одинаково: преобразовывать один exception/result в другой: я через try {} catch { throw }, ты по-людски. По-людски в данном случае будет покороче и посимпатичнее, но зато я пердолюсь с try-catch только там где мне надо – в местах преобразований, а ты дополнительно проставляешь ‘?’ в каждом вызове.

Или может быть наоборот: библиотечная функция возвращает bool/код ошибки/опциональное значение, а мы с этим ничего сделать не можем и уже сами кидаем исключение.

Типичный сценарий для плюсовых обёрток сишных либ. Не потому что ничего не можем – можем: и на плюсах в сишном стиле зафигачить. Но когда вокруг один сплошной RAII, то глупо от него отказываться и плодить бардак.

И в этом случае явные Result позволяют реже в доку заглядывать.

Туплю. Или ты про пользу явных спецификаций ошибок? Хз… И вообще чёт я устал. :/

dimgel ★★★★★
() автор топика
Последнее исправление: dimgel (всего исправлений: 2)
Ответ на: комментарий от dimgel

Или ты про пользу явных спецификаций ошибок?

Ага.

И вообще чёт я устал. :/

Аналогично. (:

Тем более, что споры «исключения против явных результатов» далеко не новые и все аргументы уже не раз были сказаны.

DarkEld3r ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.