LINUX.ORG.RU

Чтение из UTF-8 файла в массив на языке Rust

 ,


0

5

Господа, имеется такой код:

use std::fs::File;
use std::io::BufReader;
use std::io::prelude::*;

fn main() {
    let args : Vec<String> = std::env::args().collect();
    if args.len() < 2 {
        println!("Wrong! Use: {} filename", args[0]);
        return;
    }
    
    let file_name = args[1].to_string();
    let input_file = match File::open(&file_name) {
        Ok(file) => file,
        Err(_) => {
            println!("File {} not found.", file_name);
            return;
        }
    };

    let mut reader = BufReader::new(input_file);

    let mut buf = [0u8; 512];
    loop {
        let length = reader.read(&mut buf).ok().unwrap();
        if length == 0 {
            break;
        }
        let _s = match std::str::from_utf8(&buf[0..length]) {
            Ok(string) => string,
            Err(e) => panic!("{}", e),
        };  
    }

}

Проблема в том, что в файлах вперемешку идут символы разной ширины (ASCII и кириллица), поэтому иногда в буфер знак целиком не влезает и я получаю что-то вроде:

thread '<main>' panicked at 'invalid utf-8: invalid byte near index 511'

Собственно вопрос: как эффективно разрулить эту ситуацию? Дочитывать по байту, пока декодирование не пройдёт успешно? Или использовать что-то ещё?

Решение такого типа:

let mut s = std::string::String::new();
    loop {
        let length = reader.read_to_string(&mut s).ok().unwrap();
        if length == 0 {
            break;
        }
    }
не подходит, файл может быть очень большой, нужно экономить память. То же самое касается и read_line.

★★★

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

Раст, в общем-то, «язык общего назначения», как и большинство мейнстримовых языков.

Он гарантированно не будет таковым. Массы не воспримут ограниченный язык с маргинальным синтаксисом.

Как?

Как в том же питоне. Там ты не получишь 100 * 100 = 0.

И как из этого следует необходимость инициализировать аккумулятор вызовом какой-то левой функции?

Ну если писать только код подобный пример на rust-lang, то может необходимости нет. А если нужно рассчитать смещение в файле, например, то удобно сразу же добавить длину сигнатуры, BOM etc. Аналогично, если рассчитывать статистику и пр.

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

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

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

Он гарантированно не будет таковым.

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

Массы не воспримут ограниченный язык с маргинальным синтаксисом.

Ограниченный чем? А синтаксис там не хуже С++/D.

Как в том же питоне. Там ты не получишь 100 * 100 = 0.

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

А если нужно рассчитать смещение в файле, например, то удобно сразу же добавить длину сигнатуры, BOM etc.

Hормальные функции будут возвращать результат типа isize (аналог size_t) и проблемы не будет. Или можно подстраховаться и задать тип аккумулятору - тогда при неправильном типе вылезет ошибка компиляции.

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

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

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

А синтаксис там не хуже С++/D.

С С++ согласен, но ты на D то писал? Или только на картинке видел?

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

но ты на D то писал? Или только на картинке видел?

Каюсь, серьёзно не писал. Читал книгу Александреску, ну и так баловался немного. Но честно говоря, не вижу принципиальной разницы. Да, местами покрасивее/поудобнее, хотя сейчас уже местами и в С++ лучше, например, со строковыми литералами.

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

Опять же, в D, при желании, можно перегружать всякие «экзотические» операторы - >>>, ^^= и т.д. То есть, при желании, тоже можно всяких ужасов наделать.

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

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

Решать «широкий спектр задач» можно хоть на ассемблере. Вот только он под это не заточен. Как и rust. К примеру, много ли ты знаешь популярных «языков общего назначения», которое не имеют поддержки сколько-нибудь юзабельного ООП? По сути только С. А без GC? Только С и С++. Это два языка, которые вынужденно и достаточно долго приходилось использовать как языки общего назначения. Потому они и успели закрепиться, С++ в том числе выехал за счет совместимости с С, а С за счет того, что это по сути база почти любой ОС, от ядра и драйверов до библиотек. Rust же такой форы не имеет. Потому и смысла запихивать его в какой-нибудь вэб, скрипты, гуй и т.п. - нет. С и С++ он тоже не может полноценно заменить, так что никакой он не «язык общего назначения», а язык для написания достаточно сложного ядра сервера, СУБД, браузера etc. И то посмотрим как там servo - взлетит или нет. Если нет, то на языке можно будет ставить крест. А то и два или четыре ;)

