Pull to refresh

Comments 187

Как то не о чем. А где примеры? Например, в С++ это будет так, а в Rust так. В С++ это гарантировано упадет, а в Rust нет. А получился какой-то краткий и непонятный обзор с рекламой себя любимого в конце.
Для этого будет отдельная статья (полноценное сравнение с С++). Данная же статья своей целью ставит вызвать интерес и мотивацию к ознакомлению.
Тогда уж и с Хаскелем сравните, пожалуйста.
Нет смысла сравнивать Rust с Хаскелем, потому что это совершенно разные языки. Rust вдохновлялся идеями из Haskell, например, трейты очень похожи на многопараметрические классы типов (пока это их сильно урезанная версия, но в будущем это может быть исправлено), а внутри функций действует вывод типов по Хиндли-Милнеру, но в целом Rust гораздо ближе к императивным языкам. И это естественно, потому что системный функциональный язык сделать очень трудно, и даже если такое сделать, получится что-то, неудобоваримое для использования.
Важная вещь, которая приближает Rust к функциональным языкам — описать мутабельную переменную сложнее, чем иммутабельную.
Я думаю, что это заметно повлияет на стиль.
Мутабельная переменная, это переменная переменная, или, если хотите, масло масляное.
Вот иммутабельная переменная (непеременная переменная) — это нонсенс.
Может не стоит называть то что нельзя изменить словом переменная?

По русски будет: описать переменную в Русте сложнее чем константу на 4 символа " mut".
На C++ часто ленятся писать const. На Rust будут программировать не менее ленивые ;-).
Плохой код можно написать на любом языке. Но иметь возможность написать const лучше, чем не иметь такой возможности.
Еще лучше иметь возможность написать mut, а const был бы по умолчанию.
В этой жизни я не могу понять двух вещей: 1) почему пишут Руст, а не Раст; 2) почему пишут Раби, а не Руби.
Наверно дело в том, что когда россиянин читает слово RUS в овале, на своём автомобиле, он его читает как Рус. А для американцев это начало слово Раша, они читают через а. Так уж сложилось. А Rust от Rus отличается одной буквой.
Главная причина конечно в том, что я не слышал этого слова от других, а также не знал вот этого простейшего правила www.alleng.ru/mybook/2read/U.htm
Это прям хабромем «для этого будет отдельная статья». А эта статья для чего? Что я мог из нее узнать? Вы не раскрыли заголовок, я не понял, зачем мне нужен Rust. Пишите, пожалуйста, содержательные статьи.
«Ваша принцесса в другом замке»

Серьёзно, Вы ожидали увидеть другую статью. Как и WerewolfPrankster, Вам нужно полноценное доказательство , что Rust лучше С++ (а также D, Go, и чего бы то ни было ещё). Моя статья же носит исключительно показательный характер, при этом я попытался показать Rust как скрещение С++ с Haskell, что есть сугубо личный взгяд на происхождение языка.

Если Вас не убедило даже заглянуть на домашнюю страничку языка — это бывает. Но вот утверждение, что статья несодержательная, вызывает у меня недоумение. Вы просто искали другое содержимое.
Не слушайте их, статья хорошая и нужная. Для тех, кто только название языка слышал, и не в курсе, зачем оно вообще надо. Такие общие введения, описывающие идеи и причины всей движухи, очень порой помогают загореться и поизучать тему поближе.
Вы видимо мало программировали на С++, потому что в мире С++ как правило не верят в красивые слова, а верят только работающему примеру, и то только в том случае если пример достойный.
Я работаю с С++ по профессии уже как минимум 7 лет, но таким суровым ещё не стал. Видимо, нужно программировать ещё больше, не отвлекаясь на другие языки в свободное время ;)

А если серьёзно, то постараюсь сравнить подробнее и с примерами в следующей статье, раз уж ввязался (на свою голову)… Жаль только, с С++ 11 опыта у меня нет, так что сравнение может получиться нечестным.
в таком варианте я эти два слова еще ни разу не видел, «кокраз» — это подарок! :)
Тут скорей то что на C++ может «упасть» на Rust просто не скомпилируется.
Хорошо же на Хабре работает саморегуляция! Зачем пыхтеть, думать, писать материал, получив +51 к посту, если можно вот так зайти, написать первым «статья не о чём» (не удосужившись понять, о чём она) и получить +42. А Ваши статьи о чём?
Не могу понять причину вашего возмущения. «Плюсики» за комментарии ничего не дают кроме плюсиков. Разве что кроме какой-то мизерной доли рейтинга. Я с удовольствием прочитаю вашу следующую статью с подробностями об этом языке. И да я узнал о новом языке из этой статьи, за что я вам благодарен. А написал, что статья «не о чем» потому, что она так и не ответила на свое название «Зачем нам нужен Rust?» а содержит лишь базовую информацию и маркетинговые высказывания в стиле «в 5 раз безопаснее» и в «10 раз быстрее». Почти тоже самое я мог прочесть и на википедии.
Я рад, что мне удалось привлечь Ваше внимание к языку. Это и было целью статьи. О чём она? О том, какое место Rust занимает в ряду существующих языков, чем может похвастаться, чем уникален (собственно, "зачем"), какие проблемы ожидают новичков, плюс некоторая общая информация о языке и сообществе. Вопрос, на который она не отвечает, так это "как": как Rust удаётся гарантировать безопасность, при этом не теряя скорости (а где-то и прибавляя — это отдельная история).

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

Напоследок, про «рекламу себя любимого». Было бы крайне неубедительно призывать кого-то изучать Rust, вливаться в сообщество, да при этом самому оставаться в стороне.
А в чём его отличие от D, можете рассказать? Ведь D тоже планировался, по сути, «убицей C++», который подходит как для системного, так и для «обыденного» программирования.
Rust более низкоуровневый и гибкий и не позиционирует себя как «правильный C++», в отличие от D. Философия языков очень различается, как и наборы предоставляемых инструментов. D в этом плане очень похож на C++; в Rust абстракции, с которыми приходится работать, другие.
Rust более низкоуровневый и гибкий

Можно поподробней, пожалуйста. Пока кроме управления памятью я не вижу преимуществ Rust по сравнению с D.
Я, наверное, не совсем правильно выразился насчёт гибкости. Вполне возможно, что D за счёт своих шаблонов и миксинов уделает Rust по гибкости в применении (хотя в Rust есть макросы, подстановочные и процедурные), но в плане разработки самого языка Rust менялся очень сильно, и всё время происходил поиск каких-то новых путей и реализаций различных штук. За счёт этого Rust гораздо быстрее и эффективнее развивается. Под гибкостью я имел в виду это. Например, Rust стал вторым по активности проектом на Github за 2013 год, причём первым был Homebrew, в котором активность заключается не в правке кода, а в выкладывании новых описаний пакетов. Когда я писал на D, у меня сложилось совершенно противоположное впечатление о развитии языка.

А насчёт низкоуровневости — всё достаточно просто. Rust изначально разрабатывался как язык для системного программирования. Например, в D хоть и можно отключить сборщик мусора, но вся стандартная библиотека сразу станет неюзабельной. В Rust сборщик мусора не нужен в принципе, в том числе для стандартных библиотек. Также как только вы отказываетесь от сборки мусора в D, вы мгновенно получаете небезопасность C. Аналогов статического анализа, который проводит Rust для обеспечения правильной работы с ресурсами, сейчас, фактически, нет (за исключением совсем маргинальных языков вроде ATS или Cyclone).

Я писал на D довольно давно (года два назад) и уже прилично подзабыл, как там что, поэтому я не могу сравнить его с Rust полноценно. В целом мне D понравился, но Rust оставляет ощущение гораздо более практичного языка, ИМХО.
А что именно писали на D? Что-то для себя или коммерческое?
Тогда уж надо вспомнить и язык Go
Rust и Go занимают одну и ту же нишу, но отличаются парой ключевых деталей:

