Решение на Code Identifier от Николай Данаилов
Към профила на Николай Данаилов
Резултати
- 19 точки от тестове
- 0 бонус точки
- 19 точки общо
- 14 успешни тест(а)
- 1 неуспешни тест(а)
Код
Лог от изпълнението
Compiling solution v0.1.0 (/tmp/d20190123-22631-168kzbp/solution)
Finished dev [unoptimized + debuginfo] target(s) in 6.42s
Running target/debug/deps/solution-2e785d603b538f71
running 4 tests
test tests::is_valid ... ok
test tests::parse_words ... ok
test tests::titlecase_word ... ok
test tests::titlecase_word_cyrillic ... ok
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Running target/debug/deps/solution_test-29808948fb50ed3a
running 15 tests
test solution_test::test_both_static_and_dynamic_strings ... ok
test solution_test::test_camelcase_basic ... ok
test solution_test::test_cyrillic1 ... ok
test solution_test::test_digits1 ... ok
test solution_test::test_digits2 ... ok
test solution_test::test_digits3 ... ok
test solution_test::test_kebabcase_basic ... ok
test solution_test::test_multibyte_uppercase ... FAILED
test solution_test::test_normalize_case1 ... ok
test solution_test::test_normalize_case2 ... ok
test solution_test::test_screaming_snakecase_basic ... ok
test solution_test::test_titlecase_basic ... ok
test solution_test::test_underscore_basic ... ok
test solution_test::test_validity ... ok
test solution_test::test_whitespace ... ok
failures:
---- solution_test::test_multibyte_uppercase stdout ----
thread 'solution_test::test_multibyte_uppercase' panicked at 'assertion failed: `(left == right)`
left: `"someSpecialCase"`,
right: `"someSSpecialCase"`', tests/solution_test.rs:104:5
note: Run with `RUST_BACKTRACE=1` for a backtrace.
failures:
solution_test::test_multibyte_uppercase
test result: FAILED. 14 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
error: test failed, to rerun pass '--test solution_test'
История (9 версии и 8 коментара)
Николай качи решение на 20.10.2018 18:53 (преди около 7 години)
Николай качи решение на 20.10.2018 18:55 (преди около 7 години)
Николай качи решение на 21.10.2018 09:11 (преди около 7 години)
Николай качи решение на 21.10.2018 09:38 (преди около 7 години)
Николай качи решение на 21.10.2018 09:39 (преди около 7 години)
Николай качи решение на 21.10.2018 09:41 (преди около 7 години)
Николай качи решение на 21.10.2018 09:44 (преди около 7 години)
match statement-а е мощен инструмент, но си заслужава да се използва, когато if-else не стига, или е по-тромав. В случая на булева стойност, по-четимо ще е, включително за хора, които не са супер запознати с езика, да си е if-клауза това.
Това е смислен начин, да. split ще ти върне итератор към &str, понеже, в зависимост от това какво правиш, може да ти е достатъчно. В твоя случай... Е, би могло да ти бъде достатъчно при малко по-различна структура, но е ок да алокираш низове. Ще говорим скоро за lifetimes и за боравене с псевдоними вместо с owned типове.
Можеш да опростиш малко кода като избегнеш първия collect: identifier.split('_').map(|s| s.to_string()).collect().
Хм, впрочем в този конкретен случай, кода се компилира totally fine и без да алокираш низове:
fn split_identifier(identifier: &str) -> Vec<&str> {
identifier.split('_').collect()
}
Успях доста да опростя кода тук, особено като осъзнах и че to_lowercase директно ми връща String. Беше ми малко объркващо кога точно се използва &str и кога String, но май придобих интуиция донякъде. Малко се обърках, но казваш, че може да се мине без пазене на String и съответно без взимане на ownership? Идеята ми беше, че отвън ми се подава &str, но искам после да имам думите като String, защото този външния &str не се знае до кога ще живее и т.н. Даже не знам дали е възможно да се мине без да пазя String въобще, а да ги пазя като &str. Не съм пробвал. Така си го представям, пък не съм сигурен дали е съвсем вярно.
Може да се пази &str в случая, но трябва да се ползват lifetimes, което ще е ужасно объркващо. Още повече, че в тази конкретна задача, аз бих обработил низа преди да го запазя, което все пак би изисквало ownership, но това е друга тема.
Засега е напълно ок да държиш String-ове. Ще говорим още доста за приемането и връщането на reference types скоро (може би не идващата седмица, а тази след нея).
Добра работа, харесва ми и че си си имплементирал собствени тестове, винаги е чудесна идея да си валидираш assumption-ите.
Едно генерално нещо, което бих те посъветвал, е да не слагаш експлицитен тип на всичко. В някои отношения е по-експлицитно, съответно по-ясно, но в други те ограничава -- може би rust би успял да ти алокира Vec<&str>, но тъй като си поискал Vec<String>, кода няма да се компилира. А и самия код става доста verbose.
Другия проблем е, че в някои ситуации, самия тип може да стане доста сложен, особено като стигнем до анонимни функции. Пробвай да провериш какъв е типа на .map(|s| s.to_string()), например :).
Конвенцията в Rust е да изпускаме type annotations, освен ако не са задължителни. Това има хубавото качество, че ако видиш експлицитен type annotation, това комуникира с теб, че е бил задължителен по една или друга причина.
Даже имам и още десетина integration теста, но качих само този файл. :D
Усетих се, че май става малко прекалено експлицитното указване на типове, но исках като за първо домашно да го направя така - да придобия представа кои неща какво връщат точно и т.н.
.map видях, че връща някакъв итератор std::iter::Map. Обаче не ми стана много ясно защо този итератор е по-специален, а не е просто std::iter::Iterator или там какъвто е нормалния итератор.
Николай качи решение на 21.10.2018 16:47 (преди около 7 години)
Тцъ, не връща просто std::iter::Map, връща (примерно) std::iter::Map<std::slice::Iter<'_, std::string::String>, [closure@src/lib.rs:90:46: 90:63]>. (Тоест, Map<тип-на-итератора-до-момента, тип-на-функцията>.) Типа [closure@src/lib.rs:90:46: 90:63] е конкретния тип на конкретната анонимна функция, дефинирана на конкретния ред/колона в сорса :). Това буквално няма как да го напишеш на ръка.
Има си начин да се работи с нещо такова, казва се impl Trait, и вероятно скоро ще говорим за него.
За другото - да, няма никакъв проблем да експериментираш, особено в домашните. Препоръчвам го даже, стига решението да минава :).

matchstatement-а е мощен инструмент, но си заслужава да се използва, когато if-else не стига, или е по-тромав. В случая на булева стойност, по-четимо ще е, включително за хора, които не са супер запознати с езика, да си е if-клауза това.