LINUX.ORG.RU

Rust и двусвязный список

 , двусвязный список,


4

2

Хорошую тему тут затронули

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

http://contain-rs.github.io/linked-list/src/linked_list/lib.rs.html#11-1388

Или не лучшее? Растаманы и растафобы, собирайтесь на великую битву!

А вот, кстати, ещё про списки:

https://rust-unofficial.github.io/too-many-lists/

★★★★★

Последнее исправление: den73 (всего исправлений: 1)

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

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

Они есть: используй Rc<RefCell<_>>

То, что тут пишет про их ненужность, для меня выглядит несколько некомпетентным.

Некомпетентным выглядит тот, кто говорит о нужности структур и алгоритмов и критикует имплементацию в отрыве от задачи

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

https://www.youtube.com/watch?v=-c9I4ixB3Rg&ab_channel=%D1%81%D0%B5%D1%80%D0%B3%D0%B5%D0%B9%D1%82%D0%BE%D1%80%D0%BC

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

Щито поделать. Бизесу, который кормит программистов, проще купить доп серверную стойку чем согласиться на трату времени на оптимизацию кода.

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

Некомпетентным выглядит тот, кто говорит о нужности структур и алгоритмов и критикует имплементацию в отрыве от задачи

Видишь, у нас консенсус: собеседник выглядит некомпетентным. На этом можно и остановиться.

Они есть: используй Rc<RefCell<_>>

Раст, прославленный системный язык, не уступающий Си по скорости. Но почему-то решение уровня Visual Basic.

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

Бизесу, который кормит программистов, проще купить доп серверную стойку чем согласиться на трату времени на оптимизацию кода

И самое смешное то, что многие составляющие этой неоптимальности не вызваны ускорением разработки. Например, если у вас питон молотит числа или обслуживает высоконагруженное API в проде, то это никакое не ускорение разработки ценой неоптимальности, это просто безумная херотень — есть ведь даже питоноподобные компилируемые диалекты. Реально по назначению питон используется именно в том проекте, в котором я сейчас работаю, то есть, никсовая скриптовуха, bash++ — больше у питона нет применений, даже в датасаенсе питон очень спорный.

В чем неудобство сплошного массива? Почему мне нужен связанный список, дерево? (разговор изначально был про связанные списки) Быстрое удаление можно сделать маркером удаления — это работает как для простых массивов, так и для ассоциативных. Накопили много маркеров или нужно сильно расширить массив — переформируем копированием. И такой контейнер довольно прост в реализации, это не «оптимизация».

Связанный список и вообще долгоживущие указатели на данные — это чисто сишная заморочка. Даже у Apple в Objective C были дескрипторы объектов вместо указателей, что давало сразу и дополнительную отказоустойчивость, и возможность дефрагментации памяти. Самое-самое смешное то, что построенные на указателях структуры данных уже с 80-х годов перестали быть эффективными как в плане производительности, так и в плане потребления памяти — оно стало рудиментом в чистом виде. И бинарные деревья знаменитые, которые спрашивают на каждом втором собесе, даже если нанимают фронтэндера — это тоже рудимент, совсем не имеющий практического применения в 21-м веке, поскольку опираются на те же персистентные указатели с фрагментацией и неэффективный произвольный доступ, что и связанные списки.

Но тут, опять же, мы приходим к

проще купить доп серверную стойку чем согласиться на трату времени на оптимизацию кода

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

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

Внезапно, Rust не повышает стабильность — падение с сегфолтом обычно не отличается от падения с паникой.

Сразу видно, что о предмете спора Вы только слышали. Ну и, может быть, написали Hello World

Ты намекаешь на то, что налюбившись с борроу чекером я типа «автоматически» получаю проверку корректности? А мое время работы ничего не стоит? Вообще-то за это время можно было сделать ревью, тестирование — это методы намного более универсальны для повышения стабильности, чем борроу чекер, который не умеет ничего, кроме проверки прав владения в стэковой организации ресурсов. Да какие там гарантии — оно ведь unsafe-ы проверять не умеет. То есть, область где оно вообще как-то работает, заметно меньше области, где оно не помогает никак. И то «помогает» — спорное слово, учитывая тот факт, что оно при этом также «мешает», заставляя программиста больше потеть над описанием типов и времени жизни.

Я подчеркиваю слово «мешает» — именно мешает. Потому что внимание — это ограниченный ресурс, оно может использоваться либо для одной вещи, либо для другой. Rust потребляет внимание, именно потому он одновременно и мешает, и помогает.