Ограниченный чем? А синтаксис там не хуже С++/D.

Да всем практически. GC нет, ООП нет, CTFE нет, дженерики не ровня шаблонам из С++ или дженерикам C#, семантики перемещения нет, перегрузки функций нет, параметров по умолчанию нет, рефлексии нет, исключений нет и т.д. Вообще если взять C# или D, например, то они порвут по фичам rust. Насчет синтаксиса, для тебя - да, для многих (и это видно даже по ЛОРу) - нет.

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

Дык в том то и дело, что толку то от статической типизации в данном случае, если ты типы не указываешь.

Hормальные функции будут возвращать

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

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

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

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

Решать «широкий спектр задач» можно хоть на ассемблере.

Ты правда считаешь, что разницы нет?

Как минимум, всякие делфи/паскали были достаточно популярны и без ГЦ при этом. Обжектив С тоже, по сути, без ГЦ (был, но выпилили), пришедший ему на замену swift аналогично.

И да, некоторые зачем-то пишут сайты и на С++.

GC нет, ООП нет, CTFE нет, дженерики не ровня шаблонам из С++ или дженерикам C#, семантики перемещения нет, перегрузки функций нет, параметров по умолчанию нет, рефлексии нет, исключений нет и т.д.

Отсутствие ГЦ - это, в данном случае, достоинство. Иначе, язык был бы ещё менее нужен. Ну и забавно пенять на отсутствие ГЦ и указывать при этом на С++.

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

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

И не ты ли говорил, что перегрузка есть, но на трейтах?

Дык в том то и дело, что толку то от статической типизации в данном случае, если ты типы не указываешь.

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

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

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

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

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

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

Как минимум, всякие делфи/паскали были достаточно популярны и без ГЦ при этом.

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

Обжектив С тоже, по сути, без ГЦ (был, но выпилили), пришедший ему на замену swift аналогично.

ООП, кроме того там GC заменен на ARC, а не просто выпилен.

Отсутствие ГЦ - это, в данном случае, достоинство. Иначе, язык был бы ещё менее нужен. Ну и забавно пенять на отсутствие ГЦ и указывать при этом на С++.

Я и не писал, что С++ умеет все перечисленное (хотя тот же GC там уже готовят). Поинт был в том, что rust не богат возможностями. Его главная фича - безопасность работы с памятью. Так она уже 20 лет как есть в Java, лет 60 в лиспах и т.п. А еще там есть GC, ООП и другие плюшки, в том числе инструменты. Rust как более продвинутая замена С? Тоже нет, поезд ушел, Линус не бросится переписывать ядро, RedHat glibc, gtk и т.п. Да, есть мозилловцы, которые тянут rust по понятным причинам, но если посмотреть на servo (которое всего лишь нужно было грамотно скопировать с готового кода), то в текущем виде оно крайне тормознуто, примитивно и криво. При том, что ес-но никто не собирался переписывать сишные libssl, libfreetype и пр., в том числе и движок JS, который в servo, как минимум пока остался на С++.

Вот демонстрация текущих результатов:

https://www.youtube.com/watch?v=pZGhnqtXVdc

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

И не ты ли говорил, что перегрузка есть, но на трейтах?

Так это не полноценная перегрузка, тем более не перегрузка функций как таковых.

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

Еще раз повторюсь, rust не входит в категорию «почти везде», rust пытается быть в категории «мы надежней чем С и С++, но при том практически так же быстры».

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

Слив? Детский сад, можешь хоть 20 засчитывать. А расшифровка простая - информация о формате может лежать в структуре, предположим там есть нужное поле в u8 (ну не надо больше, и вообще структура описывает реальный заголовок в памяти, так в С принято для удобства делать), кто в трезвом уме сделает геттер для него с другим типом?

которую ты придумал вообще не зависит от языка

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

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

Делфи выехал на ООП

