Мой раст становится лучше
Oct. 20th, 2022 02:46 pmЗадача: конвертация из числа в roman numerals:
Ключевое know-how: Возвращать reference'ы на &'static [u8], который на самом деле кусок будущей строки и использовать "байтовые строки" для констант (b"str_content").
Не то, чтобы это был Trait Science, но любые другие выкрутасы с String или Vec<char> были бы куда более уродливыми или неэффективными. А тут я беру и возвращаю указатели на статические строки (которые и так и так у меня в .data будут), и из них мирно собираю строку. Точнее, я собираю в [u8], которую потом копирую в String.
Возможно, вместо while можно было бы иметь итератор, но я не уверен в выполнимости этого.
Ещё одно место "думать" - в районе extend_from_slice, т.к. я могу вызывать несколько реаллоакций в процессе 'extend', а мне по-хорошему надо было бы знать длину строки с самого начала. Но это отдельная интересная задача - определить размер строки для roman numeral по числовому значению.
impl Solution {
fn next_biggest(num: i32) -> (&'static [u8], i32) {
match num {
1000.. => (b"M", 1000),
900.. => (b"CM", 900),
500.. => (b"D", 500),
400.. => (b"CD", 400),
100.. => (b"C", 100),
90.. => (b"XC", 90),
50.. => (b"L", 50),
40.. => (b"XL", 40),
10.. => (b"X", 10),
9.. => (b"IX", 9),
5.. => (b"V", 5),
4.. => (b"IV", 4),
1.. => (b"I", 1),
_ => unimplemented!("Unable to represent in Roman")
}
}
pub fn int_to_roman(mut num: i32) -> String {
let mut acc = Vec::new();
while num > 0{
let (rom, value) = Self::next_biggest(num);
acc.extend_from_slice(rom);
num -= value;
}
String::from_utf8(acc).unwrap()
}
}
Ключевое know-how: Возвращать reference'ы на &'static [u8], который на самом деле кусок будущей строки и использовать "байтовые строки" для констант (b"str_content").
Не то, чтобы это был Trait Science, но любые другие выкрутасы с String или Vec<char> были бы куда более уродливыми или неэффективными. А тут я беру и возвращаю указатели на статические строки (которые и так и так у меня в .data будут), и из них мирно собираю строку. Точнее, я собираю в [u8], которую потом копирую в String.
Возможно, вместо while можно было бы иметь итератор, но я не уверен в выполнимости этого.
Ещё одно место "думать" - в районе extend_from_slice, т.к. я могу вызывать несколько реаллоакций в процессе 'extend', а мне по-хорошему надо было бы знать длину строки с самого начала. Но это отдельная интересная задача - определить размер строки для roman numeral по числовому значению.
no subject
Date: 2022-10-21 09:32 am (UTC)Мне синтаксис с диапазонами очень нравится. Вместе с exhaustive match - просто огонь.
Насчёт "отдельная функция или нет", я со своего опыта программирования и чтения своего/чужого кода спустя 2-3 года, могу сказать, что если ты стоишь перед выбором написать компактнее или что-то назвать, выбирай вариант с названием. Названия - те же комменты, только живые, и это главное хорошее, что после себя может оставить программист своим читателям.
no subject
Date: 2022-10-26 04:21 am (UTC)Название не заменяет комментарии, а только создает иллюзию этого. Еще хуже, если оно приводит к очень длинным названиям, которые ни туда ни сюда - и замучаешься запоминать и отличать, и объяснять ничего не объясняет. Но главная моя претензия - в том, что вынос кода в одноразовую функцию нарушает последовательность чтения. При чтении кода приходится прыгать к определению функции и потом назад. И это еще хорошо, если читать в vi, в котором можно поставить метку и и потом прыгнуть назад к ней. А в тех редакторах, где нет меток - еще хуже.
no subject
Date: 2022-10-26 12:51 pm (UTC)Я не совсем понимаю твоего возмущения. Range - это законный тип в Rust, очень прикольный. Ты можешь его даже в переменную сохранить. Это тип данных, а не "специальный сахар для match".
https://doc.rust-lang.org/std/ops/struct.Range.html
В языке есть синтаксис для задачи значений Range, но он ничем не более "сахар", чем возможность задавать float'ы в native виде, или array в виде перечисления.
Насчёт имён я строго с тобой не соглашусь. Если у нас есть имя, это имя - фрагмент смысла. Если имена не важны, то и имена переменных тоже не важны. c(i(j), k[l][m(n)]) и всё такое.
no subject
Date: 2022-10-29 04:45 am (UTC)> Если имена не важны, то и имена переменных тоже не важны. c(i(j), k[l][m(n)]) и всё такое.
Для кратковременно используемых переменных в мнемонических типовых применениях типа параметра цикла - да, это самые правильные имена.