У раста есть куча прикольных современных фишек, которые делают написание кода приятнее по сравнению с тем же C++, в нем отсутствует ряд бессмысленных UB, которых не должно было быть в C++ изначально — но у C++ просто не было архитектуры, он бы слеплен в режиме «сначала делаем — потом думаем». Переработать C++ достаточно для того, чтобы получить хороший язык — даваться во все тяжкие с борроу чекером не нужно. Но эксперимент с растом был хороший да, результаты интересные, спасибо, можете закапывать.

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

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

Они есть: используй Rc<RefCell<_>>

А потом я добавил хвост к голове. Здесь уже написали, что связанный список на самом деле является весьма опасным контейнером, потому что есть слишком много способов, как его можно сломать: выковырять кусок, взять указатель на элемент и провтыкать его время жизни, или вставить кусок в совсем другой список и получить два списка в одном, или замкнуть список, «Один список сломал, другой — потерял».

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

Ты неправильном меня понял. Я не выступаю адвокатом двусвязных списков. Я лишь говорю, о том, что нет принципиальных преград для имплементации его в расте.

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

то есть, в нынешней индустрии почти никто не умеет в оптимизацию и масштабирование

Конечно есть. Но они там, где парадигма «проще купить ресурсов» не работает. Встроенное железо, реалтайм системы, марсоходы всякие. Даже игроделы под консоли в принципе вынуждены подобным заниматься. Но если говорить про обычную компанию, которая занимается web/android/ios, то да. Об оптимизации думают редко :(

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

На самом деле преимущество питона в проде в другом. А именно если что-то сломалось и просто анализ данных и sentry не помогает, то можно быстро зайти на контейнер, вставить в код import pdb и найти ошибку очень быстро.

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

Именно потому, если у нас есть опасная конструкция и якобы безопасный язык, то естественно задуматься над вопросом: а как этот безопасный язык может помочь обезопасить данную конструкцию? Ведь много опасных штуковин. Их все просто выкинуть? Давайте ножи и ружья тогда выкинем.

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

Раст, прославленный системный язык, не уступающий Си по скорости

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

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

Ну если предложение заменить двусвязный список массивом на самом деле можно как-то понять, то вот предложение писать только иммутабельный код в системном ЯП - уж совсем странное.

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

а как этот безопасный язык может помочь обезопасить данную конструкцию? Ведь много опасных штуковин. Их все просто выкинуть? Давайте ножи и ружья тогда выкинем

Да, я о том же: borrow checker и safe-unsafe на самом деле почти ни о то чего не защищают. Если не считать проблемы удаленного выполнения кода, то настоящее назначение этих инструментов — следить за индусами, сознательно заметающими под ковер баги, которые иначе бы выстрелили у совсем другого программиста. С другой стороны, надо понимать, что для индусоразработки вообще-то есть Java, Go, C#, JS, и прочие безопасные языки, которые защищают одного индуса от другого, а брать низкоуровневый язык и садить писать на нем индусов — это путь вникуда.

Тем не менее, именно под соусом снижения затрат на разработку Rust внедрялся в Мозилле. Посмеялись — и хватит.

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

А именно если что-то сломалось и просто анализ данных и sentry не помогает, то можно быстро зайти на контейнер, вставить в код import pdb и найти ошибку очень быстро

Visual Studio умеет такое делать для CLR уже не помню сколько лет. Это скорее не killer feature конкретного питона и Visual Studio, а убогость класс-ориентированного программирования, которое вынуждает массово использовать инлайны и прочие варианты отимизации, не поддающиеся отладке и горячей замене, поскольку код на классах без оптимизации ползает в десятки раз медленнее из-за всех этих ваших геттеров-сеттеров. Недавно Visual Studio научилось даже для сишного кода делать горячую замену, но она там сильно ограничена.

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

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

Внезапно, нет ничего странного. Если твоя структура данных влазит в линию кэша (64 байта), то ее проще скопировать, чем изменять по месту. Или если у тебя есть выбор между выборочным изменением по месту с произвольным доступ против полного преобразования с последовательным доступом, то в пределах L1 кэша полное преобразование с последовательным доступом в большинстве случаев выигрывает.

Напоминаю, что даже лиспы с питонами и прочими джаваскриптами применяли мутабельные структуры данных — просто потому, что памяти было мало, лишний раз держать копию было больно. У JS даже была калечная модель мутабельных прототипов, которая являлась подспорьем для создания весёлых багов и уязвимостей парсинга JSON. Проблема с памятью перестала быть актуальной уже в нулевых, но языки из 90-х в своих нишах уже окопались и выбить их не получится.

Посмотри на тот же RCU в ядре линя — это ведь по сути вариант имутабельной структуры данных, где обновление производится путем копирования, а не изменения по месту. Я подчеркиваю, что после извлечения элемента из RCU контейнера этот элемент нельзя изменять и переиспользовать — он строго подлежит высвобождению. А модель страниц памяти с copy-on-write?

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

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

Тем не менее, именно под соусом снижения затрат на разработку Rust внедрялся в Мозилле. Посмеялись — и хватит.

А кстати, достигли ли они этой цели?

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

Я имею в виду, что некорректно сравнивать panic и сегфолт в плане опасности. 1-е это скорее exception.

А любиться с борроу чекером это больше удел новичков.

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

Visual Studio умеет такое делать для CLR уже не помню сколько лет

Что, прям даже на удаленном сервере можно это сделать? Если да, то я впечатлен.

Это скорее не killer feature конкретного питона и Visual Studio, а убогость класс-ориентированного программирования

Не понял полета мысли от слова совсем

Недавно Visual Studio научилось даже для сишного кода делать горячую замену, но она там сильно ограничена

Ну сделать себе отельный перезагружаемый плагин в коде можно и без Visual Studio :) фишка интерпретируемых языков в том, что это можно сделать в люблм месте и без перекомпиляции проекта. А прост зашел на рабочую машину по ssh, в vim сделал пару правок, python module.py, и погнал. И это будет рабоать без остановки рабочего сервера даже

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