— в Go всем правит garbage collector, в Rust GC есть, но основная часть переменных управляется RAII,

— в Rust есть generic программирование, а в Go нет.
Для меня Rust и Go в разных лигах. Go хорош там, где раньше я бы воспользовался С или C++, для написания небольших утилит, но которые должны быстро выполняться, для веб-сервисов, БД и так далее. В общем на Go я бы с удовольствием писал такие проекты как Redis, MongoDB, или утилиты как scp, grep. Go это простой язык, в том плане что синтаксис очень простой, чтобы понимать код, не нужно знать контект. Go — императивный язык, shared memory model.
Rust же — это именно попытка скрестить C++ и Haskel. Это функциональный язык в первую очередь, вместо shared memory тут новая модель, где компилятор знает кто владеет памятью и контролирует доступ. Это очень очень интересная идея, надеюсь у них все получится. На Rust мне было бы интересно писать бизнес-логику, или machine learning системы.
Также Go — это уже взрослый язык, на горизонте версия 1.3, язык стабильный, в том плане что гарантирована компиляция ваших программ для всех 1.х версий языка. Go используют в продакшене давно и успешно. Есть куча библиотек для всего на свете и т.п.
Rust пока не достиг этого состояния. Это не плохо, это дает ему преимущество, потому что он все еще может кардинально улучшаться. Но для продакшена его использовать еще страшно. Mozilla например недавно представила Heka github.com/mozilla-services/heka — написан на Go, Rust они рассматривали в качестве кандидата, но отказались именно по причине его нестабильности (т.е. бурного развития)
UFO just landed and posted this here
ну вот абсолютно без контекта можно понять что происходит
Комментарии
// VarRefs() - это функция, определенная для ссылки на запрос (*Query) и возвращает массив ссылок ([]*VarRef)
func (q *Query) VarRefs() []*VarRef {
    // если массив q.refs еще не вычислялся
    if q.refs == nil {
    	// присваеваем пустой массив
        q.refs = []*VarRef{}
        // для каждого statement s из массива q.statements
        for _, s := range q.statements {
            // добавляем сссылки из s.VarRefs() в массив q.refs
            q.refs = append(q.refs, s.VarRefs()...)
        }
    }
    return q.refs
}


понятное дело что нужно знать синтаксис языка, но синтаксис Go простой, его изучить можно за 2 часа, и он очень близок к C
Именно по причине его нестабильность про Rust трудно пока сказать что-то определённое. Но по всему видно, что он претендует на то чтобы стать полной заменой C++. В нём есть всё то что составляет основную силу C++: управление памятью без GC, generic программирование. При этом и то, и другое сделано гораздо более безопасно.

Хотелось бы надеяться, что язык стабилизиуется, а то за неделю-две, что я с ним знаком, там успел переименоваться тип, которым представляются строки, и квдратные скобки в данный момент не работают для индексации векторов.
Справедливости ради стоит отметить, что большая часть кода, который оперирует с массивами, использует разрезы (slice), для которых индексация работает и всегда работала. Только непосредственные владельцы векторов (Vec) вынуждены столкнуться с временным неудобством индексирования. А со всем остальным согласен ;)
Прошу прощения за придирки к терминологии, но slice — это срез, а не разрез :) например, в Python тоже есть slice'ы, и их в русском называют срезами.
Спасибо, а то я русскую литературу по вопросу не изучал. По крайней мере корень «рез» угадал ;)
Rust нужно сравнивать прежде всего с Go, как мне кажется. Собственно и родился он при аналогичных обстоятельствах и роли у них похожие и владельцы являются оппонентами по многим вопросам. Ни разу в статье Go не упоминается, как так? И все-таки хотелось бы от первой статьи больше конкретики / сравнений / юзкейсов, информации про существующие IDE / package manager'ы и прочее.
Не очень корректно сравнивать Rust с Go. Go никогда не представлялся как язык для системного программирования и он не может им быть — в Go неотключаемый GC, от которого очень многое зависит. В Rust с этой точки зрения упор именно на безопасное управление памятью без оверхеда от GC и прочих автоматических систем (но если сборщик мусора очень нужен, всегда можно взять его из библиотеки). Rust — это именно язык для системного программирования, замена C/C++. Go же позиционировался как такая быстрая компилируемая статическая замена языкам вроде Python/Ruby, т.е. в основном для веб-программирования.
Именно. Библиотек пока ещё нет, но это, на самом деле, дело будущего — ведь даже сам язык пока не очень стабилен.
Некто пост. Я просто хотел вам сказать, что вы не правильно прочитали комментарий. Про вэб говорится в контексте Go.

RoR тоже не с day one доступен стал.
Вы откуда-то непонятно откуда берёте информацию. По ссылкам, приведённым вами, не написано, что Go — это системный язык и замена C++. Наоборот, он представляется там как типобезопасный статический язык, на котором так же легко писать, как на динамических языках. И это на самом деле так.

Кроме того, полноценным язык с неотключаемой (не в принципе, а на практике — когда отключение GC бессмысленно) сборкой мусора в принципе не может быть системным настолько же, насколько системными являются C/C++.
golang.org/doc/faq#creating_a_new_language

Go was born out of frustration with existing languages and environments for systems programming
Ок, эту фразу я почему-то пропустил. Но, во-первых, больше там про это ничего нет, а во-вторых, даже если и так, и авторов Go на самом деле сподвигли на подвиги проблемы C/C++, то в любом случае Go не может быть полноценным системным языком, как C/C++.
добавьте к своему посту IMHO тогда он будет более корректен.
Уже нельзя редактировать комментарий. Но то, что Go не может быть полноценным системным языком (как C/C++) — это вполне объективный факт. Вы не сможете его использовать везде, где вы можете использовать C. Go тянет за собой рантайм (не уверен, можно ли его отключить, но даже если и можно, то все ключевые возможности Go, включая горутины, потеряются), что совершенно неприемлемо в embedded. Про сборку мусора я уже писал. Добавлю ещё про невозможность нормального преобразования указателей, только через unsafe.Pointer с жутким синтаксисом. В области применения, на которую рассчитан Go, это совершенно не страшно; в области, где царствует C — это, наоборот, очень важно.
Если бы GC имел бы аппаратную поддержку (что позволило бы его сделать не консервативным и не блокирующимся), то он бы мог использоваться и в системном программировании. Intel iMAX 432 это было реализовано. В каком-то виде и в Эльбрус-[12].
Программирую на Go. Сравнивать с Rust большого смысла нет, они не конкуренты друг другу. Go программист никогда не перейдёт на Rust и наоборот.
Rust сугубо для системного программирования, в то время как Go хм для программистов. Он крайне удобен в написании и его можно применять в очень многих сферах, но вот именно там, где предпологается использовать Rust, у Rust и будет приемущество. Работа с памятью сильно отличается.
Rust сугубо для системного программирования, в то время как Go хм для программистов.

Это весьма спорное утверждение. Вы считаете Skylight и ZeroMQ системным программированием? Насколько я вижу, единственное, что мешает Rust потеснить Go в его областях — это существующие библиотеки. В частности, это web-разработка, где прогресс отличный, но до финала ещё далеко (AreWeWebYet).
А я так полагаю, что никакого потеснения не будет. Go проектировался для решения задач Google, то есть масштабируемые сетевые сервисы, а Rust для решения задач Mozilla, то есть кроссплатформенный графический клиент. Go имеет шаблон сервера, и не только HTTP, в стандартной библиотеке над которой работают оплачиваемые высококлассные программисты Google, но ло сих пор не имеет достойной, признанной сообществом GUI библиотеки. Rust же, напротив, не имеет в репозитариях не то что web framework, но даже приглядного HTTP сервера. Более того с последним релизом Rust перешел на OS threads, против собственных легковесных green threads по умолчанию, что делает серверное программирование затруднительней. Таким образом, на мой взгляд, сферы уже поделены — Go на сервере и Rust на клиенте. Поправьте если ошибаюсь, Go я знаю хорошо, а с Rust знаком поверхностно именно в силу сферы интересов лежащей в области серверных технологий.
Rust не остановится на клиенте. Да, на сегодняшний день Go обладает значительно более сильной инфраструктурой для серверной части.

