Как стать автором
Обновить

Комментарии 40

Ложка дегтя: открытые на чтение и на запись файлы имеют один тип, и это API объявлено стабильным. На работе устроили хакатрон — решить одну задачу на разных языках. На Rust умудрились на эти грабли наступить.
По моему во всех более-менее приличных языках эти типы разделены.
Хм… А подскажите пожалуйста, в каких именно. Просто их тех, что я сталкивался, не припоминаю такого разделения ни у одного.
И как быть с файлами открытыми на изменение? Что-то вроде интерфейсов readable и writable, а файл, открытый на изменение, реализует оба?
Я что-то тоже сходу не припомню. Вот в более-менее приличном хаскеле openFile может открывать и на чтение и на запись, и возвращает однотипные Handle.
OCaml, Java (и современные JVM-ориентированные языки), Scheme.

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

Вы привели в пример Java, но в Java помимо всех этих развесистых декораторов из io тоже есть низкоуровневый API для работы с файлами с передачей параметра OpenOptions. Все эти абстракции Reader/Writer пишутся над низкоуровневым дескриптором в зависимости от потребностей. Не представляю, зачем в ядро «новой ОС» тащить все эти высокоуровневые штуки, которые сегодня одни, а завтра другие в дань моде, новым алгоритмам или ещё чему-то.
Я «загнался» по принципу минимальности интерфейса.
Из того, что разработчики ОС в прошлом веке ему не следовали, еще не следует что его надо нарушать в стандартных библиотеках современных языков программирования.
В самой ОС это позволит, например, не держать полей, нужных только для организации записи операций записи, в структурах, представляющих доступные только на чтение сущности.
На уровне системного вызова всегда можно указать, что данный поток открывает данный «файл» только для чтения. Однако, это не исключает того, что в другом потоке этот же файл можно открыть на запись. А можно и вовсе отобразить его в память. Прибавьте сюда еще буферизацию, кеширование и виртуальную память. Разработчикам ядра ОС, будь они из прошлого века или века настоящего, приходится решать задачи немного иного уровня. Вот, например, с такой структурой связывается файловый дескриптор в Linux. Где здесь overhead, связанный со знанием о том, что установлен флаг O_RDONLY. В контексте сказанного мной выше.
Извиняюсь, ссылка на структуру съелась. Или я не могу их ставить
git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/linux/fs.h?id=refs/tags/v4.0-rc6#n800
Необходимость этот флаг проверять (а забытая проверка — угроза безопасности). Да и вообще держать поле, в котором этот флаг хранится.
Кроме того, там есть еще указатель private_data, по которому могут хранится более сложные структуры.
Overhead на хранение бита? private_data — это driver specific данные, ядро их не трогает.
НЛО прилетело и опубликовало эту надпись здесь
Rust выглядит очень интересно. Но мое отношение к нему — пусть лет 5 на нем попишут другие люди, соберут все грабли, если после этого на нем кто-то еще будет писать, возможно, язык заслуживает внимания. Может и инструменты нормальные (IDE в том числе) появятся к тому времени. Очень уж много было «убийц C++» в последнее время которые так и не оправдали ожиданий, во всяком случае, как замены C++: D, Vala, Go, возможно еще какие-то о которых я забыл.
Весьма распространено заблуждение о том, что Go — это замена C++, в каждом обсуждении Rust кто-нибудь такое говорит. Go — не язык для системного программирования, у них с C/C++ и Rust совершенно разные нишы.

Vala, насколько я знаю, никогда особо и не рекламировали как убийцу C++, и у неё весьма своеобразная инфраструктура на основе GObject, которая, собственно, и не вышла за пределы Gnome и соседствующих проектов.