но языки из 90-х в своих нишах уже окопались и выбить их не получится.

Вообще-то там были какие-то поползновения заменить Си на Раст в ядре линукса. Так что даже языки из 70-х можно подвинуть.

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

Удобны они много где, но смелые мыслью молодые засранцы в Хаскеле почему-то засунули хеш-таблицы в io.

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

фишка интерпретируемых языков

если уж вспоминать старое, то common lisp одновременно:

  • компилируемый язык
  • имеет классы
  • можно заменять в любом месте и без перекомпиляции проекта
  • и даже без python module.py
  • имеет лучшую поддержку тредов (хотя да, там откровенно недоделано)

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

Так что популярность питона всё же связана не с его качествами, а с невежеством публики. А интерпретируемость к горячей замене отношения не имеет.

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

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

Для достаточно сложных алгоритмов у тебя его по прежнему не будет.

Ну что тут сказать, печально это. Собственно в этом и проблема C, пока дело касается простеньких утилит на управление ресурсами пофиг. Ну забудешь освободить память - так это вообще неважно если процесс завершается. И даже если останется указатель на освобождённую память - тоже не проблема почти всегда. Даже если используешь после освобождения, старые данные почти наверняка всё ещё там. Ну в самом худшем случае будет падать при выходе, если запускать из гуя то пользователь даже и не узнает. А вот когда это всё разрастается до доложивущего процесса, да расползается на многопоток, в этот момент и вдруг становится очень важно знать вот всё то что раст требует, кто чем владеет, не живёт ли ссылка дольше чем сам объект, из какого потока к объекту можно обращаться. Собственно раст от си отличается тем, что в C вся эта же информация описана в документации или комментах, и компилятор не следит за её актуальностью.

после чего точно так же остаются нерешенные проблемы асинхронного кода,

Давно за растом не следил, но вроде там и промизы есть, пусть и с немного непривычной семантикой, и макрос await, и либы для асинхронного IO уже чёрт знает сколько лет. Так что в этой области у него не хуже чем у других.

падение с сегфолтом обычно не отличается от падения с паникой.

В большинстве случаев чтоб программа на расте упала по панике её нужно об этом попросить. И подобные просьбы легко можно грепом отыскать.

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

Но эксперимент с растом был хороший да, результаты интересные, спасибо, можете закапывать.

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

Following a very successful first foray into Rust we are migrating an established codebase from C to Rust, and building new functionality primarily in Rust.

Наверное, опять менеджеры постарались и пропихивают.

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

Ведь много опасных штуковин. Их все просто выкинуть? Давайте ножи и ружья тогда выкинем.

Как у оружия есть предохранитель, так и у раста есть ансейф. Предлагаемая выше в теме реализация списка через (A)rc - это, конечно такое себе. Но язык позволяет, грубо говоря, опуститься на уровень С. При этом принято «небезопасные» штуки заворачивать в безопасное апи. Да, unsafe реализация может содержать ошибки со всеми прелестями в виде UB. Бороться с ними приходится традиционными методами вроде внимательного ревью, тестов, санитайзеров и т.д. Собственно, вопрос как раз в том какой процент ансейфа. byko3y рассказывает, что всё пропало - ансейф везде, поэтому смысла нет. У меня опыт сильно другой. Объективно измерить это сложновато.

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

Как у оружия есть предохранитель, так и у раста есть ансейф.

Понятно, надо бы на это посмотреть в реальной жизни.

Но язык позволяет, грубо говоря, опуститься на уровень С.

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

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

Тем не менее, именно под соусом снижения затрат на разработку Rust внедрялся в Мозилле. Посмеялись — и хватит.

А кстати, достигли ли они этой цели?

