LINUX.ORG.RU

Rust 1.12

 


1

6

Команда разработчиков Rust рада представить релиз Rust 1.12 — системного языка программирования, нацеленного на безопасную работу с памятью, скорость и параллельное выполнение кода. В этот релиз вошёл 1361 патч.

Новое в 1.12

По словам разработчиков, релиз 1.12 является, возможно, самым значительным с момента выпуска релиза 1.0. Самое заметное для пользователей изменение в версии 1.12 — это новый формат ошибок, выдаваемых rustc. Сообществом была проделана многочасовая работа по переводу вывода ошибок на новый формат. Кроме того, для лучшей интеграции и взаимодействия со средой разработки и другим инструментарием ошибки теперь можно выводить в формате JSON при помощи специального флага --error-format=json.

Самое большое внутреннее изменение — это переход на новый формат внутреннего представления программы MIR. Незаметное сегодня, это изменение открывает путь к череде будущих оптимизаций компилятора, и для некоторых кодовых баз оно уже показывает улучшения времени компиляции и уменьшение размера кода. Переход на MIR открывает ранее сложнодоступные возможности анализа и оптимизации. Первое из многочисленных грядущих изменений — переписывание прохода, генерирующего промежуточное представление LLVM, того, что rustc называет «трансляцией». После многомесячных усилий новый бэкенд, основанный на MIR, доказал, что готов к реальной работе. MIR содержит точную информацию о потоке управления программы, поэтому компилятор точно знает, перемещены типы или нет. Это значит, что он статически получает информацию о том, нужно ли выполнять деструктор значения. В случаях, когда значение может быть перемещено или не перемещено в конце области действия, компилятор просто использует флаг из одного бита на стеке, что, в свою очередь, проще для оптимизации проходов в LLVM. Конечный результат — уменьшенный объем работы компилятора и менее раздутый код во время исполнения.

Другие улучшения:

  • Множество мелких улучшений документации.
  • rustc теперь поддерживает три новые цели MUSL на платформе ARM: arm-unknown-linux-musleabi, arm-unknown-linux-musleabihf и armv7-unknown-linux-musleabihf. Эти цели поддерживают статически скомпонованные бинарные файлы. Однако, в собранном виде они пока не распространяются.
  • Повышена читабельность описаний ошибок в ссылках и неизвестных числовых типах.
  • Компилятор теперь может быть собран с LLVM 3.9.
  • Тестовые бинарные файлы теперь поддерживают аргумент --test-threads для указания количества потоков для запуска тестов, который действует точно так же, как переменная окружения RUST_TEST_THREADS.
  • В случае продолжительности выполнения тестов больше минуты показывается предупреждение.
  • Вместе с выпусками Rust теперь доступны пакеты с исходными кодами, которые можно установить при помощи rustup через команду % rustup component add rust-src. Исходные коды могут быть использованы для интеграции и взаимодействия со средой разработки и другим инструментарием.
  • Ускорено обновление индекса реестра.
  • cargo new получил флаг --lib.
  • Добавлен вывод профиля сборки (release/debug) после компиляции.
  • cargo publish получил флаг --dry-run.
  • Сокеты на Linux в подпроцессах теперь закрываются правильно через вызов SOCK_CLOEXEC.
  • Определения Unicode обновлены до 9.0.

Стабилизация библиотек:

  • Cell::as_ptr и RefCell::as_ptr.
  • IpAddr, Ivp4Addr и Ipv6Addr получили несколько новых методов.
  • LinkedList и VecDeque теперь имеют новый метод contains.
  • iter::Product и iter::Sum.
  • Option реализует From для содержащегося в нём типа.
  • Cell, RefCell и UnsafeCell реализует From для содержащихся в них типах.
  • Cow<str> реализует FromIterator для char, &str и String.
  • String реализует AddAssign.

Возможности Cargo

Самая большая возможность, добавленная в Cargo в этом цикле — «рабочие области». Описанные в RFC 1525, рабочие области позволяют группе пакетов разделять один общий файл Cargo.lock. Это позволяет намного легче придерживаться единственной версии общих зависимостей при наличии у вас проекта, который делится на несколько пакетов. Для включения этой возможности в большинстве мультипакетных проектов достаточно добавить одну единственную строчку [workspace] в Cargo.toml верхнего уровня, более сложным установкам может потребоваться дополнительная настройка.

Другая существенная возможность — переопределение источника пакета. При помощи инструментов cargo-vendor и cargo-local-registry можно переопределять зависимости локально (vendoring). Со временем это станет фундаментом для построения инфраструктуры зеркал crates.io.