Однако, допустим, на Rust вырастет неплохой http-server (teepee). У разработчиков появится возможность использовать Rust везде — и на сервере, и на клиенте, даже в Javascript. Зачем тогда компаниям будет нанимать разных специалистов на Go и Rust, держать изолированные кодовые базы, если можно всё писать на Rust, используя общие куски кода и там, и сям?
Более того с последним релизом Rust перешел на OS threads, против собственных легковесных green threads по умолчанию, что делает серверное программирование затруднительней.

Легковесные потоки никуда не делись, они включаются одной строчкой. Неужели это так затруднительно? :)
Разумеется подконфигурировать легковесные потоки не ракетостроение, но использование системных потоков по умолчанию маякует нам о целях и задачах команды разработчиков языка направленных скорее в сторону скажем игр нежели серверов.
Разработчики языка просто хотят, чтобы конфигурация по-умолчанию была как можно проще, и поведение было предсказуемее. При этом переключить её в режим лёгких потоков не составляет труда, не требует переписывания потокового кода. О чём это маякует? О том, что разработчики молодцы и учитывают все требования сообщества.
я перешёл на Rust, оставив позади Boo, Dart, Haskell

весело люди живут
А мне и с C++ и Erlang (для некоторых задач) неплохо
Менять языки как перчатки не так уж и сложно. Особенно, если на среду разработки не завязан.
И действительно весело получается ;-).
UFO just landed and posted this here
Спасибо за статью, очень здорово видеть русскоязычных людей в коммьюнити Rust :)
С другой стороны есть Haskell, этакий язык-крепость (по принципу «раз оно компилируется, значит работает»), хоть и не могущий похвастаться скоростью.

Это не так, Haskell очень даже может похвастаться скоростью. Здесь Haskell стабильно держит места вплоть за Java и C/C++. Кстати, Java — это как раз один из наиболее быстрых языков.
Однако Rust и в самом деле стремится занять нишу C/C++, и, как мне кажется, когда он станет стабильным, у него есть все шансы это сделать.
Я бы с удовольствием почитал сравнение C++ и Rust по критериям надёжности и скорости разработки.
Новые языки это интересно, круто, возможно даже удобно, но среди них пока нет кандидата на роль «убийцы C++». Дело тут не в том что они кому-то не нравятся… Просто для них нет такого количества крупных проектов с большим числом участников, библиотек и программных каркасов, сред разработки, учебной литературы и т.д. Когда на Rust (D) будет написан проект уровня сложности и востребованности, допустим KDE или набор библиотек вроде boost, а на рынке труда появится хотя бы 10 вакансий для программистов, можно будет говорить что это хороший и полезный язык для промышленной разработки приложений. Только пока будут развиваться новые языки, будет развиваться C++ со всей инфраструктурой, который, на мой взгляд становится все удобнее с каждым новым стандартом.
Так что пока Rust и прочее это возможно круто и интересно, но не более того. Полагаю, что ситуация не сильно изменится, и скажем к 2020 году. Разве что ворвётся какая-нибудь новая технология и привычные компьютеры и программирование канут в лету)
Язык пока ещё в состоянии бета-версии, он не готов для промышленного использования. Сам язык и библиотека очень сильно меняются. Например, в ближайшем будущем будет как минимум два очень серьёзных изменения — типы с динамическим размером и unboxed-замыкания. Поэтому пока что преждевременно говорить о «проектах уровня сложности KDE». И даже несмотря на это один проект похожего уровня сложности уже давно в разработке — это Servo. Да и сам компилятор Rust простым не назовёшь.
Про то что Rust пока не стабилен понятно. Но даже стабильный релиз не исправит положения, я думаю. Почему написал выше.
Про новые фичи тоже много вопросов… Нужны тесты производительности, оценки востребованности, возможности поддержки кода (и стоимости его поддержки). Так что мало просто внедрить что-то новое, нужно еще и сделать так, чтобы люди начали этим пользоваться. Проще повторить все лучшее что уже есть или было.
Одной только сложности проектов мало. Нужна востребованность, комьюнити, которое будет их развивать и т.д.
Нужны тесты производительности

pcwalton.github.io/blog/2013/04/18/performance-of-sequential-rust-programs/
Были и другие, сейчас затрудняюсь найти…

оценки востребованности

Mozilla делает его для себя. Они считают, что если язык позволит создать Servo, то он годен и для других задач сообщества.

возможности поддержки кода (и стоимости его поддержки)

Цифры какие-то наверняка есть, ведь Servo не вчера появился. Будет интересно взглянуть на них, когда разработчики сделают post-mortem.

Проще повторить все лучшее что уже есть или было.

Тут не поспоришь. Проще вообще ничего нового не придумывать.

Нужна востребованность, комьюнити, которое будет их развивать и т.д.

На этот счёт я спокоен, ибо сообщество у Rust завидное ;)
Тут не поспоришь. Проще вообще ничего нового не придумывать.

Я имел ввиду, что на популярность языка окажет влияние наличие уже реализованных в других языках, привычных программисту концепций. Например, есть аналог range-based for, замыканий, автовывода типов и т.д… Хорошо, это всем знакомые вещи, а как уж они выглядят — не важно. Важно то что они работают так как предполагает программист.
А так-то я только за новые фичи и с интересом наблюдаю за развитием Rust и прочих относительно новых языков.
Понятно. Кажется, мы пришли к банальному обсуждению революционного развития против эволюционного. Rust не вызывал бы такую бурю эмоций (смотрите соотношение up/down в посте и комментариях), если бы не предлагал чего-то координально нового (безопасность + низкоуровневость) ;)
Она уже ворвалась. Все нынешние компьютеры, смартфоны и т.д. — МНОГОПРОЦЕССОРНЫЕ. Поэтому для них надо писать параллельные приложения. Очень многие авторитетные люди ожидают, что в скором времени число вычислительных ядер в домашних ПК превысит число выполняемых процессов. Та же AMD это активно приближает.
Немного не уловил мысль… Что, на современных ЯП нельзя писать параллельные приложения? Можно и уже довольно давно. Ну а вычислительных ядер много не бывает.
Одно дело C или Java, а другое — D и Golang, создаваемые изначально с прицелом на параллельность.
На Asm'е тоже можно всё что угодно написать. При чем изначально можно было. Но почему-то он непопулярен…
В основном с внимательностью у людей проблемы, а этот язык очень чувствителен к внимательности программиста.
Asm чересчур низкоуровневый язык. Писать на нем сложные приложения долго, тяжело и, как следствие этого, дорого.

Любой язык требует внимательности… А тот язык, который прощает невнимательность программисту, объективно не пригоден для серьезной разработки.
Не прощает, а выносит уровень внимания на следующий уровень. Ведь теперь уже не надо думать как работает конвеер процессора, не надо следить за порядком и вложенностью команд PUSH/POP которые могут легко порушить всю систему и т.д.
Модель параллельного программирования с общей памятью сложна и порождает труднонаходимые ошибки.
Слишком много вычислительных ядер тоже порождает проблемы. Я не уверен, что алгоритм планирования, который не дает в Erlang переполняться очередям сообщений, будет работать, если ядер больше, чем активных процессов. Конечно, на десктопе можно «майнить биткоины», но для мобильных приложений это неприменимо, надо искать другие подходы.
boost появился в основном что бы компенсировать кривости в дизайне C++. В Rust он не особо нужен.
Вы еще скажите, что стандартная библиотека в питоне появилась, чтобы компенсировать кривость питона. Boost — это хорошая библиотека для хорошего языка.
спасибо за интересный обзор. я очень далек от компилируемых языков, но все равно хотелось бы подробностей. буду ждать обещаную выше статью.
UFO just landed and posted this here
Rust отличается от D и Go.