В расте ООП есть, просто (пока что) «немного другое». Вот сделают возможность наследовать данные (или делегировать реализацию трейта члену структуры) и будет совсем обычное ООП.

ООП, кроме того там GC заменен на ARC, а не просто выпилен.

И? В расте тоже есть RC. К тому же, я не считаю, что раст не ООП язык.

Я и не писал, что С++ умеет все перечисленное (хотя тот же GC там уже готовят)

Формально реализации уже есть, вот только ими не особо пользуются. В расте аналогично, более того, ГЦ там даже был, но от него избавились оставив возможность реализовать не прибивая язык к нему гвоздями.

Поинт был в том, что rust не богат возможностями. Его главная фича - безопасность работы с памятью. Так она уже 20 лет как есть в Java, лет 60 в лиспах и т.п.

Если уж и говорить так, то фича в «безопасности без ГЦ». Так что конкурентов как раз не особо много.

Тем не менее, фичи в расте вполне есть. Удобные модули, паттерн матчинг и алгебраические типы данных, «всё выражение», нормальные и мощные макросы и т.д. Большинства из этого в С++ или нет или криво или «„скоро“ будет».

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

Вот демонстрация текущих результатов:

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

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

Еще раз повторюсь, rust не входит в категорию «почти везде», rust пытается быть в категории «мы надежней чем С и С++, но при том практически так же быстры».

Это ты так думаешь. Есть и вот такие штуки. Значит кому-то оно надо.

Опять же, я работаю с С++ кодом, где auto дофига. И если такая тенденция есть в куче языков, то я не понимаю почему ей не следовать в С++/расте. Оно и правда удобно.

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

Зависит от того какой смысл мы в метод вкладываем. Если тупо геттер, то да. Если именно «вернуть смещение», то почему бы и нет? Опять же, я не совсем понимаю логику. Ок, в поле лежит смещение типа u8 и «его хватает». Тогда, по логике, если мы выйдем за границы, то уже что-то пошло не так. И при чём тут раст?

Ну как же, в питоне проблемы нет, в java проблемы нет и т.д.

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

В расте можно включить (и в релизе) проверки переполнения в нужных местах, если есть опасения.

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

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

Ну собственно, моё мнение следующее: раст довольно удобен. Да, есть объективно «недоделанные» вещи, но язык-то продолжает развиваться. В каком-нибудь C# 1.0 тоже мало всего было. Есть и «спорные моменты», но тоже не смертельно.

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

В расте? Где искать такое (гугл не помог)?

rustc --pretty

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

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

Хм, когда я пытал гугл, мне было ответом, что --pretty — это для дебага, а rustfmt — это пока мечты.

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

В расте ООП есть
В расте тоже есть RC
...

Окай.

Разве они сами не говорят, что серво получается куда быстрее?

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

Это ты так думаешь. Есть и вот такие штуки. Значит кому-то оно надо.

Это ровно та самая ниша, о которой я писал выше, - сервера, СУБД и т.п. Впрочем таких вещей уже огромное кол-во понаписано, на самых разных языках. Точно так же и на D тут кто-то пиарил:

http://vibed.org

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

Ок, в поле лежит смещение типа u8 и «его хватает». Тогда, по логике, если мы выйдем за границы, то уже что-то пошло не так. И при чём тут раст?

Не смещение, а размер сигнатуры. Его действительно хватает.

Если тип фиксированного размера, то будет

Потому-что тип явно указан будет.

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

Хм, когда я пытал гугл, мне было ответом, что --pretty — это для дебага, а rustfmt — это пока мечты.

Тем не менее, оно вполне работает (только что проверил). Раньше к их онлайн компилятору тоже прикручено было, сейчас что-то не вижу.

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

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

Они какие-то тесты приводят. Думаешь нагло врут?

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

Потому-что тип явно указан будет.

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

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

Они какие-то тесты приводят. Думаешь нагло врут?

Почему сразу врут - «Most benchmarks seem to be overly focused on JS engine performance». И вот чудеса, JS то у них на С++ остался, зато видно обвязка еще недоделанная и неполноценная, вот тебе и прирост в скорости. А как оно работает с обычными страницами, а не синтетикой, видно на видео.

anonymous
()