>>> Подробный список изменений

>>> Подробности

★★★★★

Проверено: Falcon-peregrinus ()
Последнее исправление: Falcon-peregrinus (всего исправлений: 10)

Ответ на: комментарий от asaw

Ну а как ещё если ты не понимаешь, что ООП и есть метод декомпозиции?

А какое там основное правило структурной парадигмы?

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

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

Да-да, придумали огромный костыль: https://github.com/rust-lang/rfcs/pull/1023 А всё потому, что инкапсуляции данных нет.

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

А какое там основное правило структурной парадигмы?

Стркутурная парадигма - это структурная парадигма, а ООП - это ООП. Это разные подходы.

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

Так а интерфейс то у А какой? Чтобы это понять я должен пройтись по всем его impl не так ли?

Достаточно посмотреть impl A {..}, во всех остальных случаях интересовать должно не «а какой интерфейс у A», а «реализует ли A такой-то интерфейс», а где это искать зависит от того какой типаж. Если твой, то у тебя, если не твой, то в библиотеке, которая предоставляет A.

Соб-но, так документация и строится: https://docs.rs/, выбирай любой для примера.

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

Причём тут инкапсуляция-то?

Специализация решает конкретный кейс: есть очень общее определение, скажем «реализовать ToString для всего, что реализует Display простым вызовом display()», а ты хочешь переопределить это своего конкретного типа этот самый ToString (в целях оптимизации).

В крестах этот обобщённый «ToString для Display» в принципе невозможно сделать (костыль через множественное наследование 100500 «классов» мы не рассматриваем). Вот и профукалось ваше ООП.

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

Достаточно посмотреть impl A {..}, во всех остальных случаях интересовать должно не «а какой интерфейс у A», а «реализует ли A такой-то интерфейс», а где это искать зависит от того какой типаж. Если твой, то у тебя, если не твой, то в библиотеке, которая предоставляет A.

Вот и получается, что в Расте ты думаешь не в терминах интерфейса объекта, а в терминах реализации. Потому что объект и его поведение (интерфейс) изначально никак не связяны. Связываются они только реализациями. Причем, множество этих реализаций практически никак не ограничивается (за исключением упомянутого выше костыля).

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

Причём тут инкапсуляция-то?

При том, что именно инкапсуляция связывает состояние объекта с поведением - данные с интерфейсом.

В крестах этот обобщённый «ToString для Display» в принципе невозможно сделать (костыль через множественное наследование 100500 «классов» мы не рассматриваем). Вот и профукалось ваше ООП.

Ну да, если выкинуть из языка именно ту фичу, с помощью которой это и реализуется (предварительно высказав про неё своё субъективное мнение и обозвав костылём), то можно сказать, что невозможно (хотя там ещё CRTP остаётся для реализации концепций типа mix-in). А так ещё Скотт Майерс 15 лет назад описывал как такие вещи делать.

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

Дык, а кто тут утверждает что ООП и есть декомпозиция?

ООП - один метод декомпозиции. Структурная парадигма - другой.

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

[quota] Почему тебе не посмотреть реализацию stdlib? https://doc.rust-lang.org/std/net/ [/quota]

Посмотрел, в принципе та проблема которая меня интерисует может быть решена по средством композиций трейтов с дефолтной реализацией:

trait BaseSocket {
   fn get_fd(&self) -> i32;
   fn close(&mut self) {
      do_sys_call_socket_close( self.get_fd() );
   }
}

pub struct UDPSocket {fd:i32};
impl UDPScoket {
  fn send_to(&mut self, &addr) {
    ......
  }
}

impl BaseSocket for UDPSocket {
   fn get_fd(&self) -> i32 { self.fd }
}

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

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

Но както выглядит не очень

Потому что это ненужная примитивщина, состоящая в основном из накладных расходов.

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

То, что ты об интерфейсе узнаешь не из строчки class A : public B, а из строчек impl Foo for A абсолютно ничего не меняет.

А можно мне твоё видение impl<T> ToString for T where T: Display + ?Sized в Ъ-ООП стиле?

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

Потому что это ненужная примитивщина, состоящая в основном из накладных расходов.

В смысле ? Я чтото не так понял или в том плане что свои сокеты велосипедить никому не нужно ?

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

(предварительно высказав про неё своё субъективное мнение и обозвав костылём)

(за исключением упомянутого выше костыля)

Какие двойные стандарты.

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

Ненужная - значит, что ты пытаешься абстрагировать какие-то ненужные вещи. Если делаешь библиотеку сокетов, то хотя бы не занимайся банальщиной вроде «абстракции read/write/close», а попытайся абстрагировать что-то полезное вроже «байтовый поток vs дискретные сообщения» (как сделано в Rust).

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

