LINUX.ORG.RU

Продемонстрирована возможность разработки частей Linux на Rust

 , ,


4

9

Французский программист написал статью, в которой рассмотрел возможность переписывания ядра Linux на Rust.

В статье отмечено, что данный язык хорошо подходит для системного программирования, будучи достаточно низкоуровневым и при этом лишённым многих недостатков C, и уже используется для написания новых ОС. Однако автор не считает создание ОС с нуля перспективным для серьёзного применения, и последовательный перенос отдельных частей Linux на Rust для решения различных проблем безопасности кажется ему более целесообразным.

В качестве «Proof of Concept» была приведена реализация системного вызова, содержащая вставки на Assembler внутри unsafe-блоков. Код компилируется в объектный файл, не связанный с библиотеками и интегрируемый в ядро во время сборки. Работа производилась на основе исходного кода Linux 4.8.17.

>>> Статья



Проверено: Shaman007 ()
Последнее исправление: sudopacman (всего исправлений: 5)

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

А в следующем докладе чел реализовал трейты из раста на шаблонах в C++ :)

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

в C/C++ программист делает работу программиста, если чётко представляет, как и что работает «под капотом». Такие языки.

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

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

Ну, в этом случае, отстаивая своё мнение, я уси$%№&^ся не буду. Однако, спецификации Раста, это не более, чем ещё один уровень абстракции, описатель, введённый в надежде на то, что так можно чётче заявить свои намерения. В реальном мире «железа», спецификации Раста соответствия не имеют.

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

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

багов и сегфолтов, из них процентов 90 словил бы раст еще на этапе написания кода

Не только Раст.

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

Утомление будет от поиска сегфолтов в многопоточном приложении на C/C++.

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

Какие ещё критические области? Плазма падает - и всех это бесит. Но WM ни разу не является критической областью.

Именно такие. «Плазма падает» (у кого падает), обычно, именно что из-за видеодрайверов.

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

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

Это правильно в конкретном мире программирования «железа». Просто не надо забивать все гвозди микроскопом.

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

В реальном мире «железа», спецификации Раста соответствия не имеют.

Любые конструкции Раста почти 1 к 1 маппятся на ЛЛВМовский SSA,который проще любого ассемблера.

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

Но есть неожиданное поведение.
Раст тут ничем не поможет.

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

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

Для справки мой код иллюстрировал приведение типов в С и... более ничего.

Очень странный способ иллюстрировать приведение типов. Тем более, для Си, который изначально проектировался, как максимально скрывающий возможности железа. В Си можно выразить ЛЮБУЮ манипуляцию данными, имеющими смысл с точки зрения системы команд процессора. По определению, иллюстрировать тут нечего.

В частном случае перевод кода в строку и обратно это возможность передать строку по сети или сохранить в файл

В Си это делается по-другому. Вы же проиллюстрировали именно передачу на исполнение содержимого произвольной области памяти. Зачем?

Код это данные, а данные могут быть кодом.

В *общем* случае, это неверно: то, что работает в архитекутре фон Неймана, не обязано работать в других. Даже на совершенно фон-Немановском x86... это может не работать. В любом случае, возможность выразить такие манипуляции тем, или иным способом, характерна для любого «системного» языка. Например, для бывшего одно время конкурентом Си языка PL/M.

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

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

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

...«Из далека, видать наверняка. Издалека мы видим дурака. И умного, порою, шлём подальше, Чтоб разглядеть того издалека»...

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

извиняюсь, следует читать «минимально скрывающий возможности железа»

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

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

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

То, что современные программисты это часто даже не подозревают, совсем другой вопрос.

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

Неправильно разрешать приводить тип (const char *) к типу (char *)

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

(*) например, область памяти/регистр, по получению некоторых условий, переводится из r/o в r/w.

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

Элементарный пример - запусти программу, скомпиленую на системе с текущей кодировкой IBM-866, на системе с текущей кодировкой UTF-8.

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

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

На свете нет языка проще, чем C.

Есть. Классический basic, например.

Так же как нет языка более низкоуровневого!

Есть. Любой продвинутый (структурный) ассемблер.

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

Ну и в каком ЯП константы занимают память?

Хе.

Есть *константы*, а есть *литералы*. И то, и другое, вообще говоря, константы. Но первое математическая абстракция, а второе --- очень даже в памяти.

Так вот, во времена первых компиляторов, любые(!) константы *всегда* становились литералами. Так было проще.

Препроцессор в Си позволил изящно этого избежать.

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

когда создавался Си и его препроцессор, неявно предполагалось две вещи:

1) машинных ресурсов мало и они дорогие

2) программист НЕ идиот и не злонамеренное чмо.

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

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

бррр...

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

Тогда и на чистом Си код будет... чистый.

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

и где наконец-то есть композиция вместо ООП

ой, как интересно!

А если вспомнить бесконечные статьи дцатилетней давности («используйте наследование! это совсем не так дорого, как кажется! композиция зло!»)... :)

И кстати, чего это вдруг противопоставление композиции и ООП?

(которое на самом деле не очень-то и ООП).

с чего бы вдруг?

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

Кстати код получился все равно не эквивалентным, твой успешно парсит текст в котором есть только одна строка, и в v2 кладет 0. А в моем примере это возвращает ошибку.

э... с чего бы?

unittest failure ---------------- ??:? _d_unittest [0x44daf0] ??:? void testpar02.__unittest_fail(int) [0x44bf56]

Например к коду из этой статьи (http://dlang.org/blog/2017/05/24/faster-command-line-tools-in-d/) можно написать не намного больший по количеству кода аналог на Rust, который будет работать почти в два раза быстрее

не читал, надо разобраться

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

Любые конструкции Раста почти 1 к 1 маппятся на ЛЛВМовский SSA

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

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

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

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

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

Так вот, во времена первых компиляторов, любые(!) константы *всегда* становились литералами. Так было проще.

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

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

э... с чего бы?

А с того бы, ты что, входную строку поменял, а тест не поменял?

Добавляем снизу к твоему коду:

int main(string[] args)
{
        Data data;
        writeln(fun(data, "Hello"));
        writeln(data);
        return 0;
}
И смотрим что получится:
Tuple!(bool, "ok", string, "what")(false, "")
Data("Hello", 0)
Я не вижу тут сообщения об ошибке

А у меня добавляем строку

println!("{:?}", parse("Hello"));
И она печатает:
Err("failed to parse value2")

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

И кстати, чего это вдруг противопоставление композиции и ООП?

Всё из-за проблем связанных с наследованием, не трудно найти критику ООП и сравнение композиции vs наследования в сети. Или Вы таки хотите много копипасты в треде?

(которое на самом деле не очень-то и ООП).

с чего бы вдруг?

Ну с того что все объекты должны общаться сообщениями в ООП и отвечать или не отвечать на сообщение, решает объект которому это сообщение отправили. А мы имеем по факту структуры с приватными полями и публичными методами которые дёргают все кому не лень - это по Вашему ООП?

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

Ну с того что все объекты должны общаться сообщениями в ООП и отвечать или не отвечать на сообщение, решает объект которому это сообщение отправили.

С чего бы вдруг? Потому что Алан Кей так думает?

А мы имеем по факту структуры с приватными полями и публичными методами которые дёргают все кому не лень - это по Вашему ООП?

Таки да, ООП. И оно такое уже лет 50.

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

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

В то время как раст заставит человека проверить что вернул iterator.next() и придется явно написать что тебе нужно, вернуть ошибку или значение по-умолчанию.

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

С чего бы вдруг? Потому что Алан Кей так думает?

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

Таки да, ООП. И оно такое уже лет 50.

Так в том то и прикол, что такое ООП не даёт ни какого преимущества. И вообще выглядит как костыль.

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

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

ООП для динамически-типизированных языков очень сильно отличается от ООП для статически-типизированных языков. Попробуйте представить, как мантра любителей ООП от Кея ляжет на статически-типизированные языки, вроде упомянутого здесь C++. Как должна выглядеть отсылка сообщения, отвечать или не отвечать на которое выбирает получатель, в статически-типизированном языке? Как это все дружит с производительностью (видели ли вы когда-нибудь бенчмарки SmallTalk-а или хотя бы Ruby)?

Так в том то и прикол, что такое ООП не даёт ни какого преимущества.

Ну да, ну да.

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

в C/C++ программист делает работу программиста, если чётко представляет, как и что работает «под капотом». Такие языки.

Вот я об этом и говорю, что в Rust о таких проблемах думать не надо.

излишнее утомление => ошибки.

Утверждение явно неверно в сравнении Rust с С/С++.

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

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

Писать платформо-зависимый код, это призывают адепты С языков? Может ты тоже пытаешься дискредитировать С/С++ программистов?

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

В то время как раст заставит человека проверить что вернул iterator.next() и придется явно написать что тебе нужно, вернуть ошибку или значение по-умолчанию.

Тут вспоминается история с checked exceptions из Java. ЕМНИП, в середине 90-х Java стал первым из мейнстримовых языков, в которых эта фича появилась. Причем под вполне себе обоснованным соусом: мол, так разработчики озаботятся тем, чтобы соблюдались контракты, чтобы было понятно, что вылетает из метода и т.д. и т.п.

По факту же checked exceptions настолько быстро всех задолбали и запутали, что было написано множество слов о том, как правильно использовать checked exceptions, но на практике это приводило к совершенно разным вариантам говнокода и упрощения себе жизни в реальных проектах:

- тупое проглатывание исключений, которые не соответствуют спецификации исключений метода;

- неумелое преобразование одних исключений в другие;

- злоупотребление RuntimeException и преобразованием исключений в RuntimeException;

- написание спецификации исключений только из throws Exception.

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

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

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

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

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

Тут вспоминается история с checked exceptions из Java.

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

А если данные нужны и обработать ошибку хочется, то это можно сделать намного удобнее чем ловить исключения, тот же оператор `?` не только делает `if err != nil return err` как в Go, но и умеет автоматически конвертировать одни виды ошибок в другие, чтобы человек не тратил на это усилия.

массово начнут использовать обычные Рафшаны с Джумшутами

Для того чтобы сэкономить время и наговнокодить есть специальный метод `.unwrap()` который кинет panic (обычный unchecked exception).

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

Ну и есть разница между «Человек знал что тут может быть ошибка и написал затычку» и «Человек даже не догадывался что такое может произойти»

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

На самом деле тут есть большая разница, в расте ошибка не сама по себе, а привязана к данным.

Я думаю, вы меня не поняли. Не суть важно, к чему привязана ошибка. В Rust-е вас заставляют писать что-то вроде v.value_or(bla-bla-bla) точно так же, как в Java заставляют писать:

public void someMethod() throws SomeStupidException {
  try {
    doSomething();
  }
  catch(ActualExceptionNotRelatedToStupidException x) {
    ... // Some action to make compiler happy.
  }
}
И вот когда разработчик вынужден думать, нужно ли ему написать value_or или unwrap только для того, чтобы компилятор оказался довольным, разработчик будет идти по пути наименьшего сопротивления.

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

Как должна выглядеть отсылка сообщения, отвечать или не отвечать на которое выбирает получатель, в статически-типизированном языке? Как это все дружит с производительностью (видели ли вы когда-нибудь бенчмарки SmallTalk-а или хотя бы Ruby)?

Это вопрос к разработчикам компиляторов. Знаю, что программы медленные на SmallTalk. Однако, то что сейчас называют ООП от этого лучше не стало. Как только мы имеем множественное наследование или проблемы с иерархией, то начинаются бесконечные рефакторинги - вот и всё.

Так в том то и прикол, что такое ООП не даёт ни какого преимущества.

Ну да, ну да.

Ну покажите мне хоть одно исследование в котором ООП имеет преимущество хотя бы перед структурным программированием?

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

Знаю, что программы медленные на SmallTalk.

Т.е. связать это с динамической природой SmallTalk-а ума уже не хватает?

Однако, то что сейчас называют ООП от этого лучше не стало.

Вообще-то называть это ООП начали еще до того, как Алан Кей занялся разработкой SmallTalk-а. Посмотрите на Simula конца 1960-х (в Wikipedia есть примеры) — это уже то, с чем люди имеют дело в статически-типизированных языках семейства C++/Java/C#.

Можно, конечно, весь этот опыт не замечать и упарываться верой в слова Кея о том, что придумывая ООП он не имел в виду C++. Только когда Кей придумывал свой ООП, ООП уже был. Вот ведь.

Ну покажите мне хоть одно исследование

Простите, я не теоретик.

в котором ООП имеет преимущество хотя бы перед структурным программированием?

Если смотреть на ООП как на развитие структурного и модульного программирования, то ваш вопрос теряет смысл.

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

И вот когда разработчик вынужден думать, нужно ли ему написать value_or или unwrap только для того, чтобы компилятор оказался довольным, разработчик будет идти по пути наименьшего сопротивления.

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

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

#[macro_use] extern crate quick_error;

quick_error! {
    #[derive(Debug)]
    pub enum ParseError {
        Value1 { description("failed to parse value1") }
        Value2 { description("failed to parse value2") }
        Number(err: std::num::ParseIntError) {
            from()
            cause(err)
            description(err.description())
        }
    }
}

Вместо строк использовать тип-ошибку.

pub fn parse<'a>(input: &'a str) -> Result<Data<'a>, ParseError> { // '
    let mut lines = input.lines();
    let first = lines.next().ok_or(ParseError::Value1)?;
    let second = lines.next().ok_or(ParseError::Value2)?;
    let data = Data {
        value1: first.trim(),
        value2: second.trim().parse()?,
    };
    Ok(data)
}

Касательно unwrap, то это отличный способ быстрого проектирования, в нём нет ничего страшного. К тому же он не всегда короче.

let value = "10".parse().unwrap();
let value = "10".parse()?; // нормальная обработка ошибок в Rust
numas13
()
Ответ на: комментарий от numas13

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

Вы, как и RazrFalcon, пытаетесь приписать мне то, что я не говорил. Пока что в данной теме я вроде бы не говорил о том, что у C++ есть в этом плане какие-то преимущества над Rust-ом.

Все растоманы такие нежные и обидчивые?

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

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

Поэтому мне интересно, что будет в Rust-е со временем, когда там львиную долю кода будут писать Рафшаны с Джумшутами.

Если в этом интересе такие нежные натуры, как вы и RazrFalcon видите наезд на Rust, то уж не знаю. Может пора розовые очки снять?

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

Ну ты сравнил конечно, в джаве разница между checked/unchecked исключениями это 0 байт кода против 10 строк кода, очевидно что выберет человек.

В то время как в расте разница такая уже и большая. А если ты особо ленивый джамшут то есть базовый тип `Box<Error>` в который конвертируется любая ошибка, и тогда твой код будет даже короче чем без обработки ошибок.

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

Вы, как и RazrFalcon, пытаетесь приписать мне то, что я не говорил. Пока что в данной теме я вроде бы не говорил о том, что у C++ есть в этом плане какие-то преимущества над Rust-ом.

Я вам ничего не приписывал, не надо искать подвох там, где его нет. Вы сказали, что программист идёт по пути наименьшего сопротивления. Я представил, что можно сказать про С/С++, следуя вашей логике. К чему столько агрессии?

Все растоманы такие нежные и обидчивые?

Мне не понятно, с чего вы это взяли из моего предложения.

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

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

Поэтому мне интересно, что будет в Rust-е со временем, когда там львиную долю кода будут писать Рафшаны с Джумшутами.

Поживём — увидим. Будем надеяться, что они будут следовать привычному пути в Rust.

Если в этом интересе такие нежные натуры, как вы и RazrFalcon видите наезд на Rust, то уж не знаю. Может пора розовые очки снять?

Я (опять) не понимаю, что я сделал, что вы записали меня в список своих врагов, может стоит немного по умерить свой пыл?

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

Вы сказали, что программист идёт по пути наименьшего сопротивления. Я представил, что можно сказать про С/С++, следуя вашей логике

В C++ нет каких-то известных мне преимуществ в обработке ошибок перед Rust-ом. Ну и как-то странно кивать на C/C++ обсуждая Rust, который a) гораздо моложе и b) создавался с тем, чтобы устранить проблемы C/С++. Так что зачем было поминать C++ в этом контексте вообще не понятно.

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

Мой поинт был вот в чем: сейчас жесткость Rust-а (т.е. тот факт, что Rust заставляет разработчика выбирать между возвратом Result<R, E> и вызовом value, или между возвратом R и вызовом value_or) преподноситься как большое преимущество. Точно так же checked exception в Java преподносились как большое преимущество. Только со временем они стали мешаться и новые языки на JVM от checked exception просто отказались.

Как бы не случилось так, что одно из _нынешних_ преимуществ Rust-а со временем не стало таким же камешком в ботинке, как checked exceptions в Java.

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

В C++ нет каких-то известных мне преимуществ в обработке ошибок перед Rust-ом. Ну и как-то странно кивать на C/C++ обсуждая Rust, который a) гораздо моложе и b) создавался с тем, чтобы устранить проблемы C/С++. Так что зачем было поминать C++ в этом контексте вообще не понятно.

Я и написал, что давайте не будем об этом. Я же знаю, что вас понесёт понесло.

Мой поинт был вот в чем: сейчас жесткость Rust-а (т.е. тот факт, что Rust заставляет разработчика выбирать между возвратом Result<R, E> и вызовом value, или между возвратом R и вызовом value_or) преподноситься как большое преимущество.

Нет, возврат ошибки, это обработка ошибки. unwrap/etc игнорирование. В первом мы продолжаем исполнения, обработка зависит от вызывающей стороны. Во втором мы просто падаем. Они не эквивалентны! Их сравнение, это большая ошибка, которая вводит вас в ложные рассуждения.

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

Нет, возврат ошибки, это обработка ошибки. unwrap/etc игнорирование. В первом мы продолжаем исполнения, обработка зависит от вызывающей стороны. Во втором мы просто падаем. Они не эквивалентны! Их сравнение, это большая ошибка, которая вводит вас в ложные рассуждения.

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

Программист может написать что-то вроде:

pub struct Data<'a> {
    value1: &'a str,
    value2: u32,
}

pub fn parse<'a>(input: &'a str) -> Result<Data<'a>, &'static str> {
    let mut lines = input.lines();
    let first = lines.next().ok_or("failed to parse value1")?;
    let second = lines.next().ok_or("failed to parse value2")?;
    let data = Data {
        value1: first.trim(),
        value2: second.trim().parse().map_err(|_| "failed to parse a number")?,
    };
    Ok(data)
}
А может и что-то вроде:
pub struct Data<'a> {
    value1: &'a str,
    value2: u32,
}

pub fn parse<'a>(input: &'a str) -> Data<'a> { // '
    let mut lines = input.lines();
    let first = lines.next().unwrap_or("empty input!");
    let second = lines.next().unwrap_or("0");
    let data = Data {
        value1: first.trim(),
        value2: second.trim().parse().unwrap_or(0),
    };
    Ok(data)
}

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

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

Т.е. связать это с динамической природой SmallTalk-а ума уже не хватает?

О мы уже переходим на личности?! Может мне тебя дибилом для равновесия назвать? SmallTalk в любом случае не будет быстрее Си, но если бы его развивали последние 50 лет, то возможно он был бы быстрее жабы.

Вообще-то называть это ООП начали еще до того, как Алан Кей занялся разработкой SmallTalk-а. Посмотрите на Simula конца 1960-х (в Wikipedia есть примеры) — это уже то, с чем люди имеют дело в статически-типизированных языках семейства C++/Java/C#.

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

Если смотреть на ООП как на развитие структурного и модульного программирования, то ваш вопрос теряет смысл.

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

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

О мы уже переходим на личности?! Может мне тебя дибилом для равновесия назвать?

Мне-то пофиг, а у вас ни ума, ни знаний не прибавится.

SmallTalk в любом случае не будет быстрее Си

Ну так ответьте самому себе: почему? И, заодно, как-таки обмен сообщениями ложится на статически-типизированные языки.

если бы его развивали последние 50 лет, то возможно он был бы быстрее жабы.

Если бы у бабушки был... Ну вот наследника SmallTalk, язык Ruby, развивают-развивают, а до Java как до Пекина раком.

И ООП тогда ещё не называли ни как.

Как-то это не мешало ООП существовать.

Если мне не изменяет память, то в НАСА как раз проводили такое исследование.

Можно на него взглянуть?

Следует ли теперь из Ваших чудесных умозаключений, что в НАСА нет смысла?

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

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

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

Checked exceptions.

fn run(...) -> Result<Data, MyError> { ... }
public Data run(...) throws MyException0, MyException1, ... { ... }

unwrap

fn run(...) -> Data {
   ...
   foo().unwrap();
   ...
}
public Data run(...) {
    ...
    try {
        foo();
    } catch (SomeException e) {
        System.out.println(e.getMessage());
        System.exit(-1);
    }
    ...
}

unwrap_or

fn run(...) -> Data {
    ...
    let x = foo().unwrap_or(0);
    ...
}
public Data run(...) {
    ...
    int x = 0;
    try {
        x = foo();
    } catch (SomeException e) {

    }
    ...
}

Повторю, Rust не заставляет вас выбирать между возвратом Result или unwrap. Единственный верный вариант для обработки ошибки — это возврат Option/Result. unwrap — игнорирование.

unwrap_or/unwrap_or_default — это логика программы. unwrap_or — если ошибка, то использовать другое значение. unwrap_or_default — если ошибка, то использовать значение по-умолчанию.

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

И да пардон, это не НАСА, это

This research was funded by IBM. The document preparation was supported by Lockheed Martin Energy Research

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

Повторю, Rust не заставляет вас выбирать между возвратом Result или unwrap. Единственный верный вариант для обработки ошибки — это возврат Option/Result. unwrap — игнорирование.

Я понял почему мы не можем найти общий язык. Вы прямо проводите аналогию между checked exceptions в Java и способами использования Result в Rust-е. Но я о другом.

Еще раз: в Java под соусом улучшения и более строгого контроля были добавлены checked exceptions. В теории они должны были работать хорошо. На практике это оказался один из самых спорных механизмов языка, от которого в современных языках для JVM (Scala, Ceylon, Kotlin и др.) просто отказались. Поскольку он не дал серьезных преимуществ на практике.

Теперь забываем про сами checked exceptions. Помним только про некую фичу, которую добавили в язык ради блага, а получилось как всегда.

Вот повсеместное использование Result-а в Rust-е так же со стороны выглядит как фича, которую добавили в язык ради блага. Но когда смотришь код на Rust-е, то выясняется, что разработчику приходится очень много внимания уделять этому самому Result-у. Там, где в другом языке можно было бы вернуть Data, в Rust-е нужно возвращать Result<Data, ...>. Там, где в другом языке можно сделать простую цепочку вызовов, в Rust-е нужно обмазываться try! или новым ?. Там, где в других языках просто берется и используется возвращенное значение, в Rust-е нужно делать какой-то вариант match-а. Ну и все эти unwrap_or/unwrap_or_default и пр.

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

Может быть, при написании низкоуровневого кода так и следует делать. Но если брать задачи чуть повыше (например, MQ-брокеры, сервера СУБД, какие-то CAD системы), то в них уже ситуация может быть другой. Откуда и соблазн свести работу с Result-ами к самому минимуму.

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

Да пожалуйста http://www.csm.ornl.gov/~v8q/Homepage/Papers Old/spetep- printable.pdf

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

Я вам сходу могу привести примеры, скажем, из C++. Если вы будете на C++ задачи из области вычислительной математики решать (причем даже не из области линейной алгебры), то ООП вам там вообще вряд ли пригодится. Скорее даже попытка с помощью ООП писать код для методов конечных разностей приведет к обратному эффекту.

А вот если вы на C++ будете делать сложное десктопное приложение, типа CAD-а, то без ООП (хотя бы в виде библиотеки уровня MFC/wxWidgets/Qt) далеко не уедите. Это уже было хорошо показано в 1980-х и 1990-х.

Тоже самое: попробуйте написать какой-нибудь парсер языка программирования на Java или на OCaml-е или Haskell-е. ООП вам здесь вряд ли сильно поможет. Что не отменяет преимуществ ООП в других областях.

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