D — да, он позиционировался и позиционируется как улучшенный C++, но он развивался именно как «C++ с человеческим лицом». Да, он проще и удобнее C++, многих противоречивых фич там нет и много полезного добавлено, плюс бинарная совместимость с C++ с возможностью линковаться к C++-библиотекам (кроме D и, собственно, C++ так больше ни один язык не умеет), но как язык он практически ничего нового не привнёс. К тому же, насколько я знаю, его подвели проблемы в развитии — переход с D1 на D2, общая скорость развития низка. Например, сравните — 1637 вопросов по D на Stackoverflow начиная с 2008 года и 1841 вопрос по Rust, начиная, фактически, с 2013 года. Из-за того, что язык развивался и изменялся очень активно, многие грабли уже были собраны и исправлены. Я участвую в сообществе Rust уже несколько лет, и за последние год-два интерес к языку вырос колоссально. Релиз стабильной версии, я думаю, окажет ещё большее воздействие.

В отличие от других «убийц» Rust действительно принёс новые идеи, вернее, весьма практичную, полезную и удобную реализацию не очень известных ранее идей — владение данными и заимствование, которые на самом деле решают конкретные проблемы. Плюс полезные и удобные фичи из других языков, вроде трейтов-тайпклассов и паттернматчинга. Да, пока что в Rust есть острые углы, и реализовано далеко не всё, что хотелось бы, но и темпов развития авторы языка снижать не собираются.
1637 вопросов по D на Stackoverflow начиная с 2008 года и 1841 вопрос по Rust

Вы уж извините, но по моему скромному мнению, это из-за того, что в Rust'е постоянно менялся API, да и человеческой документации нет.
Попробовал я писать на Rust и первый камень это то самое отсутствие нормальной и понятной документации. А по исходным кодам ничего не понятно (честно говоря, то как выглядит код на Rust мне не очень нравится). В итоге что я сделал? Правильно, отправился во всемирную паутину на поиски информации. Тут я столкнулся со второй проблемой, т.к. API постоянно менялся, то на формах практически вся информация старая. Да и на doc.rust-lang.org тоже часто встречается API который помечен как deprecated.
В итоге я целый день мучал людей на официальном канале IRC по Rust. А многие моменты, например как в match'е (аналог switch()) использовать enum, до сих пор не понял.

А еще что мне не понравилось, так это непонятные ошибоки компилятора. Это примерно как при использовании STL'а в C++, где поставишь запятую не там, а компилятор тебе ошибок на три ватмана вывалит.

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

Я на Stackoverflow регулярно отвечаю на вопросы про Rust и могу гарантированно заявить, что вопросов про изменившиеся API весьма мало, гораздо меньше, чем вопросов по существу.

Документация в виде официального гайда вполне себе наличествует и всё время совершенствуется, да и с API-документацией тоже в последнее время всё очень неплохо. Книга The Rust Programming Language очень хорошо рассказывает про особенности языка — в частности, там есть и пример использования enum'а в match.

Насчёт ошибок компилятора — вы извините, но ошибки от компилятора Rust по понятности даже близко не сравнить с ошибками от gcc, например. rustc и покажет в точности где произошла ошибка, опишет её совершенно прямолинейным английским и даже даст совет по её исправлению. Да. они занимают много места, ну и что? Как правило, большая часть ошибок — это куски кода с выделением, где собственно находится ошибка. Конечно, ничто не совершенно, и rustc ещё много где нужно доработать в плане сообщений об ошибках — и этим, в частности, разработчики собираются заниматься при подготовке финального релиза.

Как уже много раз говорилось, в стабильных версиях API серьёзно меняться не будет.
там есть и пример использования enum'а в match.

Так правильно, потому-что в match там идет тип enum, а мне нужно было чтоб в match шел u8. В итоге на IRC канале предложили пачку вариантов с FromPrimitive (который толи выкинули, толи что-то неработало), с «as is» и опять я уперся в то, что ни в документации, ни нормальных примеров найти было сложно, а из того что нашел, то вместо короткого " 'enum type' => {},", превращалось в какую-то «колбасу».
В конце я просто весь enum руками переписал на const.

Насчёт ошибок компилятора — вы извините, но ошибки от компилятора Rust по понятности даже близко не сравнить с ошибками от gcc, например