От D он отличается гораздо более активным коммьюнити и большей гибкостью в разработке. Rust даже 1 год назад очень сильно отличался от сегодняшнего; Rust 2 года назад — это совершенно другой язык. Авторы языка с помощью сообщества постоянно экспериментируют и пытаются выделить лучшие способы реализации того или иного функционала. Кроме того, он не ставит своей целью быть похожим на C++ — в нём другие инструменты для абстракции, чем в D и C++.

Go же вообще никогда и не собирался быть «убийцей» C/C++. У него совершенно другая область применения, гораздо более близкая к Python/Ruby. Его в принципе нельзя рассматривать как язык для системного программирования, у него для просто нет нужных фич.

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

Тем не менее, есть очень много тех, кому важна безопасность, но нет возможности использовать что-то более высокоуровневое, чем C/C++. А важность безопасности на самом низком уровне переоценить нельзя — вспомните недавний Heartbleed. В Rust подобные вещи невозможны просто в силу устройства языка и его системы типов/borrow checker'а.
UFO just landed and posted this here
Согласен с вами, но сейчас коммерческая разработка тоже разная бывает. Есть олдскульный корпоративный сегмент — там то что вы перечислили + вполне еще живые реликты вроде Delphi, Lotus и даже FoxPro.
И есть новые проекты, тоже коммерческие, но уже создающиеся с разумной экономией средств в сжатые сроки в соответствии с концепцией MVP. Там инструментарий гораздо шире, разработчикам позволено экспериментировать.
Все так, но необязательно, чтобы это было все сразу для развития, взгляните на Scala она щас активно отъедает определенный сегмент java рынка но вот «обилия большого числа дешевых и качественных программистов» там нет, нечто похожее было и с Objective-C там по сути главной движущей силой стал быстроразвивающийся рынок. У Mozilla есть шанс обеспечить инфраструктуру качественными библиотеками для самых популярных сегменов и предоставить некоторые индустриальные гарантии и привлечь большое количество разработчиков (что уже по сути получилось т.к уже есть излишняя популярность которая по идее не свойственна языку в предрелизном состояннии).
UFO just landed and posted this here
да конечно, но она активно двигается в этом направлении, очень много на нее проектов переводится — хотя врятли конечно скоро она за этот барьер перешагнет — скорее всего будет занимать нишу некого hi-end в мире JVM
Вы понимаете, что
— стабильности проверенной годами
— обилии КАЧЕСТВЕННЫХ библиотек, вылизываемых годами
— обилии большого числа дешевых и качественных программистов

от языка, который в открытой разработке только три года, все эти три года очень сильно менялся и до сих пор ещё нестабилен, ожидать прямо сейчас как-то странно?

Кстати, Go вполне себе успешный язык и свою нишу потихоньку наращивает. И сложные проекты вроде Docker там уже есть.
UFO just landed and posted this here
Ни один из языков, успешных в вашем понимании, не развивался всего лишь три года и не стал успешным в статусе бета-версии. Повторюсь ещё раз, от Rust этого прямо сейчас ожидать очень странно.
UFO just landed and posted this here
D очень старый, да, но D не предлагал того, что предлагает Rust. Но в любом случае, вы правы, тут рассудить может только время.
Раст тоже не предлагает кучу всего, что предлагает D. Те же шаблоны (не дженерики), миксины, перегрузка операторов, ranges вместо iterators, куча ништяков с чистыми функциями, shared data (только message passing есть).
Я не имел в виду целиком весь объём фич (кстати, перегрузка операторов в Rust есть, как и разделяемые, причём безопасно, данные; что такое ranges в D, я не помню, но итераторы в Rust могут быть оптимизированы LLVM так, что собственно итератора как объекта там не останется), многие из которых спорны (вроде миксинов в виде строк). Я имел в виду вполне конкретный, самый основной поинт Rust — безопасное управление ресурсами без сборщика мусора.
Мне кажется, что D потерял много времени. Он слишком стар, не завоевал популярности за это время, и выход C++11 его здорово подкосил. Во многом моё мнение перекликается с озвученным здесь

Rust ещё не наделал таких ошибок :)
Интересный у Вас опыт. Надеюсь, разработчики Rust не наступят на те же грабли.
Текст по ссылке не мой, если что.

Мой опыт, это большой интерес к D на начальном этапе, потом он потихоньку уменьшался-уменьшался. А потом C++11 подоспел.
Что значит «коммерчески успешный язык»? Успешный язык я могу понять, это тот который активно используется в определенных кругах. В этом смысле Go весьма успешный язык, учитывая, что ему всего 5 лет от роду. Для нагруженных многопоточных серверных приложений ему конкурентов практически нет. В остальных нишах Go вполне себе тоже развивается.
Эрлангу, для примера, нонче 30 лет будет. Это успешный язык?

При чем тут вакансии на job-портале? У Go слишком специфическая ниша. Чтобы в этой нише работать, знание языка Go это несущественное требование… Go достаточно прост, для того, чтобы без проблем его освоить при наличии хоть сколь-нибудь адекватного опыта разработки на других языках…
За Rust'ом внимательно слежу. Он скорее альфа, чем бета… К нему вообще на данном этапе претензии предъявлять глупо…
UFO just landed and posted this here
А зачем вам Go в каждой дырке? Это какое-то аномальное желание, мне кажется… Лично вам от этого в чём польза?

Я понимаю люди заботятся о профессионализме. О зарплате когда люди заботятся, я тоже могу понять… Когда язык становится попсой, зарплата разработчиков на нем падает. Это объективная реальность. По этой причине популярность Go лично мне не интересна…
Под ваше определение подходят, в основном, С#, C++, и Java, доминирующие в большом энтерпрайзе. Однако это не мешает существовать и пользоваться популярностью у разработчиков целой кучи языков — Ruby, Python, Erlang и даже PHP. И на них тоже пишут программы (которые продаются), или сервисы (приносят прибыль). Или я неверно понял термин коммерческой разработки?
— стабильности проверенной годами

А годами — это сколько? Два года? Пять? Десять? Двадцать пять?

— обилии КАЧЕСТВЕННЫХ библиотек, вылизываемых годами

А чем определяется качество библиотеки? Фактом вылизывания её годами?

— обилии большого числа дешевых и качественных программистов

Дешёвых и качественных? Хм… Любопытное сочетание, вы не находите?..
UFO just landed and posted this here
Дешевых или качественных?
Rust даже 1 год назад очень сильно отличался от сегодняшнего; Rust 2 года назад — это совершенно другой язык.
Не уверен, что это отличие в лучшую сторону.
Это действительно спорный вопрос, и некоторые вещи, которые там сделали, мне тоже не очень нравятся, но в целом, как мне кажется, направление верное. Язык становится более однородным и простым. Вырабатываются какие-то общие подходы и идиомы, которые находят отражение в самом языке. Например, избавление от managed-указателей в самом языке имеет гораздо больше преимуществ, чем недостатков.
Я отнюдь не говорю, что развитие языка — это плохо. Но за два года превратить один язык в «совершенно другой» мне намекает на то, что у создателей нет четкого плана того, что они делают. Они проводят эксперимент, какой подход покажет себя лучше и приживется. Сложно решиться на изучение технологии, у которой в новых версиях постоянно breaking changes и все время приходится переучиваться.
Изначально у авторов действительно не было конкретных представлений о форме языка и его возможностях, кроме самых общих. Это на самом деле был эксперимент. Однако то, что версию 1.0 собираются выпускать уже в этом году, говорит о том, что в целом язык уже обрёл основной «хребет» функциональности и фич, и это на самом деле так — самые основные концепции и подходы меняться уже не будут. Сейчас радикальные breaking change'ы уже более-менее запланированы, и они больше технические, чем принципиальные (те самые unboxed-замыкания и DST).
Go не взлетел? Ну да, за исключением того, что его используют какие-то Google, Yandex, DigitalOcean, CloudFlare, PayPal, CoreOS и конференция GopherCon собрала неслабое такое количество народу. Ерунда дело.
UFO just landed and posted this here
Если ориентироваться на Freelance биржи, то есть только PHP и немножко Java :) Причем PHP популярнее Java в 4 раза
Во-во, за последнее время встретил кучу крутых (быстрых и бронебойных) проектов на Go, причем многие из них переписаны с других языков (с того же питона). И да, дело не в девелоперах и кривых руках, проекты изначально были круты, а теперь просто умопомрачительны в плане производительности.
D не взлетел. Go не взлетел. Не взлетит и Rust. Ближайшие 5 лет так точно.

Много раз слышал это словосочетание, «не взлетел»… А что вы вкладываете в эти слова? Когда о языке можно будет сказать, что он взлетел?
UFO just landed and posted this here
Go вполне взлетел. Есть вполне боевые системы управление облачными сервисами, написанные на Go.
Хотя лично мне Go не понравился, все-таки нельзя не признать, что это успешный и полезный проект.
С/C++ библиотеки выкидывать не надо. С ними надо линковаться и дружить. Смотрите группу «bindings» на rust-ci

Те, кому была важна безопасность уже давно пересели на Java

Я не так хорошо знаком с Java, чтобы проводить полноценный анализ, но уже тот факт, что там все объекты могут быть null, настораживает по поводу безопасности. Можете хоть на минутку допустить мысль о том, что Rust даст Вам больше гарантий надёжности?
>D не взлетел.
Взлетит как только появится возможность писать софт под iOS и Android, а возможность эта появится в течении ближайшего года. Одна кодовая база для всех устройств это реально круто.

А что касается Rust и Go — это языки маргиналов. Слишком своеобразные для того, чтобы стать мейнстримом. На D хотя бы с C# и С++ перейти можно за пару недель в отличие от…
Так уже есть C#+Xamarin и Qt. Серьезные конкуренты для D в мобильном кроссплатформенном сегменте.
А где почитать про поддержку(планируемую, как я понимаю) iOS/Android? Дайте ссылку.
Боюсь все как всегда упрется в нормальную поддержку внешнего окружения (БД, сети, графика, оборудование и т.п.) как всегда бывает в хороших но малопопулярных языках. Как с этим дела обстоят в Rust?
Пока большого количества библиотек нет, но над этим ведётся активная работа. Например, для работы с графикой в последнее время появилось несколько библиотек (rust-sdl2 и ещё несколько, я сейчас уже не помню точно). Для баз данных тоже есть биндинги (точно знаю, что есть для PostgreSQL и SQLite). Работа с сетью есть в стандартной библиотеке, и есть биндинги к сторонним библиотекам вроде ZeroMQ.
А как все это уживается с тем, что синтаксис языка до сих пор мутирует (как написал ТС)? Библиотеки собираются старыми версиями компилятора или кто-то их постоянно переписывает?
Обычно их постоянно переписывают. Изменения происходят всё-таки последовательно, поэтому если есть интерес и желание следить за развитием языка сейчас, то поддерживать библиотеки в адекватном состоянии не так трудно. Тут ничего не поделаешь, бета-версии — они такие :) кстати, для проверки совместимости библиотек многими используется travis-ci, так что обычно даже вручную не нужно проверять, что что-то сломалось.
UFO just landed and posted this here
В том и вся прелесть, что можно использовать готовые C++ библиотеки. Зайдите на rust-ci, там вам и БД, и графика, и сети.
Ну все же по скорости Haskell обгоняет Python, а часто и Java.
Проигрывает та высоком уровне вхождения и медленной выдаче первой версии (что компенсируется временем на доводку).
У меня обратный опыт. Чтобы Хаскель более-менее приблизился к Java (не говоря о C/C++) нужно писать в особом, довольно утомительном и не очень идеоматичном стиле. И то гарантии нет.
На коротких программах, где JIT не успевает набрать статистики, Haskell обгоняет очень сильно.
Там где порождается много объектов с коротким временем жизни — Java менее приспособлен к эффективной сборки мусора.

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


1) Документации очень мало, существующая почти вся нерабочая (устарела).
2) Постоянные изменения в компиляторе/библиотеке. Ни дня без breaking change.
3) Не только постоянные изменения, но и неконсистентное состояние: одну часть изменили, другую еще нет.
4) Ни одного рабочего примера в интернете (видимо, из за (2)).
5) Каждая строка кода — битва с компилятором насмерть. Пытались писать особо изощренную шаблонную магию в С++? Тут этот ад во всем коде.
6) Ошибки компилятора повергают в недоумение даже программистов под gcc с его жуткими сообщениями.
Не поймите неправильно, я попробовал и язык мне очень нравится, я планирую обязательно научиться ему. Года через 2-3. Изучать сейчас его можно лишь с одной целью: если ваше хобби — создание языков и вы хотите следить за развитием какого-то языка практически с нуля.

Я, кстати, еще забыл:
7) Куча багов в компиляторе, постоянные креши с просьбой отправить багрепорт.
7) Куча багов в компиляторе, постоянные креши с просьбой отправить багрепорт.

Да, баги есть, но их не куча. Гораздо меньше, чем могло бы быть, и при этом ICE обычно исправляются довольно быстро, если их отправить в багтрекер Rust.
Я подошел к оценке потребительски. Я начал писать микробиблиотечку и просто писал и ловил баги. Штуки три поймал за пару часов.
Еще многое удивляет в языке. Например, понять концепции всех этих указателей довольно просто: в конце концов я и так в голове все держу это, но что напрягает, так это, например, то, что &'static str не конвертится само в &str. И че, мне теперь писать две функции чтоли? Или шаблон по модификатору ссылки? Какого фига, почему immutable borrow нельзя сделать на статик строку? И таких «удивительных» вещей довольно не мало.
Вы что-то не то делали.
но что напрягает, так это, например, то, что &'static str не конвертится само в &str. И че, мне теперь писать две функции чтоли?

Это неправда.

fn print_string_slice(s: &str) { println!("{}", s); }

fn main() {
    let s: &'static str = "abcd";
    print_string_slice(s);  // abcd
}


&'static str вполне себе конвертируется автоматом в &str.
А print_string_slice(«abcd») уже нельзя! Сюрприз :)
Можно. Опять, вы что-то не то делаете. Я сделал отдельную переменную только чтобы явно выделить тип.
Хм. Похоже, моя ошибка. Спасибо, починил у себя код!
Upd. Ах да, две функции тоже нельзя, нет перегрузки же! Этого я тоже не понимаю, сложно чтоли сделать? Только один ::new доступен, другие конструкторы будь добр назови по-другому.
Перегрузка функций (её отсутствие) — это один из самых спорных вопросов в дизайне Rust. Буквально на днях на эту тему поднимался разговор в списке рассылки. У разработчиков языка на эту тему очень жёсткая позиция, так что здесь вряд ли будут изменения.
Я, право, не вижу проблемы. Перегрузка функций усложняет язык — не всегда понятно, что именно Вы вызываете, пока не сравните типы аргументов. А для чего всё? чтобы написать new() вместо new_something() или from_something()? Смешно.
>Перегрузка функций усложняет язык — не всегда понятно, что именно Вы вызываете, пока не сравните типы аргументов

Этак можно дойти до того, что и виртуальные функции, и полиморфизм «усложняют язык, т.к. не всегда понятно, что именно вы вызываете».