Ну и говнищеее...... Ааааааааааааааааааааааааааааааа

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

Потому что C++ идеален для своих задач и еще один C++ - не нужен?

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

Это CTFE-то в rust'е нет? А чем тебе плагины к компилятору не CTFE? Причём это гораздо мощнее крестового шаблонного метапрограммирования или constexpr. Вот такие ништяки позволяет делать: https://github.com/crabtw/rust-bindgen

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

А чем тебе плагины к компилятору не CTFE?

Всем. С libclang тоже можно много чего сделать.

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

этож костыль.

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

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

Ты по ходу даже на офсайте не был.

Был, но то, что ты имеешь ввиду, не аналог того, что есть в плюсах. Это скорее аналог RVO. А вот как ты сделаешь такое:

string append( string&& a, char b )
{
    a.push_back( b );
    return move( a );
}

string append( const string& a, char b )
{
    string r = a;
    r.push_back( b );
    return r;
}

Чтоб при вызове функции автоматом использовалась оптимизация, если можно.

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

А вот как ты сделаешь такое:

В расте нет перегрузки функций. Но вообще пример слишком искусственный и «странный», правильно оно будет вот так:

fn append(a: &mut String, b: char)
{
    a.push(b);
}

fn append_copy(a: &str, b: char) -> String {
    let mut res = a.to_string();
    res.push(b);
    res
}

Это скорее аналог RVO

Нет. Вот это, по твоему, RVO?

let a = vec![1, 2, 3];
let b = a; // move
let c = b; // move

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

Но вообще пример слишком искусственный

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

правильно оно будет вот так:

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

Вот это, по твоему, RVO?

Если говорить про данный «искусственный» ;) пример, то это вообще просто переименовывание локальной переменной, а не передача владения значением из одного места в другое.

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

Но вообще пример слишком искусственный и «странный»

Что в нем странного? Вызываем функцию для добавления, при этом в случае временных объектов у нас не будет копирования. Так же имеем возможность явно указать, что у объекта забираем данные. В rust возможно только последнее. Но ведь и первое так же важно.

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

Если на входе обычная ссылка - копируем. Профит.

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

Вот только «правильно» практически никто писать не будет.

Да ладно? Посмотри, например, на Boost String Algorithms - там везде, где есть смысл как раз по две функции - инплейс и возвращающие копию. Как раз потому, что удобно.

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

Это вообще о чём? Нормальный (с передачей по ссылке) аппенд ещё и оптимальнее твоего будет. А уж вызвать нужную функцию, в зависимости от ситуации, с этим и обезьяна справится.

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

Признай уже, что был не прав с перемещением в расте.

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

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

В rust возможно только последнее.

С какой стати?

fn append(mut a: String, b: char) -> String {
    a.push(b);
    a
}

let a = append(str, 'e'); // move
let a = append(str.clone(), 'e'); // copy
Только из-за того, что семантика перемещения по умолчанию, указывать надо именно явное копирование.

Что в нем странного?

Потому что это как-то не слишком оптимально? По крайней мере, я с такими функциями нечасто сталкивался. Обычно всё-таки используют ссылки.

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

Не читай другие ответы, вот идиоматический вариант: http://is.gd/hR5xzf . Rust отличается от C++ тем, что в нем передача по значению всегда работает через move, и если чтобы передать копию, нужно явно создать ее через метод clone, и передать по значению уже эту копию. В С++ передача по значению это всегда копирование, а для перемещения нужно определять перегрузки с rvalue references. Т.к. передачу через копирование всегда можно свести к передаче копии по значению, в Rust достаточно одной версии там, где в С++ ты пишешь две.

Очевидный плюс состоит в том, что все вызовы конструкторов копирования у тебя явно видны в коде. В С++ когда ты передаешь вектор в функцию, ты не можешь быть уверен, что он не будет целиком скопирован, не проверив, что вектор принимается по ссылке, т.е. my_fun(v) может подразумевать копирование вектора, а может и нет. В Rust компилятор потребует у тебя в точке вызова либо сделать my_fun(&v) для передачи по ссылке, либо my_fun(v.clone()) для передачи копии, и my_fun(v) всегда означает передачу по значению с move.

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

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

