рджрд┐рд╕рдВрдмрд░ рдореЗрдВ рд╡рд╛рдкрд╕, рдореИрдВ рдЕрдВрдЧреНрд░реЗрдЬреА рдореЗрдВ рдПрдХ рдмрд┐рд▓реНрдХреБрд▓ рдЙрд▓реНрд▓реЗрдЦрдиреАрдп рд▓реЗрдЦ рдХреЗ рд▓рд┐рдП рдЖрдпрд╛ рдерд╛, рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреА рд╡рд┐рд╢реНрд╡рд╕рдиреАрдпрддрд╛ рдмрдврд╝рд╛рдиреЗ рдФрд░ рд░реАрдлреИрдХреНрдЯрд░рд┐рдВрдЧ рдореЗрдВ рдЖрд╕рд╛рдиреА рдХреЗ рд▓рд┐рдП, рднрд╛рд╖рд╛ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреА рдкреНрд░рдгрд╛рд▓реА рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдкрд┐рдд рдерд╛ред рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдЙрд╕ рд╕рдордп рдореИрдВ рд╡рд╛рдпреБрд╕реЗрдирд╛ рдкрд░ рд▓реЗрдЦ рд▓рд┐рдЦрдиреЗ рдореЗрдВ рдмрд╣реБрдд рд╡реНрдпрд╕реНрдд рдерд╛, рдЬрд┐рд╕реЗ рд▓рд┐рдЦрдирд╛ рдмрд╣реБрдд рдорд╣рддреНрд╡рдкреВрд░реНрдг рдерд╛, рдЬрдмрдХрд┐ рдпрд╛рджреЗрдВ рдЕрднреА рднреА рддрд╛рдЬрд╛ рд╣реИрдВред рд▓реЗрдХрд┐рди рдЕрдм, рдЬрдм рдореИрдВрдиреЗ рдЗрд╕ рдХрд╛рд░реНрдп рдХреЛ рдкреВрд░рд╛ рдХрд┐рдпрд╛, рддреЛ рдореИрдВ рдЕрдВрдд рдореЗрдВ рдЗрд╕ рдЕрджреНрднреБрдд рдиреЛрдЯ рдХрд╛ рдЕрдиреБрд╡рд╛рдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реЛ рдЧрдпрд╛ред рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреА рдореВрд▓ рднрд╛рд╖рд╛ рд╣рд╛рд╕реНрдХреЗрд▓ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рджрд░реНрд╢рдХреЛрдВ рдХреА рд╡реНрдпрд╛рдкрдХ рдкрд╣реБрдВрдЪ рдХреЗ рд▓рд┐рдП рдЙрдиреНрд╣реЗрдВ рдПрдХ рд░реИрд╕реНрдЯ рдореЗрдВ рдХреЙрдкреА рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдпрд╣рд╛рдВ рдХреА рднрд╛рд╖рд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдорд╣рддреНрд╡рд╣реАрди рд╣реИ, рдЗрд╕ рд▓реЗрдЦ рдХреА рдпреБрдХреНрддрд┐рдпрд╛рдВ рдореИрдВ рджреИрдирд┐рдХ рд╡рд┐рдХрд╛рд╕ рдореЗрдВ рдкреВрд░реА рддрд░рд╣ рд╕реЗ "рд╕рд╛рдВрд╕рд╛рд░рд┐рдХ" рд╕реА # рдФрд░ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдкрд░ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ, рдЗрд╕рд▓рд┐рдП рдпрджрд┐ рдЖрдк рдмрд╕ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рдФрд░ рд╕рдорд░реНрдерд┐рдд рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ, рднрд╛рд╖рд╛ рдХреА рдкрд░рд╡рд╛рд╣ рдХрд┐рдП рдмрд┐рдирд╛, рд▓реЗрдЦ рд╡рд┐рд╖рдп рдореЗрдВ рд╣реЛрдЧрд╛ред
рдкреНрд░реВрдлрд░реАрдбрд┐рдВрдЧ рдФрд░ рдЕрдиреБрд╡рд╛рдж рд╕рд╣рд╛рдпрддрд╛ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред Hirrolot, funkill рддрдерд╛ andreevlex

рд╕рдордп рдХреА рдПрдХ рд▓рдВрдмреА рдЕрд╡рдзрд┐ рдореЗрдВ, рдореИрдВ рдпрд╣ рд╕рдордЭрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдЯреАрдХ, рд╕рд░рд▓ рддрд░реАрдХрд╛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрдШрд░реНрд╖ рдХрд┐рдпрд╛ рдХрд┐ рдЯрд╛рдЗрдк-рдбреНрд░рд┐рд╡реЗрди рдбрд┐рдЬрд╝рд╛рдЗрди рдХреНрдпрд╛ рд╣реИ ( рдЗрд╕рдХреЗ рдмрд╛рдж - рдЯрд╛рдЗрдкрдбреАрдбреА, рд▓рдЧрднрдЧред рдЯреНрд░рд╛рдВрд╕ред )ред рдХрд╛рдлреА рдмрд╛рд░ рдЙрдиреНрд╣реЛрдВрдиреЗ рдореБрдЭрд╕реЗ рдкреВрдЫрд╛ рдХрд┐ "рдЖрдк рдЗрд╕ рддрд░рд╣ рдХрд╛ рдирд┐рд░реНрдгрдп рдХреИрд╕реЗ рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВ?", рд▓реЗрдХрд┐рди рдореЗрд░реЗ рдкрд╛рд╕ рдХреЛрдИ рд╕рдВрддреЛрд╖рдЬрдирдХ рдЬрд╡рд╛рдм рдирд╣реАрдВ рдерд╛ред рдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдПрдХ рджреГрд╖реНрдЯрд┐ рдХреЗ рд░реВрдк рдореЗрдВ рдирд╣реАрдВ рдЖрдпрд╛ рдерд╛: рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рдкреБрдирд░рд╛рд╡реГрддреНрдд рдбрд┐рдЬрд╛рдЗрди рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдереА рдЬреЛ рдореБрдЭреЗ "рд╕рд╣реА" рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╛рдзреНрдп рдирд╣реАрдВ рдХрд░рддреА рдереА, рд▓реЗрдХрд┐рди рдЕрднреА рддрдХ рдореИрдВ рджреВрд╕рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреА рд╡реНрдпрд╛рдЦреНрдпрд╛ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдирд╣реАрдВ рд╣реВрдВред
: JSON , , . , , , TypeDD, , , :
, .
TypeDD
, : TypeDD, , , . , . , , , .
, , , " ?". :
enum Void {}
fn foo(x: i32) -> Void
? , тАФ , .. Void
тАФ , , Void
. , , :
fn head<T>(xs: Vec<T>) -> T
. ? , - , , :
fn head<T>(xs: Vec<T>) -> T {
match xs.as_slice() {
[x, ..] => *x
}
}
error[E0004]: non-exhaustive patterns: `&[]` not covered
--> src/lib.rs:2:11
|
2 | match xs.as_slice() {
| ^^^^^^^^^^^^^ pattern `&[]` not covered
|
, , , . , , []
, . , .. , , , ! , , , ( , . .).
- . , . , " " - , . head
, , .
, head
, .. : , . , : . , , , , : , , . Rust Option
:
fn head<T>(xs: Vec<T>) -> Option<T>
, head
тАФ None
, , T
:
fn head<T>(xs: Vec<T>) -> Option<T> {
match xs.as_slice() {
[x, ..] => Some(*x),
[] => None,
}
}
, ? , тАФ тАж .
Option
, , , head
. . head
None
, , . , :
fn get_configuration_directories() -> Result<Vec<String>, &'static str> {
let config_dirs_string = std::env::var("CONFIG_DIRS").map_err(|_| "cannot read env")?;
let list: Vec<_> = config_dirs_string.split(',').map(|x| x.to_string()).collect();
if list.is_empty() {
return Err("CONFIG_DIRS cannot be empty");
}
Ok(list)
}
fn main() -> Result<(), &'static str> {
let config_dirs = get_configuration_directories()?;
match head(config_dirs) {
Some(cacheDir) => initialize_cache(cacheDir),
None => panic!("should never happen; already checked config_dirs is non-empty")
}
Ok(())
}
get_configuration_directories
, . head
main
, , Option<&str>
None
, , , ! :
-, . , , ?
-, . , , , , , .
, , . , get_configuration_directories
, , , ? , main
, "" , .
. None
, get_configuration_directories
.
, , .
, head
, . , - : , , head
, , , . ?
() head
.
fn head<T>(xs: Vec<T>) -> T
, . , , : ( тАФ Vec<T>
). , head
.
, , .
, NonEmptyVec
. :
struct NonEmptyVec<T>(T, Vec<T>);
, NonEmptyVec
тАФ T
(, ) Vec<T>
. , Vec<T>
[]
, . , head
:
fn head<T>(xs: NonEmptyVec<T>) -> T {
xs.0
}
, , , , . :
fn get_configuration_directories() -> Result<NonEmptyVec<String>, &'static str> {
let config_dirs_string = std::env::var("CONFIG_DIRS").map_err(|_| "cannot read env")?;
let list: Vec<_> = config_dirs_string.split(',').map(|x| x.to_string()).collect();
match non_empty(list) {
Some(x) => Ok(x),
None => Err("CONFIG_DIRS cannot be empty")
}
}
fn main() -> Result<(), &'static str> {
let config_dirs = get_configuration_directories()?;
initialize_cache(head(config_dirs));
Ok(())
}
, main
! , get_configuration_directories
. NonEmptyVec
Vec
non_empty
, :
fn non_empty<T>(list: Vec<T>) -> Option<NonEmptyVec<T>>
, Option
, None
: . , NonEmptyVec
, ( !) , . , NonEmptyVec
Vec<T>
, .
head
, :
, .
, get_configuration_directories
, . , main
, !
, head
, non_empty
:
fn old_head<T>(xs: Vec<T>) -> Option<T> {
non_empty(xs).map(head)
}
, : head
. , .
? , тАФ , , . , : , , . :
fn validate_non_empty<T>(xs: Vec<T>) -> Result<(), UserError> {
if !xs.is_empty() {
Ok(())
} else {
Err(UserError::new("list cannot be empty"))
}
}
fn parse_non_empty<T>(mut xs: Vec<T>) -> Result<NonEmptyVec<T>, UserError> {
if !xs.is_empty() {
let head = xs.remove(0);
Ok(NonEmptyVec(head, xs))
} else {
Err(UserError::new("list cannot be empty"))
}
}
: , , . : validate_non_empty
()
, , , parse_non_empty
NonEmptyVec<T>
, , . , parse_non_empty
, validate_non_empty
.
: validate_non_empty
, parse_non_empty
, . , parse_non_empty
, , ", ". parse_non_empty
. - , ? , , , , parse_non_empty
, .
: ? , , , . , тАФ тАФ , - . , , , parse_non_empty
: , .
: , , , ! Rust , :
: . - -, , . , , , , , .
, , : , . : - , . , NonEmpty
: , .
, , , . , ? , , , ?
, . Ad-hoc , - . 2016 The Seven Turrets of Babel: A Taxonomy of LangSec Errors and How to Expunge Them :
тАФ , , , ; , ( - ), "" .
, :
, . , - , .
, , , , , , , . тАФ , , , тАФ .
, тАФ , , . , , , , "" . , , .
, : , , , . , .
, ,
, . ", , !", , , . "" "", "".
: .
, , , , , - . тАФ , , :
fn check_no_duplicate_keys<K: Eq, V>(xs: &[(K,V)]) { ... }
"" тАФ : . - , , , . , , , HashMap
. , HashMap
, , .
, , , , , . - , HashMap
. , , , . check_no_duplicate_keys
:
fn check_no_duplicate_keys<K: Eq, V>(xs: &[(K,V)]) -> HashMap<K,V> { ... }
, !
:
, . , . , , .
, . , . , , , .
, . - , .
, , , , . , , - . , - !
, :
, . bool
, ( , , . .). , тАФ , , ,
Result<(), Error>
. , - , , .
. , , , , , , . тАФ -.
, , : .
, " " . , , , , , . (newtype)
, - .
, . , error "impossible"
- тАФ , , . , , .
, -. , , тАФ ! , .
. , тАФ " " тАФ . , , , . , тАФ ! тАФ . , тАФ .
, , : Type Safety Back and Forth. , . Ghosts of Departed Proofs, , , .
, , , . , тАФ , . , TypeDD, , , , . , , . , тАФ .
, тАФ , .