Может разработчики языка просто поленились хранить сигнатуры функций не просто по имени, но и по количеству/типу параметров, а теперь прикрывают этот фундаментальный просчет отмазками «ну вам что, сложно написать add_float(float), add_int(int), add_unsigned_int(unsigned int) вместо add(float), add(int), add(unsigned int)» (условно), потому что это настолько глубоко в кишках, что туда никто не хочет лезть?
Крайности. Виртуальные функции как-раз несут реальную пользу, в отличие от перегрузки. Так что вносимое усложнение языка обосновано. Более того, в Rust нет наследования, поэтому определить, какая функция будет вызвана в конкретном месте, намного проще — достаточно посмотреть, какое (или какие) из реализованных (и доступных области видимости) способностей (traits) эту функцию имеют.
Пожалуйста, не называйте трейты способностями :) насколько я в курсе, такой перевод термина trait в контексте языков программирования вообще не используется и сильно режет глаз :)
А мне как раз очень нравится. Оригинальный смысловой перевод.
А я уж думал, когда меня поругают за «обозреватель», «способности», «сопоставление с образцом», и другие ;)

Просветите меня, как по-русски грамотно перевести trait?
Никак — просто трейт. Например, такой термин используется в переводах книг по Scala. Ещё один возможный перевод — «типаж», но он, имхо, хуже, чем «трейт». См. здесь.
А сопоставление с образцом — это как раз самый распространённый и вменяемый перевод pattern matching'а, хотя в разговорной речи обычно всё-таки говорят «паттерн-матчинг» :)
Простите, но «трейт» уж совсем никак не звучит по-русски. «Типаж» звучит нитересно, но «способность» лучше вписывается в полные фразы:
«тип реализует способность» vs " тип реализует типаж" vs «тип реалиует трейт»
Тем не менее, это термин. В сообществе Scala и, насколько я в курсе, PHP используется в подавляющем большинстве именно он. Multitran также символизирует.
«Тип реализует трейт» ничем не хуже чем, например, «тип реализует интерфейс». И если так подумать, то способности не реализуют, ими обладают, что в контексте языков программирования не используется почти никогда.
Это конечно дело вкуса, но я на стороне автора — «тип реализует способность» звучит намного лучше чем «тип реализует трейт» и это хорошо, что автор не пошёл на поводу у т.н. «общественности» которая говорит «трейт» по русски.
Не могу с вами согласиться. Это не дело вкуса, это общепринятая терминология. Точно так же, как Map<K, V> в Java не переводят как «отображение» (хотя это и есть непосредственный перевод, в том числе и по смыслу) — обычно так и говорят, «мап» или «мапа», реже — «словарь» или «ассоциативный массив» (что очень длинно и неудобно, поэтому так говорят редко). Если не придерживаться общепринятой терминологии, то люди просто перестанут друг друга понимать.
Map<K, V> в Java не переводят как «отображение»
Потому что переводят как раз-таки как «ассоциативный массив» :) Я бы сказал, это устоявшийся перевод на русский, длинный и неудобный, но… «Отображение» — это скорее из мира математики.
Нет, не так. Map в этом случае в английском подразумевает именно отображение, потому что ассоциативный массив по сути и есть математическое отображение, которое в английском обозначается, в частности, словом «map» (или «mapping»).

Грубо говоря, в английском этой структуре данных соответствуют понятия {map, dictionary, associative array}. В русском же это будет {словарь, ассоциативный массив}. Это означает, что перевод «map» как «отображение» в контексте структур данных будет неверным, потому что это не устоявшийся термин. При этом «мапа» или «мап» будет сленговым/жаргонным переводом, который допустим в определённых условиях (например, в личной переписке или в разговоре), но недопустим в других условиях, например, в деловом/научном тексте. То же самое справедливо для трейтов.
Ну, я полностью с вами согласен. Вы, в общем-то, верно переформулировали своими словами мой первоначальный посыл:
Это означает, что перевод «map» как «отображение» в контексте структур данных будет неверным, потому что это не устоявшийся термин.
А, ок. Видимо, я вас неправильно понял, сорри :)
Есть же красивый термин «сюръекция» :-)
Ну «сюръекция» — это «отображение на», т.е. отображение, у которого образ совпадает с областью значений. Если в вашей мапе из строк в Integer меньше 2^32 элементов, или если их 2^32, но хотя бы два значения совпадают, то это уже не сюръекция :)
tenshi: А при чём тут множество значений Integer?) Map — это сюръекция множества ключей _засунутых в структуру_ на множество значений _тоже засунтых в структуру_. Как ключи, так и значения в общем случае могут быть любых типов. Важно лишь то, что для любого значения найдётся какой-нибудь ключ.

Сюръекция, в строгом математическом смысле, это «отображение на», т.е. такая функция, у которой образ совпадает со множеством значений. В общем случае образ функции может быть меньше области значений. Например, есть функция f(x) = x^2. Ясно, что мы можем считать, что f: R → R. Но Im f = [0, ∞) ⊂ R. Т.е. f — не сюръекция. Это, я думаю, вы знаете.

Аналогично с Map. В декларации Map явно указываются области определения и значения (собственно, почему словарь и назвали «отображением» в английском): Map. Если бы Map m было бы сюръекцией, то для любого Integer i всегда бы нашлось такое String s, что m.get(s).equals(i), что, понятно, не соответствует действительности.

Googolplex: Да, любое отображение можно рассматривать как сюръекцию на его образ. Однако, строго говоря, это будет уже другое отображение, потому что отображение — это тройка множеств (dom f, Im f, f ⊆ dom f × Im f), и если одно из множеств поменяется, то формально само отображение тоже будет другим. В контексте структур данных это существенно. В частности, Java не позволяет описать тип «Множество чисел типа Integer, являющихся значениями данного экземпляра Map», поэтому нельзя говорить о «множестве значений, засунутых в структуру». Следовательно, когда вы имеете на руках Map, вы можете его понимать только как отображение f: String → Integer, и никак иначе. А это уже, очевидно, не сюръекция. Если бы в Java можно было бы описать такой тип (возможно, Agda2 и аналогичные языки с зависимыми типами такое могут), хотя я лично сомневаюсь в его полезности, то тогда, вероятно, можно было бы говорить о сюръекциях, хотя я тут тоже утверждать ничего не могу — не работал особенно с этими языками.

tenshi: Отображение типа на тип — это уже полноценная функция. Map и подобные структуры работают не с типами (которые в общем случае — бесконечные множества), а с конкретным конечным множеством значений. При этом одни значения помещаются в «образ» (ключи), а другие в «отображение» (значения). А Map гарантириует сюръективное отображение первого множества на второе. А запись вида Map — не более чем ограничение на типы ключей и значений. Если вы запросите значение по ключу, которого нет в мапе, то получите что угодно, но только не Integer.
Можно перевести иначе. «отображение» — это слишком общий, да к тому же перегруженный математикой термин. Давайте представим, что нам нужно перевести выражение:
input.map(|x| x^2)
По-русски это звучит как «каждому элементу x из входной последовательности сопоставляется x^2». Отсюда, собственно, и термин "сопоставление". Он не ассоциируется с математикой и лучше отражает смысл происходящего.
Я вам очень не советую переизобретать терминологию, вы сделаете только хуже для своих читателей. Если бы вы переводили художественный текст, то всё было бы в порядке. Если бы вы переводили тексты с совершенно новыми концепциями, которые до вас не переводил никто в принципе (включая сленг и жаргон), то это тоже бы прокатило. Но в технических/научных текстах с уже давно устоявшимся переводом терминов изобретать свой собственный перевод этих терминов нельзя. Это одно из основных правил переводчика профессионально-технической литературы.
Примесь это mixin. Это другого рода концепция. Например, в Scala примеси реализуются через трейты. В Rust такого понятия сейчас вообще не существует. Трейты — это, фактически, классы типов из Scala.
Могу ошибаться, но кажется что это связано с выводом типов. Перегрузка идет в разрез с этой концепцией.
1) Документации очень мало, существующая почти вся нерабочая (устарела).

Документации мало, да, но туториалы и стандартная библиотека обычно поддерживаются в более-менее актуальном состоянии. Никуда не денешься, язык всё ещё в бете.
2) Постоянные изменения в компиляторе/библиотеке. Ни дня без breaking change.
3) Не только постоянные изменения, но и неконсистентное состояние: одну часть изменили, другую еще нет.
4) Ни одного рабочего примера в интернете (видимо, из за (2)).

То же самое. Язык активно развивается, и уж лучше пусть пока будут breaking change-ы, чем зафиксированный неудобный дизайн.
5) Каждая строка кода — битва с компилятором насмерть. Пытались писать особо изощренную шаблонную магию в С++? Тут этот ад во всем коде.
6) Ошибки компилятора повергают в недоумение даже программистов под gcc с его жуткими сообщениями.

Очень спорно и субъективно. Достаточно на базовом уровне воспринять самые важные концепции языка (aliasing указателей и владение данными), и получится писать сразу почти без ошибок. Никаких сложных концепций, как в метапрограммировании, там нет в принципе. Говорю это по опыту.

Вы хотите сказать, что вот это (первое, что нашёл в гугле; это всего лишь ошибка о том, что в функцию передают лямбду, принимающую string, а надо, чтобы принимала wstring):

prog.cpp: In instantiation of ‘void fill_array(std::array<T, N>&, F&&) [with T = std::vector<std::basic_string<wchar_t> >; unsigned int N = 10u; F = main()::<lambda()>]’: prog.cpp:18:61: required from here prog.cpp:10:9: error: no match for ‘operator=’ in ‘v = main()::<lambda()>()’

prog.cpp:10:9: note: candidates are:
In file included from /usr/include/c++/4.7/vector:70:0,
                 from prog.cpp:4:

/usr/include/c++/4.7/bits/vector.tcc:161:5: note: std::vector<_Tp, _Alloc>& std::vector<_Tp, _Alloc>::operator=(const std::vector<_Tp, _Alloc>&) [with _Tp = std::basic_string<wchar_t>; _Alloc = std::allocator<std::basic_string<wchar_t> >]

/usr/include/c++/4.7/bits/vector.tcc:161:5: note: no known conversion for argument 1 from ‘std::vector<std::basic_string<char> >’ to ‘const std::vector<std::basic_string<wchar_t> >&’

In file included from /usr/include/c++/4.7/vector:65:0,
                 from prog.cpp:4:

/usr/include/c++/4.7/bits/stl_vector.h:427:7: note: std::vector<_Tp, _Alloc>& std::vector<_Tp, _Alloc>::operator=(std::vector<_Tp, _Alloc>&&) [with _Tp = std::basic_string<wchar_t>; _Alloc = std::allocator<std::basic_string<wchar_t> >; std::vector<_Tp, _Alloc> = std::vector<std::basic_string<wchar_t> >]

/usr/include/c++/4.7/bits/stl_vector.h:427:7: note: no known conversion for argument 1 from ‘std::vector<std::basic_string<char> >’ to ‘std::vector<std::basic_string<wchar_t> >&&’

/usr/include/c++/4.7/bits/stl_vector.h:449:7: note: std::vector<_Tp, _Alloc>& std::vector<_Tp, _Alloc>::operator=(std::initializer_list<_Tp>) [with _Tp = std::basic_string<wchar_t>; _Alloc = std::allocator<std::basic_string<wchar_t> >; std::vector<_Tp, _Alloc> = std::vector<std::basic_string<wchar_t> >]

/usr/include/c++/4.7/bits/stl_vector.h:449:7: note: no known conversion for argument 1 from ‘std::vector<std::basic_string<char> >’ to ‘std::initializer_list<std::basic_string<wchar_t> >’


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

dangling.rs:3:12: 3:14 error: `i` does not live long enough
dangling.rs:3     return &i;
                         ^~
dangling.rs:1:23: 4:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 1:22...
dangling.rs:1 fn dangling() -> &int {
dangling.rs:2     let i = 1234;
dangling.rs:3     return &i;
dangling.rs:4 }
dangling.rs:1:23: 4:2 note: ...but borrowed value is only valid for the block at 1:22
dangling.rs:1 fn dangling() -> &int {
dangling.rs:2     let i = 1234;
dangling.rs:3     return &i;
dangling.rs:4 }
error: aborting due to previous error


Это одна из наиболее часто встречающихся ошибок в Rust (когда ссылку передают за пределы её области жизни). У меня сейчас нет рядом компилятора Rust, но если написать аналог кода по ссылке наверху на Rust, то вы получите ясное и недвусмысленное сообщение о том, что типы несовместимы.
кто владеет определённой сущностью (owner), кто лишь временно одалживает её (mutable borrow), а кто просто пришёл посмотреть (immutable borrow)
Теперь буду знать, какими обидными словами ругать должников и любителей поглазеть.
Еще не плохо рассказать (пардон за рутинный вопрос, но не последний по важности) — что представляет из себя инструментарий (есть ли нормальный отладчик, IDE — приспособленная для работы — или юзай простой редактор, компилируй в консоли/батничком). Насколько доступны сторонние наработки (С++ держится на плаву благодаря им и наоборот D — не может поднятся даже из-за не утвежденной библиотеки поставки).
Самые распространённые современные отладчики — gdb и lldb — работают и используются.

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

Интеграция с C отменная. FFI в Rust, имхо, лучше только в самом C :)
Насколько мне известно, ситуация с IDE в последнее время идёт на поправку. Если сначала можно было использовать Vim/Emacs/Sublime/Kate/Geany с подсветкой, есть и авто-подстановка, которую можно прикрутить к Emacs или Atom (проект).
А что значит «перешёл на Rust»? Кто-то в продакшне использует Rust? Или вы в Rust core team?
«перешёл» в данном контексте значит «впредь стал реализовывать свои новые и старые идеи»
Увы, у rust до сих пор даже пакетов под операционки нет. Дистрибьюция в виде tar.gz only — это как-то печально…
Ну да, мы в продакшен на арче с генту, вперёд. Нет ни rpm, ни deb'ов. Считай — 90% линуксов пропущено.

(да, я в курсе, что по мнению дистровотч арч занимает 69% рынка, а генту 78%, но я предпочитаю быть реалистом).
В ссылке, что я дал для Ubuntu, есть deb пакеты. Как я понимаю, можно либо подключить себе этот репозиторий и обновляться стандартными средствами, либо качать напрямую.
Во-первых, когда Rust станет постабильнее, появятся и пакеты, поддерживаемые мейнтейнерами дистрибутивов. Сами разработчики и не должны этого делать никак. А для Ubuntu, например, уже сейчас есть PPA.

Во-вторых, зачем вам в продакшне компилятор Rust? В продакшне будет результат работы компилятора — бинарник, который скорее всего даже будет статически слинкован — аналогично Go. У него не будет зависимости на Rust.
А рабочая станция разработчика — это не продакшен? Когда я говорил «нет ничего, кроме tar.gz», я имел в виду то, что на сайте у авторов. Go в этом смысле подсуетился, и пакеты есть во всех приличных дистрибутивах.
Рабочая станция разработчика — это рабочая станция разработчика. Продакшен — это боевые сервера. Если вы считаете не так, то у вас, как мне кажется, странное восприятие термина «продакшен» :)
На сайте у авторов, имхо, и не должно быть ничего, кроме tar.gz. Пакеты для конкретных дистрибутивов должны делать мейнтейнеры. Когда Rust стабилизируется, я более чем уверен, что во всех популярных дистрибутивах появятся пакеты. Сейчас в этом нет особого смысла.
Как-то совсем ни о чём статья по меркам хабра. Куча голословных утверждений, которые без деталей сильно попахивают.
Ну, например,
Указатели есть только в незащищённом коде (unsafe {}). Вместо них в безопасном коде есть ссылки, которые гарантированно указывают на существующие объекты.

К этому утверждению сразу пару серьёзных вопросов. Ну, например:

1. Куча алгоритмов клинически зависят от nullptr. Ну там банальный список или дерево — у каждого элемента есть указатель на next или child элементы, и этот указатель by design может стать нулевым (nullptr). Программист, соответственно, итерирует список чем-то типа while (curItem.next !=nullptr). А тут вроде как nullptr нету. И как с этим жить? Выносить все алгоритмы обхода структур данных в unsafe? Пилить отдельное поле под указание конца цепочки? А зачем тогда rust?

