Решение на 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
, и вероятно скоро ще говорим за него.
За другото - да, няма никакъв проблем да експериментираш, особено в домашните. Препоръчвам го даже, стига решението да минава :).
match
statement-а е мощен инструмент, но си заслужава да се използва, когато if-else не стига, или е по-тромав. В случая на булева стойност, по-четимо ще е, включително за хора, които не са супер запознати с езика, да си е if-клауза това.