Ну если я в C попытаюсь сравнить struct и int, то gcc мне так и напишет, что, мол, разные типы. А rustc мне писал (enum и u8) на пол страницы ошибок и я пол-часа вычитывал что-же он от меня хочет и как это исправить.

Как уже много раз говорилось, в стабильных версиях API серьёзно меняться не будет.

Знаете, смотря на Криса Мэйсона с его btrfs и разработчиков systemd, где оба в свои проекты тащат что на глаза попадется, т.к. не имеют достаточного опыта в создании такого типа проектов, то так-же мне и видятся разработчики Rust'а, которые будут в свой проект пихать любые возможности, что захотят. Если не ошибаюсь, в след. стабильной версии они хотят к существующему способу обработок ошибок (с try!() и Result<>), добавить еще и исключения. Т.е. сразу они не могли понять что им нужно, поэтому ничто не остановит их в будущем еще что-то поменять и превратить Rust в ту-же «legacy помойку» как и C++, где в оном ничего нельзя изменить из-за совместимости.

В общем ладно, как мне видится, то разработчикам Rust'а нужно просто собраться и избавится от соблазна что-то менять. Посмотрим что дальше будет. Но все равно, по моему скромному мнению, Rust все-таки, по большей части, так и останется ЯП для собственных нужд. Буду рад ошибаться.
видятся разработчики Rust'а, которые будут в свой проект пихать любые возможности, что захотят. Если не ошибаюсь, в след. стабильной версии они хотят к существующему способу обработок ошибок (с try!() и Result<>), добавить еще и исключения. Т.е. сразу они не могли понять что им нужно, поэтому ничто не остановит их в будущем еще что-то поменять и превратить Rust в ту-же «legacy помойку» как и C++, где в оном ничего нельзя изменить из-за совместимости

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

Кроме того, в Rust никогда не тащили фичи просто так. Вы же не видели Rust где-то с два-три года назад, так? С точностью до наоборот, всё это время из языка пытались исключить лишние фичи, и что-то новое вводилось после обсуждения и с обоснованием необходимости. Посмотрите репозиторий github.com/rust-lang/rfcs — там практически у каждого RFC, в особенности связанных с масштабными изменениями, обсуждение растягивается на много страниц. У авторов языка есть весьма чёткое видение целей и задач в его отношении, а спорные моменты разрешаются в обсуждениях в тех же RFC или на форумах.

Можете поподробнее рассказать про match? Вот рабочая программа, с преобразованиями в обе стороны:
#![feature(core)]

use std::num::FromPrimitive;

#[repr(u8)]
#[derive(FromPrimitive)]
enum Number {
    One, Two, Three
}

fn main() {
    match Number::One as u8 {
        0 => {}
        _ => {}
    }

    match Number::from_u8(0) {
        Some(Number::One) => {},
        _ => {}
    }
}


Да, пока что FromPrimitive — нестабильный трейт (поэтому его нельзя использовать с бетой), ну так и язык пока ещё только в бете.

Ну если я в C попытаюсь сравнить struct и int, то gcc мне так и напишет, что, мол, разные типы. А rustc мне писал (enum и u8) на пол страницы ошибок и я пол-часа вычитывал что-же он от меня хочет и как это исправить.

Вот такой код:
struct X;

fn main() {
    match X {
        10 => {}
    }
}

даёт такую ошибку:
test2.rs:5:9: 5:11 error: mismatched types:
 expected `X`,
    found `_`
(expected struct `X`,
    found integral variable) [E0308]
test2.rs:5         10 => {}
                   ^~
error: aborting due to previous error

Я не знаю, что может быть понятнее.
Кстати говоря, вы случайно не знаете, к какой версии они собираются заняться векторизацией? А то со времен известного патча, не принятого по причине слишком раннего появления и нехватки времени у архитекторов ничего больше вроде бы не слышно.
Нет, к сожалению, не знаю.
Я также не знаю, где вы услышали про исключения — ничего подобного в планах нет и не предвидится.

Ну может я в очередной раз наткнулся на старую информацию где-то в недрах GitHub'а.