2. В плюсах тоже есть ссылки, которые, в отличие от указателей, «гарантированно» указывают на объект. «Гарантированно» — в том смысле, что компилятор не даст создать ссылку без инициализации. И, если ваша функция, например, не должна принимать на вход nullptr ни при каких условиях, вы делаете параметр ссылкой. Удобно.
Однако это не спасёт, если:
а)
int* ptr = new int; 
int& ref = *ptr;
// blabla * 100 lines
delete ptr;
// blabla
ref = 1; // Ооps


б) или даже так:
int* ptr = nullptr;
// bla bla * 100 lines
int& ref = *ptr;
ref = 1; // Oops

Как это, собственно, решается в rust-е? Как конкретно этот язык
предотвращает почти все падения

?
>Программист, соответственно, итерирует список чем-то типа while (curItem.next !=nullptr). А тут вроде как nullptr нету. И как с этим жить? Выносить все алгоритмы обхода структур данных в unsafe? Пилить отдельное поле под указание конца цепочки?

Да это-то не особо проблема. Первое, что приходит в голову — создать отдельный специальный объект (статический, если они конечно есть в Rust :)), назначить его «нулевым» и ссылаться на него там, где привыкли ссылаться на NULL.
Т.е. лепить отдельный nullptr для каждого типа данных? (Если, конечно, там строгая статическая типизация. Если нестрогая, то как может не быть потерь производительности?)
Я не говорю, что обойтись без nullptr вообще никак невозможно. Возможно. Но у каждого обходного манёвра есть свои достоинства и недостатки. Поэтому все подобные утверждения нужно пояснять, как конкретно тот или иной аспект реализован. Иначе это маркетинговый буллшит, а не содержательная статья для хабра.
С этим не поспоришь, полностью согласен.
nullable нужен там где он нужен, где значение может быть нулевым, для этого есть en.wikipedia.org/wiki/Option_type
для каждого типа данных его лепить не нужно, также как не нужны магические значения -1 и т.п.
nullable занимает как минимум на 1 бит больше.
Там, где обычный указатель помещался в один регистр процессора, для nullable надо уже два.
А, вижу ниже уже написали, что если тип — указатель, то его значение не может быть null, поэтому размер nullable не растёт
Давайте разберём те самые «голословные» утверждения:

1. Когда-нибудь слышали о Option (в Scala) или Maybe (в Haskell)? Вот пример реализации дерева на Rust, и никаких unsafe{} блоков не нужно.

2. В плюсах ссылка есть лишь синтаксический сахар к указателю. Компилятор не гарантирует её доступность:
int *x = 123;
int &y = *x;
y = 1; // memory access violation


Далее по Вашим примерам.
a) В Rust не нужно вручную удалять память (это ведь источник ошибок), и переменные живут до конца своей области видимости. Но мы можем немного изменить пример, не меняя сущности:

let mut array = Vec::new();
array.push(1);
let ptr = array.get(0); // возвращает ссылку на первый элемент
array.push(2); // небезопасно, ибо память под вектор может измениться

Получаем справедливое ругательство о том, что мы не имеем право изменять массив, пока жива ссылка на один из его элементов:

:21:9: 21:14 error: cannot borrow `array` as mutable because it is also borrowed as immutable
:21 array.push(2);
^~~~~
:20:19: 20:24 note: previous borrow of `array` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `array` until the borrow ends
:20 let ptr = array.get(0);
^~~~~
:22:6: 22:6 note: previous borrow ends here
:17 {
:18 let mut array = Vec::new();
:19 array.push(1);
:20 let ptr = array.get(0);
:21 array.push(2);
:22 }

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

Я понимаю Ваше возмущение, но Вы не сможете познать Rust, оперируя исключительно моделью программирования С/C++. Для того, чтобы получить помощь от компилятора в виде гарантии безопасности Ваших операций с памятью, нужно думать немного иначе, и изучение функционального программирования в целом очень тому помогает.

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

Это, конечно, детский лепет. В старых добрых Сях 1969-ого года разработки локальные переменные тоже живут до конца своей области видимости, прямо на стеке. Весь вопрос в динамической памяти, когда вам нужно создать объект, который переживёт функцию-создатель. Если в Rust автоматический сборщик мусора, то — на основе чего? Есть ли фризы сборщика и прочие прелести, особенно актуальные для системного ПО?

Ну и опять же, no offense, но просто все эти вещи должны быть раскрыты в основной статье, а не глубоко в каментах.
Maybe классная штука, но не бесплатная.

Очень даже бесплатная. По крайней мере Option<&T> под капотом использует всё тот же NULL. Проверяется просто:
    println!("{}, {}",
        std::mem::size_of::<Option<&int>>(),
        std::mem::size_of::<int>())


Далее про RAII и «детский лепет».
Указатель на динамическую панять (Box) тоже живёт, пока живёт его владелец. Получив ссылку на содержимое, мы «замораживаем» указатель на время действия ссылки (определяется статически, так что за это не платим). Rust не позволит нам угробить динамическую память, пока на неё ссылаются (так же, как и в приведённом примере с вектором).

Сборщик мусора в Rust есть, но он сугубо по желанию (не один рубильник для всего сразу, а Gc просто как тип указателя, реализованный как сторонняя библиотека). Так что системное ПО живёт счастливо и прелестями Gc не пользуется.

Ну и опять же, no offense, но просто все эти вещи должны быть раскрыты в основной статье, а не глубоко в каментах.

Я раскрыл общие черты языка, без особой конкретики, да в весьма субъективном соусе. Такого рода пост, по Вашему, неполноценен? Понимаю, что Вы хотите большего, и постараюсь осветить, но только как приятное дополнение, а не требование.
В Rust Option — бесплатная штука. Компилятор оптимизирует использование памяти так, что, в частности, Option<&int> будет занимать ровно столько же памяти, сколько и &int. Это возможно за счёт отсутствия null-указателей. Более того, в планах схожая оптимизация для большего количества типов, помимо указателей.

Про динамическую память тут уже объясняли. Все операции с памятью в Rust детерминированы. Например, вышеупомянутый `Vec` выглядит примерно так:
pub struct Vec<T> {
    len: uint,
    cap: uint,
    data: *mut T
}

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

Примерно так же работает и std::vector в C++. Однако в C++ вы можете получить указатель на внутренности массива, и этот указатель сможет «пережить» сам массив — например, его можно вернуть из функции, где вектор является локальной переменной. В Rust это невозможно принципиально за счёт статического анализа. В этом, собственно, главное преимущество Rust — за счёт статического анализа полностью исключаются возможности обращения к невалидной памяти.

Если немного поразмышлять, можно увидеть, что типы, подобные Vec имеют семантику типов-значений, т.е. ведут себя точно так же, как типы-значения вроде int (за исключением автоматического копирования и вызова деструкторов; это различие также себя проявляет в системе типов Rust за счёт трейтов Copy, Clone и Drop), даже несмотря на то, что внутри у них динамически выделенная память. Такие структуры очень легко описывать в терминах владения данными и уникальных указателей. Однако, это не всегда удобно/возможно: например, с помощью уникальных указателей можно описать древовидные структуры данных, а вот двусвязный список, например, сделать уже нельзя. В таком случае используются другие типы умных указателей, например, Rc, который означает указатель с подсчётом ссылок, или Gc, который будет означать указатель со сборкой мусора. В C++ есть аналогичные типы, например, shared_ptr или unique_ptr, но в C++ ничего не мешает вам получить обычный сырой C-указатель на их внутренности и сохранить его после того, как указатель «умрёт». В Rust этого сделать нельзя в принципе.

В целом, я согласен, это тема достойная отдельной статьи.
Sign up to leave a comment.

Articles

Change theme settings