Нет конечно. Низкоуровневый код как было тяжело писать, так и остается тяжело. Да, можно на каждый чих копировать данные, но в таком случае ты бы не писал на расте, правильно? Нужно оптимизировать, нужно использовать unsafe. Тут придется оптимизированный код, а не бинарные деревья писать.

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

Я имею в виду, что некорректно сравнивать panic и сегфолт в плане опасности. 1-е это скорее exception

Это не «скорее exception», это он самый и есть. Для большинства применений «в плане опасности» разницы между паникой, сегфолтом, и необработанным исключением нет — программа одинаково валится. К слову, именно потому я пишу, что исключения проблему обработки ошибок никак не решают. А браузеры и операционные системы пишут единицы — и то чот я не вижу ОС на Rust.

А любиться с борроу чекером это больше удел новичков

Я тоже так умею: «сегфолты — удел новичков, норм кодеры сразу пишут корректную работу с памятью»,

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

Это скорее не killer feature конкретного питона и Visual Studio, а убогость класс-ориентированного программирования

Не понял полета мысли от слова совсем

Ну я же написал сразу там: причина — практическая невозможность выполнять программу без оптимизации.

фишка интерпретируемых языков в том, что это можно сделать в люблм месте и без перекомпиляции проекта. А прост зашел на рабочую машину по ssh, в vim сделал пару правок, python module.py, и погнал

И в интерпретируемых тоже не всё так гладко — горячая перезагрузка в проде может завалить сервак, потому на самом деле это не «просто зашел на рабочую машину по ssh и в vim сделал пару правок».

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

Вообще-то там были какие-то поползновения заменить Си на Раст в ядре линукса

У нас есть ядерный код на C++, но сишка тотально доминирует.

смелые мыслью молодые засранцы в Хаскеле почему-то засунули хеш-таблицы в io

Хаскель убит в фундаменте совсем не из-за имутабельных структур, а из-за ленивости по умолчанию и безумной тяги к чистоте — которая на самом деле является эвфемизмом к «ничего не делать». Если программа что-то делает — она «грязная». И получили что получили.

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

common lisp одновременно:

компилируемый язык
имеет классы
можно заменять в любом месте и без перекомпиляции проекта и даже без python module.py
имеет лучшую поддержку тредов (хотя да, там откровенно недоделано)

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

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

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

Ты, как и все фанбои раста, Си, C++ глубоко и безнадежно застряли в идеологии программирования 80-х, когда любая операция выполняется условно атомарно, мгновенно, синхронно. То есть, сделал чтение из файла — оно сразу завершилось. Выделил память — она сразу выделилась. Взял блокировку в стэке, сделал мгновенную операцию, отпустил блокировку. Эта модель неактуальна уже лет 20, потому что программа просто-таки обязана делать еще десяток задач параллельно со «взял блокировку» и «прочитал файл».

В Rust есть примерно ноль инструментов для того, чтобы давать какие-то гарантии по лайфтауму того же связанного списка. Да, выше упомянули Rc<RefCell<_>> — но это СТЭК-ОРИЕНТИРОВАННАЯ структура данных: при доступе из многопоточного кода к структуре с подсчетом ссылок ты должен залочить родительскую структур, записать лок в стэк, увеличить счетчик ссылок, достать из стэка лок, разлочить его, вернуть значение с увеличенным счетчиком вызвавшему коду. Вызывающий код, если делает операцию над ячейкой со счетчиком, аналогично в стэке будет увеличивать счетчик под блокировкой, запоминать это в стэке, и уменьшать счетчик под блокировкой. Или брать единую блокировку на все операции. Всё это чудовищно неэффективно, потому во всяких JVM, CLR, Go, и прочих высокопроизводительных многопоточных системах не используется.

Вот и для кого все эти лайфтаймы вообще делались? Для какого кода, если с асинхронностью и многопоточностью у тебя почти всегда будет нарушение лайфтаймов, то есть unsafe. Если тебя не впечатлила многопоточность, то я могу вспомнить БД, которые вообще сделаны из одного сплошного небезопасного состояния. Или что-то железное, вроде тех же ОС, которые опять-таки нет смысла писать на Rust, потому что там всё один сплошной unsafe.

Вот прямо как в Haskell: идеальная модель программирования, но, к сожалению, на этой идеальной модели можно написать только бесполезный код. Код с прикладной ценностью обильно вываливается из идеальной модели в unsafe/impure/imperative, и модель становится уже не столько помощником, сколько обузой, через которую приходится перешагивать по двадцать раз в день. А потом говорить «да мне не тяжело, я не замечаю».

Только не надо думать, что я считаю, что в Rust нет ничего хорошего. Мне давно не хватает в C/C++ норм базовых структур данных и возможности их применить в тех же прототипах функций — эта штука почти годно была бы сделана в Rust, если бы среди разрабов Rust был хотя бы один человек, понимающий в оптимизации компиляторов, как это было при разработке Pascal. Но этот парад абсурда с борроу чекером и «безопасностью» — это контрпродуктивная наркомания, которая сделала Rust специализированным языком для написания браузеров, то есть, очень хорошо проработаны фичи, связанные с разработкой браузеров, и никак не проработаны отдельные фичи, не связанные с браузерами. Вроде скорости компиляции, побочных эффектов, глобального состояния, lock-free и персистентных структур данных ,и так далее.

Собственно раст от си отличается тем, что в C вся эта же информация описана в документации или комментах, и компилятор не следит за её актуальностью

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

Так что в этой области у него не хуже чем у других

Апелляция к «у C++ еще хуже». Потому что C/C++ — говно, а не ЯП. Потому корректно говорить «у Rust всё так же плохо, как у других» — то есть, он по прежнему застрял в 80-х, это не ЯП 21-го века, это просто ремейк C++.

В большинстве случаев чтоб программа на расте упала по панике её нужно об этом попросить. И подобные просьбы легко можно грепом отыскать

К сожалению, грепать и вычитывать тебе придется также стандартную либу, которая тоже весьма любит паниковать. Если я не ошибаюсь, есть даже встроенные в компилятор паники — вроде доступа к строке по индексу.

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

Предлагаемая выше в теме реализация списка через (A)rc - это, конечно такое себе. Но язык позволяет, грубо говоря, опуститься на уровень С. При этом принято «небезопасные» штуки заворачивать в безопасное апи. Да, unsafe реализация может содержать ошибки со всеми прелестями в виде UB

И это есть самая большая моя претензия к расту: разрабы попытались впихнуть невпихуемое, совместить несовместимое, дать гарантии там, где гарантий быть не может, сделать низкоуровневый язык высокоуровневым и высокоуровневый низкоуровневым. Получился сложный и медленно компилирующийся язык, а ради чего? Пока у тебя в коде хотя бы один unsafe — это не safe программа, это не «заворачивать в безопасное API», а «снижать число опасностей». Чувствуешь разницу? Немножко небезопасный, чуть-чуть мертвый, слегка беременный.

А снижать число уязвимостей и ошибок можно и в C++. Да, это сложнее, да, ведь в C++ много бессмысленных UB, которых не должно было быть изначально — именно это является настоящей причиной повышенной надежности программ на Rust, а не borrow checker. Borrow checker — это просто третья нога, но почему-то многие топят за то, что «с ней бегать быстрее».

А я напоминаю для тех, кто кроме C++ и Rust ничего не видел, что простота языка — это одно из самых важных качеств ЯП. Именно потому Rust — это низкопробный высер. Поэкспериментировали, посмеялись, закопали. Теперь сделайте норм ЯП,

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

Это норм, хотя конечно, хотелось бы безопасной реализации в безопасной обёртке

Аксиома массового IT: никому не нужна никакая безопасность. Всем нужна только различная степень опасности. То есть, если школьники ломают ваш сервис, то нужно что-то с этим делать. Если ломают только продвинутые хакеры — это пофигу, это норм, это просто надо бороться с хакерами (а не писать надежный софт). Или, вон, как Илон Маск — выдавать денежные компенсации за найденные уязвимости, чтобы потом рассказывать «вот, у меня уязвимостей нет, потому что всё, что смогли найти, я скупил». Хотя, если ты посмотришь, какие там страшные уязвимости когда-то были найдены, то никогда в жизни в теслу не сядешь.

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

и то чот я не вижу ОС на Rust.

Я на 90% уверен в их существовании. Если эмулятор x86 на Расте есть, то почему бы ОС не быть?

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

И потому настолько чудовищно тяжело для него написать компилятор-рантайм

Не настолько. Они уже существуют. Как минимум, 4 открытых реализации.

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

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

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

Хаскель убит в фундаменте

Так что им помешало сделать иммутабельные хеш-таблицы? Ведь иммутабельные структуры данных хороши, а хеш-таблица - это предмет первой необходимости.

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

Не настолько. Они уже существуют. Как минимум, 4 открытых реализации

Языку 65 лет.

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

Это решено для JVM и CLR, но это очень трудоемко. Закладывать крайне трудоемкую фичу в качестве базового требования к реализации — довольно глупая затея. Но почему-то лисперы продолжают талдычить про «лисп классный, потому что в нём есть REPL». Но REPL сейчас дофига где есть, аргумент некорректен, REPL не является никакой выдающейся фичей.

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

Так что им помешало сделать иммутабельные хеш-таблицы? Ведь иммутабельные структуры данных хороши, а хеш-таблица - это предмет первой необходимости

Хэш-таблицы — это мутабельный контейнер по своей природе. Имутабельны деревья. Я не знаю, какие там есть или нет реализации деревьев для хаскеля. но их точно можно сделать — в той же Clojure именно на персистентных деревьях сделаны ассоциативные массивы.

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

Вот ты так классно ругаешь С++ и Раст, но когда начинаешь ругать лисп, то слова против С++ и Раста как-то начинают сдуваться. Не нужно рассуждать о том, что ты не знаешь. Для лиспа, представь себе, это тоже решено. Возраст тут не релевантен и зря ты на него пытаешься переключить внимание. Если тебе это сложно, то это тебе сложно. Промышленности это не сложно, да и вообще не сложно. Через рассуждения о возрасте не получится опровергнуть преимущества горячей замены в лиспе. И привлекая соображения про REPL - тоже не получится. REPL и горячая замена - это разное. Т.е. вместо того, чтобы просто признать, что да, в лиспе это сделано лучше, или промолчать, ты несёшься куда-то не в ту степь ради спора.

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

Ну прекрасно, т.е. всё же совет делать всё иммутабельным почему-то таков, что ему не все следуют, даже среди относительно молодых засранцев. И даже ты в глаза не видел кода иммутабельных хеш-таблиц, знаешь только, что они есть. Значит, и ты не всё делаешь иммутабельным. Нечего тогда академичных старпёров лохматить.

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

Если тебе это сложно, то это тебе сложно. Промышленности это не сложно, да и вообще не сложно

«Промышленность» сказала, что сложно, перешла на питон, и больше не думает возвращаться. Даже в тех нишах, где нужна производительность параллельных вычислений — внезапно выясняется, что от многопоточности лиспа не так уж и много пользы, когда нет годных инструментов координации. У питона они есть, пусть и специфичные для каждой задачи.

REPL и горячая замена - это разное

Ты хочешь сказать, что заменять код в проде, а не только в отладочном стенде — это хорошая идея? А нынче, между прочим, хорошим тоном считается вообще не допускать разрабов к проду. Я не совсем согласен с этим, но я согласен с тем, что никакие отладочки и горячие замены за пять минут в проде категорически недопустимы. Даже если нужна горячая замена, то она должна хотя бы день тестироваться, прежде чем быть применена.

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

И даже ты в глаза не видел кода иммутабельных хеш-таблиц, знаешь только, что они есть

Никогда такого не говорил. Еще расскажи мне про имутабельные мутексы.

Значит, и ты не всё делаешь иммутабельным

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

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

Ты хочешь сказать, что заменять код в проде, а не только в отладочном стенде — это хорошая идея?

Нет. Я хотел сказать, что repl и горячая замена - это разное, и я это сказал. Хорошая идея заменять код в проде или плохая - это уже отдельный вопрос, но тут высказывалось мнение, что это нужно. Так вот, если это нужно, то лисп позволяет это сделать лучше, чем питон.

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

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

какая разница, сложно или нет, если это уже сделано. Ладно, я чем-нибудь другим лучше займусь, но не думай, что ты победил :)

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

Так вот, если это нужно, то лисп позволяет это сделать лучше, чем питон

Лучше чем? Лично у меня претензии к питону по поводу того, что в нем слишком много вещей можно поменять в рантайме.

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

Ты, как и все фанбои раста, Си, C++ глубоко и безнадежно застряли в идеологии программирования 80-х, когда любая операция выполняется условно атомарно, мгновенно, синхронно.

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

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

Да-да-да. Сраного никому не нужного связанного списка, за использование которых джунов надо на горох ставить. Но внезапно, когда выяснилось что на Раст такое пишется сложнее чем на С он вдруг сразу понадобился.

Да, выше упомянули Rc<RefCell<_>> — но это СТЭК-ОРИЕНТИРОВАННАЯ структура данных: при доступе из многопоточного кода к структуре с подсчетом ссылок ты должен залочить родительскую структур, записать лок в стэк, увеличить счетчик ссылок, достать из стэка лок, разлочить его, вернуть значение с увеличенным счетчиком вызвавшему коду.

Нет, ничего этого ты делать не должен. Потому что в твоей многопоточной программе весь этот список будет всегда жить в одном потоке. Более того, если ты его наколхозил в том виде, в котором описал, через Rc<RefCell<_>>, то ты его не то что из разных потоков дёргать не сможешь, ты его в принципе даже не передашь в другой поток, Rc - не реализует Send. Так что не ссы, спокойно пользуйся своим двусвязным списком, ничего лочить не надо. Раст позаботился о тебе.

Вот и для кого все эти лайфтаймы вообще делались? Для какого кода, если с асинхронностью и многопоточностью у тебя почти всегда будет нарушение лайфтаймов, то есть unsafe.