Я не делаю библиотеку сокетов. Я пытаюсь расмотреть конкретную проблему на конкретном примере. А именно общую кодовую базу при реализации двух различных сущностей не более того ...

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

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

Вообще-то классическое определение - это изоляция внутренней реализации от интерфейса, и сокрытие подробностей реализации. Ну ОК, давайте возьмём ваше определение. Итак, в чем отличие крестового класса от растовой структуры? Не касаясь различия в АБИ, и там и там есть данные и методы. На первый взгляд, различие в том, что в цпп в объявлении класса перечислены также методы, что, конечно, никак не обеспечивает более плотную связь, но, по идее, делает поиск интерфейса класса чуть проще. Но только на первый взгляд: и IDE (даже те, что есть сейчас), и автоматически сгенерированная документация в расте отлично покажет и трейты и методы структуры, с другой стороны из-за наследования в объявлении крестового класса объявлены не все методы и данные, а из-за необходимости объявлять также и приватные методы и дружественные функции и классы, объявление класса настолько захламлено, что никакой особой ясности там нет. В итоге и там и там «связь» класса и методов находится либо через подсказку IDE, либо через документацию. С другой стороны, реализация интерфейсов «сбоку» имеет свои плюсы именно с точки зрения ООП. Согласно принципам ОО дизайна, клиентский код должен зависеть от абстрактного интерфейса, а не конкретных реализаций. Что означает необходимость включения в интерфейс всех частей алгоритма, которые могут варьировать я от реализации к реализации. С другой стороны эти же принципы требуют не перегружать интерфейс, да и не факт, что интерфейс и конкретные классы доступны для модификации. Чтоб решить этот конфликт, нужно городить копию дерева типов из адаптеров. В расте адаптеры не потребуются, просто свой трейт и реализации для конкретных типов.

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

То, что ты об интерфейсе узнаешь не из строчки class A : public B, а из строчек impl Foo for A абсолютно ничего не меняет.

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

А можно мне твоё видение impl<T> ToString for T where T: Display + ?Sized в Ъ-ООП стиле?

Если тебе нужна не-ООП фича, то тебя никто не заставляет использовать ООП, можешь просто использовать обобщенные функции со специализациями/частичными специализациями - C++ это может, если ты про это. Если, всё же, хочется именно ООП, то есть известный паттерн на эту тему: https://en.wikipedia.org/wiki/Visitor_pattern

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

Да хоть сто вложенных модулей. Мне ничего не помешает, например, приделать к этому же самом объекту новое поведение в другом месте. То есть все думали, что объект типа «улитка» умеет только ползать, а она вдруг раз - и полетела, потому что какой-то шутник прилепил к ней трейт Wings. С другой стороны, поскольку инкапсуляции нет, то нет и наследования поведения когда это нужно. Потому что невозможно сделать наследование сферического поведения в вакууме. Поведение в общем случае связано с состоянием, то есть с данными.

Во-первых, в тех же c++ такое тоже возможно. class Mysnall: public Snall, public Wings { и привет, код, который не создаёт объект сам (а с фабриками никто не создаёт объект сам) не может быть уверенным в свойствах. Более того, даже интерфейс Wings не нужен, просто наследовался и переопределил какой-нибудь CanFly и привет. В этом как раз и проблема наследования реализаций. Во-вторых, в расте навешивание трейтов ограничено. Навесить можно любой трейт на свой тип, либо свой трейт на любой тип. Если тип улитка или трейт крылья определены тобой, тебе лучше знать, умеет ли улитка летать. Если кому-то нужно отправить улитку на другой конец Земли, он может реализовать для неё свой трейт FlyByPlane, реализовать посадку улитки в самолёт посредством её стандартных движений.

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

Вообще-то, похоже, никто так и не понял, что ты пытаешься растолковать. «тут инкапсуляция есть, а тут нет, потому что я так сказал».

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

Во-первых, в тех же c++ такое тоже возможно. class Mysnall: public Snall, public Wings {

Нет, тут смысл в том, что в C++ ты для этого создаешь НОВЫЙ ТИП, а в расте ты можешь волшебным образом добавить новое поведение старому.

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

в расте ты можешь волшебным образом добавить новое поведение старому.

Ровно таким же способом можно добавить новое поведение и в Си++ .

class Flyable {
  Snail *snail_;
public:
   void fly() { snail_->crawl(); }
}
tailgunner ★★★★★
()
Ответ на: комментарий от asaw

С каких это пор добавление нового поведения нарушает инкапсуляцию данных? Может ты еще скажешь что в C# нет инкапсуляции, потому что там есть extension методы?

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

Нет, тут смысл в том, что в C++ ты для этого создаешь НОВЫЙ ТИП, а в расте ты можешь волшебным образом добавить новое поведение старому.

Как я уже писал, в мире IOC и фабрик ты не работаешь с типами, ты работаешь с объектами этого или наследуемого типа, которые, весьма вероятно, создаёшь не сам. Ну вот у меня есть код

void PetCollection::AdoptPet(Snail*newPet)
{
    m_Fence.Add(newPet); // помещаем за оградку, так как не умеет прыгать или летать
}
И тут приходит WingedSnail и всё падает. Почему? Потому что кривая C++/С#/Java поддержка ООП позволяют наследование реализаций и не разделяют указатель на конкретный тип и указатель на базовый тип для ОО. В расте так не получится, если я принимаю улиток, то получу я улитку. Если принимаю животное, то должен ожидать, что животное может оказаться любым.

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

Вашему терпению можно позавидовать. Вы столько времени пытаетесь донести до Rust-оманов простые и очевидные вещи, но все как горохом о стену.

Логику же Rust-оманов в данном случае вообще понять не могу. Ну вот есть устоявшееся определение ООП. Ну не подходит Rust под это определение. Но зачем-то Rust-оманам нужно натягивать сову на глобус. Ведь можно же просто сказать — этот ваш ООП отстой в принципе, поэтому в Rust-е сделали следующий шажок в эволюции и решают эти же проблемы другими средствами. И эти средства типа лучше, чем классический ООП.

Но вместо этого начинается — ООП кривой, наследование реализации — кривизна, ООП в C++/C#/Java — кривое и т.д., и т.п. А вот в Rust-е ООП — такое как надо ООП. Настоящее.

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

Вашему терпению можно позавидовать.

Вы не понимаете. Человек мир спасает. Ради такой цели сутками на форуме сидеть - тьфу. Ведь если не прибить процедуры к данным гвоздями, то что угодно может случиться.

Только представьте: кто-то может реализовать метод reproduce(e: Environment) для структуры Virus, хотя это структура не унаследована от структуры Animal. Ужасно. Если человек на такое решился, то у него уже нет никаких моральных ограничений. Я даже не хочу думать, что он там может понаписать. /s

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

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

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

Интереснее то, что наследование конфликтует с твоим определением инкапсуляции, потому что поведение задаётся не здесь, а в базовом классе.

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

Действительно, не понимаю. ООП — это устоявшаяся за 30+ лет троица: инкапсуляция, наследование, полиморфизм. Если это все в языке X из коробки — значит язык X можно назвать ООЯ. Нет — значит нельзя.

Не более того.

Если язык не ООЯ, это вовсе не значит, что он плох и что на нем разрабатывать софт сложнее, чем на ООЯ. Это просто значит, что язык не ООЯ. Посему называть его ООЯ или говорить, что он поддерживает ООП просто не правильно.

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

в расте ты можешь волшебным образом добавить новое поведение старому.

Новое поведение на основе его публичного интерфейса и только если типаж твой. Пример с улиткой от khrundel очень показателен, перечитал бы ты его ещё разок.

ты для этого создаешь НОВЫЙ ТИП

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

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

Вот и получается, что в Расте ты думаешь не в терминах интерфейса объекта, а в терминах реализации.

Реализация - это то, что в фигурных скобочках. А интерфейс - это название функции и её сигнатура (та штука, которую в C/C++ копипастят в/из заголовочные(х) файлы(ов)). В Расте, созданием человекочитаемой документации на интерфейс занимается генератор документации.

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

Эй нет, вряд ли здесь какой-то rustоман будет утверждать, что там есть ООП (как минимум потому что под ООП сегодня понимается всё что угодно, поэтому и говорить об этом смысла чуть более, чем нисколько). Но тут приходит человек и начинает оперировать отдельными понятиями (считая их каким-то особым свойством его недоязычков), которые, как внезапно выясняется, выполняются и в rust-е.

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

Это просто значит, что язык не ООЯ.

Спор в основном идет не о классификации Раста. asaw утверждает, что язык без наследования реализаций - не язык, а ходячее недоразумение, или что-то в этом роде.

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

Мне показалось, что речь о другом. asaw говорит, что если в языке нет инкапсуляции и наследования (реализаций), то язык не поддерживает ООП, а это не есть хорошо, т.к. ООП уже доказало свою состоятельность и т.д. и т.п.

На что ему говорят, что в С++/C#/Java — кривое ООП, а вот в Rust-е то с ООП все нормально как раз из-за того, что в языке нет ни инкапсуляции, ни наследования реализации.

Безотносительно того, прав ли asaw в том, что ООП нужно, аргументы против точки зрения asaw-а выглядят довольно странно. Причем формально-то asaw прав: нет соответствия святой троице ООП — нет и ООП в языке.

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

Нет, не скажу. Там есть инкапсуляция и есть extension методы. Или как в C++ - есть инкапсуляция, и есть free functions. А вот в Си инкапсуляции нет, есть только free functions, хотя даже вполне можно привязывать функции к объектам.

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

Добавление трейта ничем не отличается от добавления extension метода. И раз второе не нарушает инкапсуляцию по твоему мнению, значит и первое не должно.

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

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

Так в этом то и предмет обсуждения: что непосредственно позволяет выразить язык. В Си тоже можно «не смотреть на синтаксис, а смотреть на семантику», и видеть там ООП, только это не означает, что в Си есть поддержка ООП.

Интереснее то, что наследование конфликтует с твоим определением инкапсуляции, потому что поведение задаётся не здесь, а в базовом классе.

Я здесь никаких своих определений не приводил, только общепринятые.

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

Да, вот вы правильно уловили суть. Причем, я же не говорю, что полноценной поддержки ООП в расте никогда не будет потому что её там не может быть, я просто говорю, что сейчас там нет поддержки пары основных принципов. И именно это, по моему мнению, является причиной того, что некоторые проекты на Rust превратились в bloatware.

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

И именно это, по моему мнению, является причиной того, что некоторые проекты на Rust превратились в bloatware.

Недавно как раз был соответствующий наброс: Why I’m dropping Rust. IIRC, человек там как раз жаловался на отсутствие наследования реализации.

Понятное дело, что православные Rust-оманы уже предали автора сего опуса обструкции :)

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

Добавление трейта ничем не отличается от добавления extension метода. И раз второе не нарушает инкапсуляцию по твоему мнению, значит и первое не должно.

Как можно нарушить что-то, если его и так нет?)

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

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

Правильно. Раст позволяет выразить то, что ты подразумеваешь под инкапсуляцией. То, что для этого используются другие ключевые слова суди дела не меняет. А стоит ли так писать код, когда язык предоставляет лучшие концепции это второй вопрос.

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

Причем формально-то asaw прав: нет соответствия святой троице ООП — нет и ООП в языке.

Инкапсуляция есть, что бы asaw не думал.

mod M {
    pub struct S {private_field: u32}
    impl S { pub public_interface(&self) {} }
}

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

Открытой рекурсии нет (https://en.wikipedia.org/wiki/This_(computer_programming)#Open_recursion). Это верно. Впрочем, о проблемах открытой рекурсии известно давно (см. ссылки на литературу в википедии). Поэтому, кстати, и можно говорить о «кривизне С++/С#/Java».

Наследование реализаций для ООП не обязательно.

Да и вообще, ООП это такое размытое понятие, что спорить об определениях особого смысла нет. В статье из википедии, куча ссылок на литературу, где пытаются систематизировать, что же всё-таки такое ООП. Формального определения, насколько я знаю, нет.

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

На что ему говорят, что в С++/C#/Java — кривое ООП, а вот в Rust-е то с ООП все нормально как раз из-за того, что в языке нет ни инкапсуляции, ни наследования реализации.

Кто это тут говорит из людей, которые хотя бы документацию раста освоили, что в языке нет инкапсуляции?

Ну а кривое ООП или не кривое в С++/С#/Java это сложный вопрос. С точки зрения какого-нибудь smalltalk-а там и не ООП вообще, в отличие от современного догмата «ООП = классовая модель + троица».

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

Как можно нарушить что-то, если его и так нет?

Я не говорю что (классическое) ООП в Rust есть, я говорю только про инкапсуляцию, и она есть пока не доказано что ее нету (презумпция невиновности). Я все пытаюсь вытянуть из тебя что же все таки мешает расту иметь инкапсуляцию, но все твои аргументы сводятся к

Этого в расте нет, точка.

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

Правда заключается в том, что человек пытался использовать парадигмы других языков в Rust и у него не получилось. Не более.

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

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

Я все пытаюсь вытянуть из тебя что же все таки мешает расту иметь инкапсуляцию

Отсутствие языковых средств для выражения состояния и поведения типа как единой сущности.

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

А зачем так сложно, когда есть free functions?

А причем здесь free functions, если речь о трейте?

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