Да, пока что FromPrimitive — нестабильный трейт (поэтому его нельзя использовать с бетой), ну так и язык пока ещё только в бете.

Так это версия 1.0 в бете. А что до FromPrimitive, то как сказано здесь: «Unstable: trait is likely to be removed».

Можете поподробнее рассказать про match?

Ну мне нужны были обычные перечисления, как в C, Go и т.д. На Rust'е это выглядело бы так: is.gd/qFdqhO
В этой ветке, в октябре 2013, добавили FromPrimitive / ToPrimitive, а потом, в ноябре того-же года, коммит был отменен (если я правильно понял GitHub).
В общем, нет ToPrimitive, а я стараюсь писать максимально независимо ни от чего, дабы на любой ОС, железе все работало. Например когда я пишу на C, то я стараюсь писать по стандарту и не использовать нестандартные расширения компилятора (а ToPrimitive, в принципе, можно отнести к этому понятию).

Так-что ждем Rust 1.1.
Я не очень понимаю причём здесь ToPrimitive, потому что он целиком и полностью заменяется кастом через as. FromPrimitive — да, его нестабильность пока что проблема.

А в целом enum'ы в Rust — это совсем другая концепция, чем enum'ы в С/C++ и прочем. Это алгебраические типы данных, tagged union'ы, если хотите — даже если они и могут быть представлены числами, как значения они с числами несовместимы. Собственно, именно поэтому непосредственно ваш пример не работает и не заработает никогда — и, имхо, это хорошо: лучше, когда котлеты отдельно от мух.
Ну да, всегда лучше все сделать ручками, когда можно было бы автоматически :)

А вообще, мне очень понравились enum в Go в сочетании с itoa. Например нам нужно перечисление, содержащее степени двойки. Так мы банально пишем:
enum {
        a = 1 << iota
        b
        c
}

Получаем:
  • a == 2^1
  • b == 2^2
  • c == 2^3

Или:
enum {
        a = iota * 3
        b
        c
}

  • a == 1 * 3
  • b == 2 * 3
  • c == 3 * 3

P.S. Я в курсе о том Go это язык для решения прикладных задач, а Rust позиционируется как высокоуровневый язык для системного программирования.
Поправка: iota начинается с нуля.
Ваши примеры будут равны:
a == 2^0
b == 2^1
c == 2^2

и

a == 0 * 3
b == 1 * 3
c == 2 * 3
Что до непонятных ошибок, то из того что вспомню вот: is.gd/oNnlG2
Пишет о «unreachable pattern», хотя должен писать о «неизвестном идентификаторе».
Кстати говоря, проблема до сих пор открыта :)

Короче говоря, хватит тут демагогию разводить, так и быть спишем на бету. Вот выйдет первый стабильный релиз, вот тогда можно и разводить :D
Да, конкретно эта проблема довольно известна. Как мне кажется, её очень здорово решили в Scala — идентификаторы в паттерне, начинающиеся с маленькой буквы, всегда обозначают байндинги, а с большой — сравнение с конкретным значением. Но в Rust такой подход вряд ли прокатит, хотя бы потому что нет возможности эскейпить произвольные строки для использования как идентификаторов.
Весьма распространено заблуждение о том, что Go — это замена C++, в каждом обсуждении Rust кто-нибудь такое говорит. Go — не язык для системного программирования, у них с C/C++ и Rust совершенно разные нишы.

Это не заблуждение. Go родился именно из-за проблем С++ и как замена C++.