Все можно. Хоть ООП на С. Никто не спорит. И читабельность вполне себе будет. Относительно конечно, но никто еще не умер от чтения кода с GTK, например.

Да ладно? Посмотри, например, на Boost String Algorithms - там везде, где есть смысл как раз по две функции - инплейс и возвращающие копию. Как раз потому, что удобно.

«инплейс и возвращающие копию» - это вообще из другой оперы.

Это вообще о чём? Нормальный (с передачей по ссылке) аппенд ещё и оптимальнее твоего будет. А уж вызвать нужную функцию, в зависимости от ситуации, с этим и обезьяна справится.

Жизнь показывает, что большинство не могут нормально даже две строки сложить оптимально:

Конкатенация строк

Они даже не думают про то, что такое strlen, strcpy, snprintf и т.п. А ты надеешься, что им нужна еще одна оптимальная функция (которая по сути ничего не выиграет по сравнению с rr).

Признай уже, что был не прав с перемещением в расте.

Возможно, но твой пример это никак не показывает.

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

передача по значению всегда работает через move
передачу по значению с move

Lol.

вот идиоматический вариант

Идиоматически будет работать с &str везде, где возможно.

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

Жизнь показывает, что большинство не могут нормально даже две строки сложить оптимально:

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

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

Не читай другие ответы, вот идиоматический вариант: http://is.gd/hR5xzf

Спасибо.

Т.к. передачу через копирование всегда можно свести к передаче копии по значению, в Rust достаточно одной версии там, где в С++ ты пишешь две.

Зато там, где в С++ две версии в реализации, в Rust много правок для вызове.

Очевидный плюс состоит в том, что все вызовы конструкторов копирования у тебя явно видны в коде

Согласен.

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

Вот только если пишут нормальные люди, то они попрофилируют и оптимизируют

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

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

Rust отличается от C++ тем, что в нем передача по значению всегда работает через move, и если чтобы передать копию, нужно явно создать ее через метод clone, и передать по значению уже эту копию.

Не всегда, реализующие типаж `Copy` типы таки копируются.

quantum-troll ★★★★★
()
Ответ на: комментарий от anonymous

но если посмотреть на servo (которое всего лишь нужно было грамотно скопировать с готового кода), то в текущем виде оно крайне тормознуто, примитивно и криво
крайне тормознуто

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

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

Cow из стандартной библиотеки. Сам нагуглишь, не маленький.

Т.е. еще один ручной вариант для захламления кода? Спасибо, не надо.

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

Отрисовка там медленная, расчёт вёрстки же там на порядок быстрее, чем в гекко.

Отрисовать текст + картинки по готовым координатам - плевое дело, которое не может так тупить в принципе, даже если переписать freetype на JS, а картинки выводить на экран попиксельно. Затык там как раз в верстке. Ну в крайнем случае в тугом чтении данных через http, но оно у них тоже на rust.

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

Ты хотя бы определись.

Просто не стоит подменять понятия. В С++ тоже доступен cow (и в libstdc++ даже использовался, хотя почти никто этого не замечал, или в Qt), но это же не то, это библиотечная возможность. Так можно и нормальное ООП на С++ сделать (как GObject, только намного удобней), и тоже сказать - а чо, есть же в С++ ООП как у людей и точка.

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

Шокирующий факт: `Box<T>` — тоже библиотечная возможность!

Это как раз не шокирующий, вот если они GC в библиотеку запихнут - я может и удивлюсь.

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

Я не вижу проблемы в том, чтобы иметь `Cow` как часть библиотеки. У него вполне чёткая семантика, которую так или иначе нужно иметь в виду, реализуется он прямолинейно, а благодаря приведению типов его можно использовать точно так же, как и заимствующую ссылку (пример: http://is.gd/ZOCWZn).

quantum-troll ★★★★★
()
Ответ на: комментарий от anonymous

Кстати в С++ boehmgc, например, используется в Inkscape. Означает ли это, что сам С++ умеет GC? Конечно нет.

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

Я не вижу проблемы в том, чтобы иметь `Cow` как часть библиотек

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

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

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

И это в том числе сказывается на ее использовании.

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

вынужденное изменение оригинального кода, что не так уж и хорошо.

Зато более явно намерения показывает.

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