Я не понимаю твоей логики. Вот ты пишешь, что асинхронность и многопоточность - это сложно. Пишешь в теме про язык, который специально рекламируется как язык, решающий эту проблему. Пишешь явно ничего не понимая в том, как авторы языка предлагают проблему решать. Но вместо того чтоб поинтересоваться, какие для этого придуманы абстракции, посмотреть идиоматические примеры кода, предлагаешь обернуть всю программу в unsafe блок и гонять данные между потоками через raw-pointer’ы, чтоб borrow checker не ругался. Тебе не кажется, что проблема не в расте, а в тебе?

И в Rust тебе придется большую часть этой информации описывать в комментах и документации.

Не знаю… В моё время говорили что комментарии в стиле a = b; // присваеваем a значение b - это плохие комментарии и писать их не надо. Если язык предоставляет возможность описать лайфтаймы и владение, дублировать эту информацию как-то глупо.

Апелляция к «у C++ еще хуже». Потому что C/C++ — говно, а не ЯП. Потому корректно говорить «у Rust всё так же плохо, как у других» — то есть, он по прежнему застрял в 80-х, это не ЯП 21-го века, это просто ремейк C++.

Для раста достаточно и «у C++ еще хуже», всё-таки ниша та же. Но описанные проблемы характерны не только C++. Где вот к примеру многопоточка сделана на уровне раста? Ну, может где-то и сделана, но явно не в Java/.net/Python и прочие активно использующиеся языки.

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

Ты, как и все фанбои раста, Си, C++ глубоко и безнадежно застряли в идеологии программирования 80-х, когда любая операция выполняется условно атомарно, мгновенно, синхронно.

Чё ты несёшь вообще? Ты так-то критикуешь язык, в котором компилятор следит, чтоб к объектам из других потоков не обращались, в котором ради вот этого напрягают программистов, заставляя использовать 2 разных реализации счётчиков ссылок

Да-да, ты всё правильно понял, и продолжаешь мне рассказывать про божественные приемы программирования на i386, что я на самом деле не шарю и лучше не умею. Тем временем шла середина 2022.

Весь смысл этого порно со счетчиками заключается в том, чтобы выжать последние копейки производительности из процессора, например, чтобы не применять GC — хотя GC бывает быстрее подсчета ссылок. Выжать из того процессора, который в лучшем случае использует одну сотую возможностей транзисторов на кристалле. Это примерно как рассказы про 30% прироста производительности в интерпретаторе питона за 5 лет разработки — плюс-минус ничего, короче говоря.

Высокую производительность на классическом процессоре невозможно совместить с безупречной надежностью. Можно получить меньше багов, но ты не получишь безупречной надежности. Даже если каким-то чудом ты сможешь устранить совершенно все баги — выяснится, что в процессоре есть дефекты, которые проявляются спустя недели-месяцы работы под нагрузкой. Или в оперативу прилетит излучение и переключит бит. Потому классическая модель машины Тьюринга имеет неисправимый дефект.

Rust не пытается встать над этой моделью, не пытается предложить абстракции, которые хотя бы как-то нивелировали неудобства и ненадежность машины Тьюринга. Но при этом он не пытается использовать ЦП на полную с помощью «lock-free» программирования, то есть аппаратных блокировок. Lock-free алгоритмы подразумевают ОДНОВРЕМЕННЫЙ ДОСТУП НА ЗАПИСЬ. Тот самый, избежать который так отчаянно пытались разрабы языка. И тот самый, для которого даже в полуобщих-полуспециальных формах не получается давать гарантии по поводу свойств, по причине запредельного экспоненциального роста сложности параллельных асинхронных алгоритмов.

Borrow checker — это в том числе оптимизация для избежания подсчета ссылок вообще, например, чтобы не брать счетчик для итерации по строке, а чтобы просто итерировать по этой строке минимумом инструкций. Кому нужно так жестко заморачиваться, если проблема №1 во всей индустрии сейчас — это «процессоры слишком мощные и нам нечем их загрузить». В том числе из-за этого пишут на чудовищно неэффективных инструментах — иначе железо будет простаивать без дела.

Из раста получилась ни рыба, ни мясо, бегство от низкоуровневости и ненадежности, где лежат все оптимизации, но всегда ценой ненадежности, в сторону высокоуровневости, которой в Rust на самом деле нет и на каждый шаг ЯП будет запутывать твои ноги в трясине из вспомогательных конструкций, без которых он не скомпилирует твою программу. Это те самые две лодки, на которых безуспешно пытался устоять C++, который, как метко выразился Йося Крейнин, одинаково плохо поддерживает все парадигмы. Есть ЯП, которые хороши в своей одной нише, но C++ в ней хуже, зато C++ хуже в большем числе ниш, и потому так популярен в индустрии — вот так мыслят манагеры, не спрашивайте почему. Наверное, потому что всю жизнь продают вечные двигатели и телепорты, сегодня продал — завтра купил. Все эти патологические наклонности один в один скопировал Rust, привнеся лишь немного сахарку и устраняя UB, которых не должно было быть в самом C++ изначально, если бы его создатель разбирался в программировании, а не в мастерстве выслуживания перед руководством.

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

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

Rc<RefCell<_>>, то ты его не то что из разных потоков дёргать не сможешь

Сорян, я не в курсе. какие там из счетчиков потокобезопасные, а какие — нет, я написал про то, про что написал, независимо от ЯП.

Так что не ссы, спокойно пользуйся своим двусвязным списком, ничего лочить не надо. Раст позаботился о тебе

Ага, нет потоков — нет проблем. Очень удобно жить в 80-х годах.

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

Он может рекламироваться как лекарство от рака, но по факту этой проблемы не решает. Rust — это специализированное средство разработки браузера, который по большей части крутит логику в одном потоке, но также имеет нескольких вспомогательных, которые очень редко пересекаются с главным. Именно под эту модель спроектированы Sync/Send, mut и оптимизация через ссылки на разделяемые данные, borrow checker. Эта модель эдак 80-х годов/начала 90-х (если я еще не писал об этом). Проблема такой модели заключается в том, что у тебя производительность и время отклика полностью определяется главным потоком, он является конечным ресурсом, при исчерпании которого ты просто ничего не можешь дальше развивать. C++ позволял дольше всех игнорировать фундаментальный изъян этой модели — именно поэтому C++ победил в разработке GUI, именно потому его попытались повторить в Rust. Именно потому для Rust-а так важна производительность, он никак не может стать высокоуровневым языком — высокоуровневые алгоритмы слишком быстро исчерпают ресурс главного потока. Но это «решение» — на самом деле рак, который убивает разработку, и Rust этот рак не лечит, а лишь удлиняет страдания. А чтобы разработать иную модель, нужно спускаться на уровень сишки, и терять все гарантии Rust.

Но вместо того чтоб поинтересоваться, какие для этого придуманы абстракции, посмотреть идиоматические примеры кода, предлагаешь обернуть всю программу в unsafe блок и гонять данные между потоками через raw-pointer’ы, чтоб borrow checker не ругался. Тебе не кажется, что проблема не в расте, а в тебе?

Не кажется. Я достаточно давно и много пишу многопоток, чтобы знать, что никаких универсальных абстракций для ЦП Тьюринга нет и быть не может. Оно небезопасное и всё тут. Ты либо дольше разрабатываешь, либо теряешь производительность, либо теряешь надежность — что-то произойдет. Я сам недавно на LOR-е писал, что наклевывается что-то такое, но по итогу я не вижу никакого света в конце тонеля — слишком высока комбинаторная сложность. Можно давать какие-то гарантии только после ведения абстракций/ограничений, но тут ты сразу теряешь производительность.

Забавно, что низкоуровневые конструкции современных ЦП сами являются причиной неэффективного использования энергии и транзисторов — внутри процессор работает совершенно по-другому.

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

Я уже раза два писал, что лайфтаймы и владение — это едва ли половина всех проблем низкоуровневого кодинга. А в высокий уровень Rust не умеет.

Где вот к примеру многопоточка сделана на уровне раста?

Многопоточка Clojure — космос по сравнению с растом. та вопрос лишь в производительности, на которую поменяли эти абстракции — GUI в классическом однопоточном стиле на таком не напишешь. С другой стороны, я сам PSO разрабатывал, имея следующим шагом идею разработки для питона GUI через разделяемые объекты, которое позволило бы игнорировать всю тормознутость ЯП. К сожалению, я не осознавал, насколько это длинный путь, проходить который ни у кого нет мотивации.

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

Кому нужно так жестко заморачиваться, если проблема №1 во всей индустрии сейчас — это «процессоры слишком мощные и нам нечем их загрузить». В том числе из-за этого пишут на чудовищно неэффективных инструментах — иначе железо будет простаивать без дела.

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

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

Даже если каким-то чудом ты сможешь устранить совершенно все баги — выяснится, что в процессоре есть дефекты, которые проявляются спустя недели-месяцы работы под нагрузкой. Или в оперативу прилетит излучение и переключит бит. Потому классическая модель машины Тьюринга имеет неисправимый дефект.

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

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

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

вам уже неоднократно говорили

Да тут весь тред достоен музейной выставки. Пассажи про cachelines / L1 / i386 / lock-free чего стоят. Такое ощущение что товарищ на каких-то веществах и его «прёт». Лично я уже затарился попкорном и уселся в первом ряду ;)

bugfixer ★★★★
()
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)