Ниши у Rust и Go не абсолютно одинаковые, но во многом пересекающиеся. Подходы разные — Go вырос из практических соображений и опыта, Rust — аккумулирует теоретические достижения PLT.
Нет, это не так. Go не является заменой C++ даже близко — он гораздо ближе по области применения к языкам вроде Python и Erlang. В частности, Go не является языком системного программирования, в частности, из-за рантайма и сборщика мусора, которые хоть и можно отключить, но без которых язык становится практически бесполезен. Насколько я помню, сами авторы писали, что жалеют, что называли его «systems programming language».
Я отталкиваюсь от двух вещей, когда говорю про Go как замену С++:
1) Чисто исторический факт, описанный в официальном блоге Golang — язык Go решили создать именно из-за недовольства С++, после внутренней презентации С++0Х.
2) Для меня лично Go стал именно заменой С++. Там где нужна работа с «системой» и производительность — раньше я использовал С++, просто потому что не было приемлимой альтернативы. Go заменил мне С++ полностью: я бы использовал C++ только в продуктах, где необходимо выжимать каждую наносекунду и это в намного большем приоритете, чем скорость разработки или читабельность кода. Во всех остальных случаях, причин писать новые проекты на С++, а не на Go я не вижу.

Поэтому да, с вашим определением «системного языка» как «языка без рантайма» я не согласен.
Это не моё определение. Отсутствие рантайма — необходимое условие для языка системного программирования. Вот определение с википедии:

A system programming language usually refers to a programming language used for system programming; such languages are designed for writing system software, which usually requires different development approaches when compared to application software.

System software is computer software designed to operate and control the computer hardware, and to provide a platform for running application software. System software includes software categories such as operating systems, utility software, device drivers, compilers, and linkers.


Два ключевых элемента — операционные системы и драйверы — на Go писать абсолютно непрактично, именно из-за того, что в Go многие фичи языка основаны на рантайме, который использовать в ОС/драйверах не получится. Безусловно, вы можете отключить рантайм и писать драйверы, и получится это гораздо легче, чем, например, на Java — но Go для этого не предназначен, и поэтому это будет просто пожирание кактуса. И именно поэтому Go не является заменой C++. А Rust — пусть и потенциально, но является, потому что он изначально проектировался практичным для тех областей, где используется C++, и он отлично работает даже на голом железе, что подтверждается проектами вроде zinc.rs.

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

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

Соглашусь, хотя под «низкоуровневостью» тут имеется ввиду, наверное, контроль памяти? Все таки одна из главных претензий к С++ была именно в том, что слишком большая часть дизайна языка посвящена именно контролю памяти.

Мой же поинт в том, что «драйвера» и по-настоящему «низкоуровневый код» — это достаточно узкая сфера и сводить к ней «нишу С++» не совсем корректно. Прикладной серверный/сетевой софт, который еще 5 лет назад, действительно почти без вариантов стоило писать только на С++, сейчас гораздо эффективнее писать на Go.
Именно поэтому, кстати, практически все новые проекты в SaaS/PaaS маркете пишутся именно на нём.
Под низкоуровневостью подразумевалось программирование в окружении с точным контролем над ограниченными ресурсами — в том числе, памятью. Скажем, программирование реалтаймовых систем.

Мой же поинт в том, что «драйвера» и по-настоящему «низкоуровневый код» — это достаточно узкая сфера и сводить к ней «нишу С++» не совсем корректно.

В том-то и дело — уже давно C++ используется либо в легаси-проектах, либо там, где нужна производительность (та самая «низкоуровневость», условно). В других областях он уже давно вытеснен более подходящими языками, и Go — только один из них. Повторюсь, именно поэтому когда говорят об «убийце C++», подразумевают язык, который способен вытеснить C++ из самых основных оставшихся ниш.
Хм, может я что-то упускаю, но кто вытеснил C++ в GUI приложениях?
Эм, языки более высокого уровня и JavaScript в браузере? GUI-программы под винду пишутся в основном на .NET-платформе, под линукс и кроссплатформенные — да, здесь пока альтернативы Qt и GTK нет. Под iOS и OS X пишут на Objective C, но это, во-первых, не C++, во-вторых, vendor lock-in, а в третьих — недавно появился Swift. Но таких программ подавляющее становится всё меньше и меньше по сравнению с веб-приложениями.
Есть Qt Quick, есть Vala, есть PyQt/PySide… Есть тот же node-webkit. Много вариантов последнее время появилось.
Go это скорее замена Си99 чем С++.
Так же он тяготеет к Python/Erlang но это только маскировка.

И ИМХО современный C++ куда приятнее Go…
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории