https://github.com/rust-lang/rfcs/pull/1859 ì Try
í¹ì± ; PR https://github.com/rust-lang/rust/pull/42275 ìì 구íëììµëë€
ëª íì±ì ìíŽ https://github.com/rust-lang/rust/issues/31436 ìì ë¶ëŠ¬í©ëë€(https://github.com/rust-lang/rust/pull/42275#discussion_r119167966ì ë°ëŒ).
Iterator::try_fold
륌 구íí ì ììµëë€.fold
ê° try_fold
êŽì ìì 구íëìŽ ë ë€ ì¬ì ìí íìê° ìëë¡ íë ê²ìŽ ì¢ì ê²ì
ëë€.)ëª ê°ì§ ìì ê±° 볎êŽì:
ì°ëŠ¬ë êŽë š íìê² ì í륌 í¹ì ììì ê°ì§ê³ ììµëê¹ Error
ëì Err
? Err
ëŒê³ íë©Ž Result
ì ì ë ¬ë©ëë€. ë€ë¥ž íëë ìŽë¯ž Ok
ì
ëë€.
ì°ëŠ¬ê° ë³ëì íìì ëí í¹ì ìììŽ ììµëê¹ from_error
ë° from_ok
ëì ì ëšìŒì, ë°©ë²ì from_result
ë ëì¹ ë ê²ìŽëŒê³ into_result
íë ê²ì ë€ë¥ž ê²ì
ëë€ í¹ì±ì ì ë°?
( RFC ì íë ìŽê·žëŒìŽë ë§í¬ ì ë°ìŽíž ë²ì )
@glaebhoerl
Error
ë Err
ë https://github.com/rust-lang/rust/issues/33417#issuecomment -269108968 ë° https:// ìì TryFrom
ì êŽë šíì¬ ë
Œìëììµëë€ . github.com/rust-lang/rust/pull/40281; ë¹ì·í ìŽì ë¡ ì¬êž°ìì ìŽëŠìŽ ì íëìë€ê³ ê°ì í©ëë€.Result
륌 ê°ì§ê³ ìê³ T:Try
ë¡ ë°êŸžë €ê³ íë 겜ì°ë ë묌 ê²ìŒë¡ ììí©ëë€. ëë íì Try::from_result(Ok(
ì Try::from_result(Err(
ížì¶íë ê²ë³Žë€ Try::from_ok
ì Try::from_error
륌 ì ížíë©°, 맀ì¹ë¥Œ ìì±íë ê²ë³Žë€ ë ê°ì§ ë°©ë²ì ê°ëšíê² êµ¬ííê² ëìŽ êž°ì©ëë€. ìë§ë into_result
륌 Into<Result>
ê° ìëëŒ "íµê³Œíìµëê¹? ì€íšíìµëê¹?"ëŒê³ ìê°íêž° ëë¬žìŒ ê²ì
ëë€. í¹ì ì íì ì€ìíì§ ìì 구í ìžë¶ ì¬íìŒë¡ Result
ì
ëë€. (ì ë "ìì° ê°ì¹ ë ì¡°êž° ë°íì ëí ìë¡ìŽ ì íìŽ ììŽìŒ í©ëë€.) ì ìíê±°ë ì¬ê°íê³ ì¶ì§ ììµëë€. ê·žëŠ¬ê³ ë¬žìíì ê²œì° from_error
ê° ?
ëíŽ ë§íë ê²ì ì¢ìí©ëë€ throw
)ìž ë°ë©Ž from_ok
ë ë€ ëìŒí ë°©ë²ìŒë¡ ì¬ì©íë ëì ì±ê³µ ë©í(#41414)ì ëíŽ ìŽìŒêž°í©ëë€.ìŽê²ìŽ ìŽ ëêžì ëí ì¬ë°ë¥ž í¬ëŒìžì§ íì€íì§ ììµëë€. ê·žë ì§ ìì ê²œì° ëŠ¬ëë ì íŽ ì£Œìžì. ì€ë§ìŒëŠ¬:. ìë§ë ìŽê²ì https://github.com/rust-lang/rfcs/pull/1859 ì ììŽìŒ íê³ ëêž êž°ê°ì ëì³€ìµëë€. ì!
Try
ížë ìì ë¶í íê±°ë into_result
ë©ìë륌 ì ê±°íë 겜ì°ê° ìëì§ ê¶êží©ëë€. ëìê² íì¬ Try
ë FromResult
( from_error
ë° from_ok
) ë° IntoResult
( into_result
í¬íš)ì í©ê³Œ ë€ì ë¹ì·í©ëë€ from_error
into_result
).
FromResult
ë ?
ì°ì°ìë¡ ë§€ì° ìžì²Žê³µíì ìž ì¡°êž° ì¢
ë£ë¥Œ ê°ë¥íê² íë©°, ìŽê²ìŽ ìŽ êž°ë¥ì í¬ë¬ ì¬ì© ì¬ë¡ëŒê³ ìê°í©ëë€. IntoResult
ë ìŽë¯ž ì¬ì© ì¬ë¡ë³ ë©ìëë Into<Result>
ë¡ ê¹ëíê² êµ¬íí ì ìë€ê³ ìê°í©ëë€. ëª ê°ì§ ì ì©í ìê° ëëœ ëììµëê¹?
Try
í¹ì± RFC ì ë°ëŒ expr?
ë ë€ì곌 ê°ìŽ ì€íì ì ê±°í ì ììµëë€.
match expr { // Removed `Try::into_result()` here.
Ok(v) => v,
Err(e) => return Try::from_error(From::from(e)),
}
ëŽê° ê³ ë €í ëêž° ë¶ì¬ ìë Future
ë° Option
ì
ëë€.
ë€ì곌 ê°ìŽ struct FutureResult: Future
ëíŽ FromResult
ìì°ì€ëœê² 구íí ì ììµëë€.
impl<T, E> FromResult for FutureResult {
type Ok = T;
type Error = E;
fn from_error(v: Self::Error) -> Self {
future::err(v)
}
fn from_ok(v: Self::Ok) -> Self {
future::ok(v)
}
}
Result::Err
ì ì©ë ë impl Future
ê° íšììì ë°íëë ?
ëí í©ëŠ¬ì ìž êµ¬íì ê°ì íë©Ž ë€ì곌 ê°ìŽ ìì±í ì ììµëë€.
fn async_stuff() -> impl Future<V, E> {
let t = fetch_t();
t.and_then(|t_val| {
let u: Result<U, E> = calc(t_val);
async_2(u?)
})
}
fn fetch_t() -> impl Future<T, E> {}
fn calc(t: T) -> Result<U,E> {}
ê·žê²ìŽ ë°ë¡ ëŽê° ì€ë ìŒì° 구ííë €ê³ íë ê²ìŽê³ Try
ê·žê²ì 못ë°ììµëë€! ê·žë¬ë ì°ëŠ¬ê° 구ííë €ê³ íë ê²œì° íì¬ Try
ì ëíŽ Future
ìë§ë ìŽë€ íì€ ì íìŽ into_result
; íšë, ì°šëš ëë íŽë§ì í ë² íë ê²ìŽ ì ì©í ì ìì§ë§ ìŽ ì€ ìŽë ê²ë 볎ížì ìŒë¡ ì ì©í ê² ê°ì§ ììµëë€. into_result
ì Try
ììŒë©Ž ìì ê°ìŽ ì¡°êž° ì¢
ë£ë¥Œ 구íí ì ììŒë©° Future
륌 Result
ë¡ ë³ííŽìŒ íë ê²œì° ëªšë Try
) ì ì í ë°©ë²ìŒë¡ ë³íí ì ììµëë€(ì°šëší wait
ë©ìë ížì¶, poll_once() -> Result<T,E>
ížì¶ ë±).
Option
ë ë¹ì·í 겜ì°ì
ëë€. ì°ëŠ¬ë 구í from_ok
, from_err
ìì°ì€ëœê² ê°ìŽ Try
í¹ì± RFC ë° ë³í í ì Option<T>
ì Result<T, Missing>
ëšì§ì o.ok_or(Missing)
ëë ížëŠ¬í ë°©ë² ok_or_missing
.
ëììŽ ëꞰ륌 ë°ëëë€!
ëë ìŽ ëªšë ìŒì ë§€ì° ëŠìì ìë ìì§ë§ ìŽë² 죌ë§ì ?
ì _success_ 륌 ëšëœìí€ë €ë 겜ì°ì ëë¹íŽ ë€ì ìì°ì€ë¬ìŽ ìë¯žê° ìë€ë ìê°ìŽ ë€ììµëë€.
fn fun() -> SearchResult<Socks> {
search_drawer()?;
search_wardrobe()
}
ê·žë¬ë ìŽ ê²œì° Try
í¹ì± ë©ìëì ìŽëŠìŽ ë§ì§ ììµëë€.
ê·žë¬ë ?
ì°ì°ìì ì믞륌 íì¥í©ëë€.
try_fold
for rayon ì íë¡í íìŽíí ë Consumer::full()
ë©ìëì ëíŽ Try::is_error(&self)
ê°ì ê²ì ìíìµëë€. (Rayonì ìë¹ìê° êž°ë³žì ìŒë¡ ížì ì€íìŒ ë°ë³µììŽêž° ë묞ì ìŽê²ì ê°ì§ê³ ìì§ë§ ì°ëŠ¬ë ì¬ì í ì€ë¥ë¥Œ ëšëœìí€ê³ ì¶ìµëë€.) ëì Result::is_err()
ížì¶í ì ìëë¡ ì€ê° ê°ì Result<T::Ok, T::Err>
ë¡ ì ì¥íŽìŒ íìµëë€.
ê±°êž°ìì Try::from_result
ê° ê²°êµ T
ë¡ ëìê°êž°ë¥Œ ìíì§ë§ match
ë T::from_ok
ë° T::from_error
맀íëììµëë€. ëìì§ _ììµëë€.
Try
í¹ì±ì from_ok
ë° from_error
ê° íìí ê²œì° ìžì²Ž ê³µíì ìí from_result
ë°©ë²ì ì ê³µí ì ììµëë€. í¹ì ê·ž ë°ëë¡ë. 죌ìŽì§ ììì ëë ë ê°ì§ë¥Œ 몚ë ì ê³µíë 겜ì°ë¥Œ ëŽ
ëë€.
PR #42275ê° ë³í©ëììŒë¯ë¡ ìŽ ë¬žì ê° íŽê²°ëììµëê¹?
@skade ì íì LoopState
ê° ìŒë¶ Iterator
ëŽë¶ì ëíŽ ìííë ê²ê³Œ ê°ìŽ ëšëœ íë¡ë¥Œ ì ìí ì ììµëë€. ìë§ë Try
ê° ì±ê³µìŽë ì€íš ëì "ê³ì ëë ì€ëš"ì ëíŽ ìŽìŒêž°íë€ë©Ž ë ìì°ì€ë¬ìž ê²ì
ëë€.
@cuviper ê²°êµ íìí ë²ì ì Ok
ì í ëë Error
-in-original ì íìŽììµëë€. ëë destructure-and-rebuildê° ì¶©ë¶í ìŒë°ì ìŽê³ ìµì íê° ìëê³ í¹ì±ì ëí ë§ì í¹ë³í ë°©ë²ìŽ íìíì§ ìꞰ륌 ë°ëëë€.
@ErichDonGubler ìŽê²ì ì¶ì 묞ì ìŽë¯ë¡ íŽë¹ ìœëê° ìì ë ëê¹ì§ íŽê²°ëì§ ììµëë€.
겜í ë³Žê³ ì:
ëë ìŽ í¹ì±ì ì€íì ì®êž°ë €ê³ íë ê²ì ìœê° ì¢ì íë€. ì§êž ì¬ë¬ ë² ìŽë€ ìŽì ë¡ë Result
ëí ê³ ì í ë³íì ì ìíê³ ì¶ì§ë§ ê²°êµ Result
륌 ì¬ì©íê² ë ëë§ë€ ëë¶ë¶ Try
구ííêž° ë묞ì ìŒìžì§ ìëì§ ëë
ìì:
Chalk VMì© ì ìë²ìì "ê°ë¥"ì í ëì 결곌륌 ëíëŽë ìŽê±°íì ê°ê³ ì¶ììµëë€. ì¬êž°ìë ë€ ê°ì§ ê°ë¥ì±ìŽ ììµëë€.
enum StrandFail<T> {
Success(T),
NoSolution,
QuantumExceeded,
Cycle(Strand, Minimums),
}
ëë ?
ìŽ ìŽê±°íì ì ì©ë ë "ì±ê³µ"ì íꞰ륌 ìíì§ë§ ë€ë¥ž 몚ë ì€íšë ì쪜ìŒë¡ ì ííìµëë€. ê·žë¬ë Try
í¹ì±ì 구ííë €ë©Ž ì€ë¥ ì¬ë¡ë§ 캡ìííë ìŒì¢
ì "ìì¬" ì íì ì ìíŽìŒ íìµëë€.
enum StrandFail {
NoSolution,
QuantumExceeded,
Cycle(Strand, Minimums),
}
íì§ë§ ìŒëš ìŽ ì íìŽ ììŒë©Ž StrandResult<T>
ë³ì¹ì ë§ë€ ìë ììµëë€.
type StrandResult<T> = Result<T, StrandFail>;
ê·žëŠ¬ê³ ìŽê²ìŽ ëŽê° í ìŒì ëë€.
ìŽì ìŽê²ìŽ ëšìŒ ìŽê±°íì ê°ë ê²ë³Žë€ ë°ëì ëë¹ ë³ŽìŽì§ë ìì§ë§ ìœê° ìŽìíê² ë껎ì§ëë€. ìŒë°ì ìŒë¡ ì륌 ë€ìŽ íšìì ëí 묞ì륌 ìì±í ë 결곌륌 "ok" ë° "error"ë¡ "귞룹í"íì§ ìê³ "ê°ì"ìŒë¡ ë€ìí ê°ë¥ì±ì ëíŽ ìŽìŒêž°í©ëë€. ì륌 ë€ìŽ:
/// Invoked when a strand represents an **answer**. This means
/// that the strand has no subgoals left. There are two possibilities:
///
/// - the strand may represent an answer we have already found; in
/// that case, we can return `StrandFail::NoSolution`, as this
/// strand led nowhere of interest.
/// - the strand may represent a new answer, in which case it is
/// added to the table and `Ok` is returned.
ëŽê° " Err(StrandFail::NoSolution)
ë°íí©ëë€. ìŽê²ì Err
ëŽê° ì¶ê°íŽìŒ íë ìŽ ì±ê°ì ìí°í©ížì²ëŒ ë껎ì§êž° ë묞ì
ëë€.
(ë°ë©Žì íì¬ ì ìë ë
ìê° Try
implì ì°žì¡°íì§ ìê³ ?
ì ëììŽ ë¬Žììžì§ ì ì ìëë¡ ëìì€ëë€.)
ìŽ ê²°ê³Œê° ê·žëŠ¬ ëëŒìŽ ê²ì ìëëŒê³ ìê°í©ëë€. íì¬ Try
impl ì Result
ì ëíìž í목ì ?
륌 ì¬ì©íëë¡ ê°ì í©ëë€. ìŽ ê· ìŒì±ì ì°ì°ìŽ ìëì§ë§ 결곌ì ìŒë¡ Ʞ볞ì ìŒë¡ "ëšì§ Result
"ê° ìë ê²ë€ê³Œ íšê» ?
륌 ì¬ì©íë ê²ì ì±ê°ìê² ë§ëëë€. (ê·ž 묞ì ë Ʞ볞ì ìŒë¡ NoneError
ë°ìíë ê²ê³Œ ëìŒí 묞ì ì
ëë€ -- Option
ì "ì€íš"륌 ëíëŽêž° ìíŽ ì íì ìžìì ìŒë¡ ì ìíŽìŒ í íìê° ììµëë€.)
ëë ëí StrandFail
ê²œì° ë³Žíµì ê²°ê³Œê° ì»ë From::from
ë³íì ìíì§ ììµëë€.
ì°ê²°ë Try::Error
ì íìŽ ì¬ì©ììê² ì§ì ë
žì¶/ì¬ì©ë ì ìŽ ììµëê¹? ìëë©Ž ?
ëìê°ë§ì ìŒë¶ë¡ íìí©ëê¹? íìì 겜ì°, ê·žë¥ "구조ì "ì ì ìíë ì€ì 묞ì ê° íìëì§ ììµëë€ - type Error = Option<Option<(Strand, Minimums)>>
ìŽë ëë . ( enum
ì ìì "ì€íš ì ë°"ì íŽë¹íë 구조륌 íì
íŽìŒ íë ê²ì ì¢ì§ ìì§ë§ ì 첎 ê³µê° API륌 ì¬ì§ê±°íŽìŒ íë ê²ë³Žë€ ë ì±ê°ì ê² ê°ìµëë€.)
ì ë ë°ëŒíì§ ììµëë€. ëŽë¶ ì€ë¥ ííìŽ ìë ì íì ëíŽ Try륌 ì±ê³µì ìŒë¡ 구ííìŒë©° Ok
ë° Error
ê° ëìŒí ì íìž ê²ìŽ ìì°ì€ëœìµëë€. ì¬êž°ìì 구íì 볌 ì ììµëë€: https://github.com/kevincox/ecl/blob/8ca7ad2bc4775c5cfc8eb9f4309b2666e5163e02/src/lib.rs#L298 -L308
ì€ì ë¡ ìŽ ìì ì ìííêž° ìí ìë¹í ê°ëší íšíŽìŽ ìë ê² ê°ìµëë€.
impl std::ops::Try for Value {
type Ok = Self;
type Error = Self;
fn from_ok(v: Self::Ok) -> Self { v }
fn from_error(v: Self::Error) -> Self { v }
fn into_result(self) -> Result<Self::Ok, Self::Error> {
if self.is_ok() { Ok(val) } else { Err(val) }
}
}
ì±ê³µì íê³ ì¶ë€ë©Ž ë€ì곌 ê°ìŽ ìëíŽìŒ í©ëë€.
impl std::ops::Try for StrandFail<T> {
type Ok = T;
type Error = Self;
fn from_ok(v: Self::Ok) -> Self { StrandFail::Success(v) }
fn from_error(v: Self::Error) -> Self { v }
fn into_result(self) -> Result<Self::Ok, Self::Error> {
match self {
StrandFail::Success(v) => Ok(v),
other => Err(other),
}
}
}
구조ì ì íì ì ìíë ê²ì ê°ë¥íì§ë§ ꜀ ì±ê°ì ëëìŽ ëëë€. Self
ì¬ì©í ì ìë€ë ë° ëìí©ëë€. ê·žë° ë€ì StrandResult
ìì Result<_, StrandResult>
ë±ìŒë¡ ë³ííêž° ìíŽ ?
륌 ì¬ì©í ì ìë€ë ê²ì ëìê² ìœê° ìŽìíê² ë껎ì§ëë€.
íë¥í 겜í ë³Žê³ ì, @nikomatsakis! ëë ëí Try
(ë€ë¥ž ë°©í¥ìì) ë¶ë§ì¡±íìµëë€.
TL/DR : FoldWhile
ìŽ ë§ìŽ ë§ë€ê³ ìê°í©ëë€. Break
-vs- Continue
?
íŽìì ëíŽ ìŽìŒêž°íë ëì ê·žê²ì ì€ë¥ ìž¡ë©Žìì.
ë êžžê²:
ëë ?
ê° ë묎 ížëŠ¬íêž° ë묞ì "ì€ë¥"ë³Žë€ "ì±ê³µ"ì ë ê°ê¹ìŽ ê²ì Err
륌 ê³ì ì¬ì©í©ëë€.
try_fold
륌 ì¬ì©íì¬ position
(ë° êž°í ì¬ë¬ ë°ë³µì ë©ìë) Result
(ëŽ ëëë find
Err
ê²ì ì°Ÿë ê² ) ëì Break
ë° Continue
ë³í ìŒë¡ ëë§ì
itertools ìì tree_fold1
륌 ìì±í ë ëŽë¶ íšìê° íì Err
ë°í íë ìŽìí None
ê° Iterator::next()
ì "ì€ë¥" ëŒë ìŽìí ì°ê²° ëê¹ìŽ ìì§ë§ ëìì ëê¹ì§ ëë¬íŽìŒ íêž° ë묞ì fold
ì "ì±ê³µ"ì
ëë€. ìí í . ê·žëŠ¬ê³ ?
(Rust 1.12ìì 컎íìŒíŽìŒ íë¯ë¡ íŽë¹ ìœëìì try!
) 륌 ì¬ì©íì¬ ì¢
ë£ ì¡°ê±Žì ì ííë ê²ìŽ ë§€ì° ížëŠ¬í©ëë€.
ë°ëŒì ë€ë¥ž ê²ìŽ ìëëŒë©Ž Try
ëíŽ ìì±í ì€ëª
ìŽ ì못ëìë€ê³ ìê°íê³ "ì±ê³µ/ì€íš ìŽë¶ë²"ì ëíŽ ìŽìŒêž°íŽìë ìëë©° "ì€ë¥"ìì ì¶ìííŽìŒ í©ëë€.
ëŽê° ìê°í ë ë€ë¥ž ê²ì Try
ëíŽ ìœê° ë¯žì¹ impls륌 ê³ ë €íŽìŒ íë€ë ê²ì
ëë€. ì륌 ë€ìŽ, Ordering: Try<Ok = (), Error = GreaterOrLess>
ë "íšì ìë"ì ê²°í©ëìŽ struct Foo<T, U> { a: T, b: U }
ì ëí cmp
륌 íì©í ì ììµëë€.
fn cmp(&self, other: &self) -> Ordering try {
self.a.cmp(&other.a)?;
self.b.cmp(&other.b)?;
}
ëë ê·žê²ìŽ ì¢ì ì¢ ë¥ì ë¯žì¹ ê²ìžì§ ëì ì¢ ë¥ìžì§ ìì§ ëªšëŠ ëë€.ìì: íì§ë§ ìŒëš ë¬Œê±ŽìŽ ë€ë¥Žë©Ž ê·žê²ë€ìŽ ë€ë¥Žë€ë ê²ì ì ì ìêž° ë묞ì íì€í ì°ìíšìŽ ììµëë€. ê·žëŠ¬ê³ ê·ž ì쪜ì "ì±ê³µ"ìŽë "ì€ë¥"륌 í ë¹íë €ë ìëë ì ë§ì§ ìë ê² ê°ìµëë€.
ëí "ì€ë¥ ë³í"ìŽ ëììŽ ëì§ ìë ë ë€ë¥ž 겜ì°ì
ëë€. ëë ëí ìì "I want ? but it's not error" ìì ìì ì¬ì©í ì ìŽ ììµëë€. ê·žëŠ¬ê³ ê·žê²ì íì€í ì¶ë¡ ì ì¬íì ì ë°íë ê²ìŒë¡ ìë €ì ž ììŒë¯ë¡ 결곌ë¡ë§ ì íëìŽìŒ íë ê²(ëë ì ì¬ì ìŒë¡ ì ê±°ëìŽ .map_err(Into::into)
ìŽì§ë§ ì€í ë¶ê°ë¥í ì ìì)ìžì§ ê¶êží©ëë€.
ížì§: ì, ê·žëŠ¬ê³ "ëŽ ì€ë¥ ì íì ëíŽ Try
륌 구ííë ëì ì€ë¥ì ëíŽ ê³ì 결곌륌 ì¬ì©í©ëë€"ì ëí ëëµìŽ "ì¢ìµëë€. ììí ê²ì
ëë€"ìžì§ ê¶êží©ëë€.
ížì§ 2: ìŽê²ì ìì https://github.com/rust-lang/rust/issues/42327#issuecomment -318923393곌 ë€ëŠ ëë€.
ížì§ 3: Continue
ë³íìŽ https://github.com/rust-lang/rfcs/pull/1859#issuecomment -273985250ììë ì ìë ê² ê°ìµëë€.
ëŽ 2ìŒíž:
ëë @fluffysquirrels ì í¹ì±ì ë í¹ì±ìŒë¡ ë¶í íë ì ìì ì¢ìí©ëë€. íëë ê²°ê³Œë¡ ë³ííêž° ìí ê²ìŽê³ ë€ë¥ž íëë 결곌ìì ë³ííêž° ìí ê²ì
ëë€. ê·žë¬ë ëë ì°ëŠ¬ê° ëìê°ë§ì ìŒë¶ë¡ into_result
ëë ìŽì ììíë ê²ì ì ì§íŽìŒ íë€ê³ ìê°í©ëë€. ê·žëŠ¬ê³ ìŽ ìì ìì Option
륌 Try
ìŽí ìì íëìŽìŒ íë€ê³ ìê°í©ëë€.
ëë ëí @scottmcm ì ì€ë¥/íìžìŽ ìë ì€ëš/ê³ìì ì ìíë ìŽëŠì ì¬ì©íë ììŽëìŽë¥Œ ì¢ìí©ëë€.
ì¬êž°ì í¹ì ìœë륌 ë£ìŒë €ë©Ž ë€ì곌 ê°ìŽ ìœë ê²ìŽ ì¢ìµëë€.
ë¬Œë¡ ì§ì 룚íë§íŒ ì¢ì§ë ìì§ë§ "ë°©ë² ìë"륌 ì¬ì©íë©Ž ê°ê¹ìµëë€.
self.try_for_each(move |x| try {
if predicate(&x) { return LoopState::Break(x) }
}).break_value()
ë¹êµë¥Œ ìíŽ "ì€ë¥ ìŽí" ë²ì ìŽ ì ë§ ì€íŽì ìì§ê° ììì ë°ê²¬íìµëë€.
self.try_for_each(move |x| {
if predicate(&x) { Err(x) }
else { Ok(()) }
}).err()
NoneErrorì ëí ëì€íë ìŽë¥Œ 구íí ì ììµëê¹? ì€íš ììê° ìëìŒë¡ From<NoneError> for failure::Error
íìíëë¡ íì©í©ëë€. https://github.com/rust-lang-nursery/failure/issues/61 ì°žì¡°
3ì€ ë³ê²œìŽ ëìŽìŒ íëë° RFC ë±ì 곌ì ì ì ëªšë¥Žê² ìµëë€.
@cowang4 ì§êžì 결곌ì ìµì
ì ë ìŽì íŒí©íì§ ììŒë €ê³ í©ëë€. ì íìŽ ë¶ìì íì¬ ìµì
ì ê³ì ìŽìŽ ëë ê²ìŽ ëë¶ë¶ìŽêž° ë묞ì
ëë€. Try
ì ëììžê³Œ ëìê°ë¥Œ NoneError
ê° íìíì§ ìì ëììžìŒë¡ ë°êŸŒë€ê³ íŽë ëë ëëŒì§ ìì ê²ì
ëë€ ...
@scottmcm ìê² ìµëë€. ëì ìë륌 ì ê² ìŽ. ëë ê²°êµ ëŒìŽëžë¬ëŠ¬ íšìê° Noneì ë°íí ë Errì ë°ííë íšíŽì ê¹ëíê² ë§ëë ë°©ë²ì ìí©ëë€. Try
ìŽìžì ë€ë¥ž ê²ì ìê³ ììµëê¹? ìì:
fn work_with_optional_types(pb: &PathBuf) -> Result<MyStruct, Error> {
if let Some(filestem) = pb.file_stem() {
if let Some(filestr) = filestem.to_str() {
return Ok(MyStruct {
filename: filestr.to_string()
});
}
}
Err(_)
}
ìŽ ì€íì ìž êž°ë¥ê³Œ failure
ìì륌 ì°Ÿì í ìì°ì€ëœê² ë€ì ì¬íì ëë žìµëë€.
use failure::Error;
fn work_with_optional_types(pb: &PathBuf) -> Result<MyStruct, Error> {
Ok({
title: pb.file_stem?.to_str()?.to_string()
})
}
ìŽì ì ìžêží ê²ì²ëŒ impl Display for NoneError
ê° ìë€ë ì ì ì ìžíê³ ë _ê±°ì_ ìëí©ëë€.
ê·žë¬ë ìŽê²ìŽ ì°ëŠ¬ê° ìíë êµ¬ë¬žìŽ ìë ê²œì° íšíŽì ëšìííë ë€ë¥ž íšì/맀í¬ë¡ê° ìì ì ììµëë€.
if option.is_none() {
return Err(_);
}
@cowang4 Display
륌 구íí ê³ ì í ì íì ì¬ì©íë failure::Error
ëíŽ From<NoneError>
륌 구ííë€ë©Ž ìëí ê²ìŽëŒê³ ìê°í©ëë€.
ê·žë¬ë opt.ok_or(_)?
륌 ì¬ì©íë ê²ìŽ ë ëì ë°©ë²ìŒ ì ììŒë¯ë¡ OptionìŽ Noneìž ê²œì° ì€ë¥ê° 묎ììžì§ ëª
ìì ìŒë¡ ë§í ì ììµëë€. ì륌 ë€ìŽ, to_str()
ê° Noneì ë°ííë 겜ì°ì pb.file_stem
ê° Noneìž ê²œì° ë€ë¥ž ì€ë¥ê° íìí ì ììµëë€.
@tmccombs ëŽ ìì ì ì€ë¥ ì íì ë§ë€ë €ê³ ìëíì§ë§ ì못íì ê²ì ëë€. ë€ì곌 ê°ììµëë€.
#[macro_use] extern crate failure_derive;
#[derive(Fail, Debug)]
#[fail(display = "An error occurred.")]
struct SiteError;
impl From<std::option::NoneError> for SiteError {
fn from(_err: std::option::NoneError) -> Self {
SiteError
}
}
fn build_piece(cur_dir: &PathBuf, piece: &PathBuf) -> Result<Piece, SiteError> {
let title: String = piece
.file_stem()?
.to_str()?
.to_string();
Ok(Piece {
title: title,
url: piece
.strip_prefix(cur_dir)?
.to_str()
.ok_or(err_msg("tostr"))?
.to_string(),
})
}
ê·žë° ë€ì ëŽ ì€ë¥ ì íì ì¬ì©íŽ 볎ììµëë€ ...
error[E0277]: the trait bound `SiteError: std::convert::From<std::path::StripPrefixError>` is not satisfied
--> src/main.rs:195:14
|
195 | url: piece
| ______________^
196 | | .strip_prefix(cur_dir)?
| |___________________________________^ the trait `std::convert::From<std::path::StripPrefixError>` is not implemented for `SiteError`
|
= help: the following implementations were found:
<SiteError as std::convert::From<std::option::NoneError>>
= note: required by `std::convert::From::from`
error[E0277]: the trait bound `SiteError: std::convert::From<failure::Error>` is not satisfied
--> src/main.rs:195:14
|
195 | url: piece
| ______________^
196 | | .strip_prefix(cur_dir)?
197 | | .to_str()
198 | | .ok_or(err_msg("tostr"))?
| |_____________________________________^ the trait `std::convert::From<failure::Error>` is not implemented for `SiteError`
|
= help: the following implementations were found:
<SiteError as std::convert::From<std::option::NoneError>>
= note: required by `std::convert::From::from`
ì¢ì, ë°©êž ë€ë¥ž ì€ë¥ ì íìì ëŽ ì€ë¥ë¡ ë³ííë ë°©ë²ì ìê³ ì¶ìŽíë€ë ê²ì 깚ë¬ììµëë€. ìŽ ì€ë¥ë ìŒë°ì ìŒë¡ ìì±í ì ììµëë€.
impl<E: failure::Fail> From<E> for SiteError {
fn from(_err: E) -> Self {
SiteError
}
}
ìëì...
error[E0119]: conflicting implementations of trait `std::convert::From<SiteError>` for type `SiteError`:
--> src/main.rs:183:1
|
183 | impl<E: failure::Fail> From<E> for SiteError {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: conflicting implementation in crate `core`:
- impl<T> std::convert::From<T> for T;
ìê² ìµëë€. std::error::Error
ìŽë»ìµëê¹?
impl<E: std::error::Error> From<E> for SiteError {
fn from(_err: E) -> Self {
SiteError
}
}
ê·žê²ë ìëíì§ ììµëë€. ë¶ë¶ì ìŒë¡ë ëŽ From<NoneError>
ì 충ëíêž° ë묞ì
ëë€.
error[E0119]: conflicting implementations of trait `std::convert::From<std::option::NoneError>` for type `SiteError`:
--> src/main.rs:181:1
|
175 | impl From<std::option::NoneError> for SiteError {
| ----------------------------------------------- first implementation here
...
181 | impl<E: std::error::Error> From<E> for SiteError {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `SiteError`
|
= note: upstream crates may add new impl of trait `std::error::Error` for type `std::option::NoneError` in future versions
NoneError
ìŽ std::error::Error
구ííì§ ììë€ê³ ìê°íêž° ë묞ì ìŽìí©ëë€. ëŽ ë¹ ìŒë° impl From<NoneError>
죌ì ì²ëŠ¬íë©Ž ë€ìì ì»ìµëë€.
error[E0277]: the trait bound `std::option::NoneError: std::error::Error` is not satisfied
--> src/main.rs:189:25
|
189 | let title: String = piece
| _________________________^
190 | | .file_stem()?
| |_____________________^ the trait `std::error::Error` is not implemented for `std::option::NoneError`
|
= note: required because of the requirements on the impl of `std::convert::From<std::option::NoneError>` for `SiteError`
= note: required by `std::convert::From::from`
몚ë From
ìëìŒë¡ ìì±íŽìŒ í©ëê¹? ëë ì€íš ììê° ê·žê²ë€ì ìŽëìŽ ëŽìŒíë€ê³ ìê° íìµëê¹?
ìë§ë option.ok_or()
ê³ ìíŽìŒ í ê²ì
ëë€.
몚ë Fromì ìëìŒë¡ ìì±íŽìŒ í©ëê¹? ëë ì€íš ììê° ê·žê²ë€ì ìŽëìŽ ëŽìŒíë€ê³ ìê° íìµëê¹?
ì ë ì€íš ììê° ê·žë ê² íì§ ìëë€ê³ ìê°í©ëë€. íì§ë§ ëŽê° í늎 ì ììµëë€.
ì¢ì, ê·žëì ëë ì€íš ìì륌 ë€ì ì¡°ì¬íê³ ë¬žìì ë€ë¥ž ë²ì ì ì¬ë°ë¥Žê² ìœê³ ìë€ë©Ž Result
ì ì€ë¥ ì íìŒë¡ íì failure::Error
륌 ì¬ì©íëë¡ ì€ê³ëììµëë€. ì¬êž°ë¥Œ ì°žì¡°íììì€ . ê·žëŠ¬ê³ ëë¶ë¶ì ì€ë¥ ì íì ëíŽ í¬êŽì ìž impl Fail
í¹ì±ì 구íí©ëë€.
impl<E: StdError + Send + Sync + 'static> Fail for E {}
https://github.com/rust-lang-nursery/failure/blob/master/failure-1.X/src/lib.rs#L218
ê·žëŠ¬ê³ impl From
íì¬ Try
/ ?
ë€ë¥ž ì€ë¥(stdì ì€ë¥ì ê°ì)륌 ê°ì¥ ì€ìí failure::Error
ì íìŒë¡ ë§ë€ ì ììµëë€.
rust
impl<F: Fail> From<F> for ErrorImpl
https://github.com/rust-lang-nursery/failure/blob/d60e750fa0165e9c5779454f47a6ce5b3aa426a3/failure-1.X/src/error/error_impl.rs#L16
ë€ë§, ìŽ ë
¹ 묞ì ì êŽë šë ì€ë¥ NoneError
ë ì€íì ìŽë¯ë¡ Display
í¹ì±ì 구ííì§ ìêž° ë묞ì ìì§ ìëìŒë¡ ë³íí ì ììµëë€. ê·žëŠ¬ê³ Option
ì Result
ì¬ìŽì 겜ê³ê° íë €ì§êž° ë묞ì ìíì§ ììµëë€. ê²°êµìë 몚ë ì¬ìì
ëê³ ì 늬ë ê²ìŽì§ë§ ì§êžì ëŽê° ë°°ìŽ ì€í ì ê±° êž°ì ì ê³ ìí ê²ì
ëë€.
ëì죌ì 몚ë ë¶ë€ê» ê°ì¬ë늜ëë€. ì²ì²í Rust륌 ë°°ì°ê³ ììµëë€! :ìë€:
ëë ëŽê° ë°°ìŽ ë¬Žì€í êž°ì ì ê³ ìí ê²ì ëë€.
:+1: ìì§í ë§íŽì .ok_or(...)?
ë ê³ì ê° êžžìŽëŒê³ ìê°í©ëë€(ëë .ok_or_else(|| ...)?
, ë¬Œë¡ ). NoneError
_had_ Display
impl 겜ì°ìë ëëŒê³ í ê¹ì? "ëê° ìììŽ"? í° ì€ë¥ë ìëì§ë§...
구첎ì ìž ì ìì í걞ì ë ë€ê°ê°ë € íë€ë...
TrySuccess
ëììŽ ë§ìì ë€êž° ììíìµëë€. í¥ë¯žë¡ê²ë ì 륌 í¬íší _ì묎ë_ë ìë ê·žê²ì ì¢ìíë€ê³ ìê°í©ëë€. RFCì ìµì¢
ë²ì ìë ììµëë€. ê·žë¬ë ë€ííë ê·žê²ì ìì¬ìì ìŽì : https://github.com/rust-lang/rfcs/blob/f89568b1fe5db4d01c4668e0d334d4a5abb023d8/text/0000-try-trait.md#using -an êŽë š-ì íì ëí - ë - ì±ê³µ -ê°
ê°ì¥ í° ë°ëë ì°êŽë ì í( trait TrySuccess { type Success; }
)ì ëí ì 첎 íµì¬ í¹ì±ìŽ 곌ëíë€ë í©ëŠ¬ì ìž ë¶ë§ìŽììµëë€. ê·žë¬ë catch
try
(https://github.com/rust-lang/rust/issues/41414#issuecomment-373985777) ok-wrapping(RFCììì ê°ìŽ)ì ìíí ì ììµëë€. , ê°ìêž° ì§ì ì ìŽê³ ì€ìí ì©ëê° ììµëë€. ìŽê²ìŽ ë°ë¡ ëíì ì ìŽíë ââí¹ì±ì
ëë€. " ?
ë íì ëìŒí ì íì ìì±íŽìŒ íš"ìŽëŒë 목íì íšê» ìŒë°ì ìŒë¡ ìíë€ê³ ìê°íë 목íì íšê» í¹ì±ìŽ 묎ê²ë¥Œ ë ì ì ì§íë ê² ê°ìµëë€. ì€ížë¡ë§š:
trait TryContinue {
type Continue;
fn from_continue(_: Self::Continue) -> Self;
}
?
ì°ì°ììì ë°íëë êŽë š ì íë ë¶ëª
í ì¡Žì¬íŽìŒ íë ì íì
ëë€. ìŽë Nikoê° ë¶ëª
í ë§í "ìŒì¢
ì 'ìì¬' ì íì ì ìíŽìŒ íë" ì±ê°ì¬ì ì¹ì§ ìëë€ë ê²ì ì믞í©ëë€. ê·žëŠ¬ê³ ()
ê²ì í©ëŠ¬ì ìŽê³ ìŒë°ì ìŽêž° ë묞ì NoneError
ì ê°ì ë¹í늌ì íŒí©ëë€.
ížì§: ìì ê±° 볎êŽìì ê²œì° "ë°í"ìŽ ì¢ì ëšìŽìŒ ì ììµëë€. try
ë©ìë(ìŒëª
ok-wrapping)ìì return
ê° ë°ìíêž° ë묞ì
ëë€. return
ë ìŽê²ì ëí 몚ëë ì°ì°ì ìŽëŠ ìŽêž°ë í©ëë€. iiuc...
ížì§ 2: ë€ë¥ž í¹ì±/ë°©ë²ì ëí ëŽ ìê°ì ìì§ ìì íëì§ ìììµëë€. @tmccombs.
@scottmcm ê·žë¥ ëª ííê², ìëë©Ž ë€ì ë ê°ì§ í¹ì±ì ì ìí©ëê¹?
trait TryContinue {
type Continue;
fn from_continue(_: Self::Continue) -> Self;
}
trait Try<E>: TryContinue {
fn try(self) -> Result<Self::Continue, E>
}
ê·žëŠ¬ê³ x?
desuguringì ë€ì곌 ê°ìµëë€.
x.try() match {
Ok(c) => c,
Err(e) => throw e // throw here is just a placeholder for either returning or breaking out of a try block
}
try { ...; expr}
ë ë€ì곌 ê°ìŽ ì€íì ì ê±°í©ëë€.
{
...
TryContinue::from_continue(expr);
}
@scottmcm ì ë ok-wrappingì ê³ ë €í ë ê·ž ë³íìŽ íšì¬ ë ë§€ë ¥ì ìŽëŒë ê²ì ìììµëë€ =)
ë€ì í¹ì±ìŒë¡ ê³ì ì§ííë©Ž ?
ëí í¹ì±ì ë€ì곌 ê°ìµëë€(몚ëë¡ ëê·ëªš ìì ê±° ìŽë).
trait Try<Other: TryContinue = Self>: TryContinue + Sized {
fn check(x: Other) -> ControlFlow<Other::Continue, Self>;
}
enum ControlFlow<C, B> {
Continue(C),
Break(B),
}
ë€ìí 귌거:
TryContinue
ì ì í ìžì ì íì ëí ìëë¡ x?
ííìŽ íì ëìŒtry_fold
ì ê°ì ê°ëší 겜ì°ì type 맀ê°ë³ìì Ʞ볞ê°ìŽ Self
ìŽë¯ë¡ T: Try
ë©ëë€.TryContinue
íì¥í©ëë€. ëŠ¬íŽ ì íìŒë¡ ì¬ì©ë ì íìŽ ë³žë¬žì ?
륌 íì©íë©Ž ok-wrappingë ì§ìíŽìŒ íêž° ë묞ì
ëë€.?
ëí ìžìë ìŒë° ì íìŽë¯ë¡ TryContinue
ì ê°ìŽ "ìŽë€ ê²ìì Self
륌 ìì±"í©ëë€.try{}
/ ?
ëí 맀í¬ë¡ ë° Option
, Result
ë° Ordering
ëí impls륌 í¬íší ì 첎 ê°ë
ìŠëª
ë°ëªš: https ://play.rust-lang.org/?gist=18663b73b6f35870d20fd172643a4f96&version=stable ( 1 ë
ì ì ì€ @nikomatsakis ìê² ê°ì¬ë늜ëë€ ð)
ëšì :
Result
implì ì¬ì í í¬í
ì í 맀ê°ë³ìê° ììµëë€.Ordering
implì ì¶ê° LessOrGreater
ì íìŽ íìíì§ ìì ê²ì ëí ì¢ì ì 충ììŒ ì ììµëë€.From
ë³íì ì ê³µíì§ ììStrandResult
ë ìŽìšë ìêŽíì§ ìêž° ë묞ì ì¢ì ì ììµëë€ SearchResult
ì ê°ì í목ì ê²œì° ì€ëš 겜ë¡ê° ì±ê³µ 겜ë¡ìŽêž° ë묞ì ìŽìí ì ììŒë©° ê²°êµ ì¶ë¡ ì ëììŽ ë ì ììµëë€. ìŽìšë ì€ì²©ë ?
ìŒìŽì€.throw
êµ¬ë¬žìŽ ë¬Žììžì§ ëª
ííì§ ììµëë€.Ok(x) => x, Err(r) => throw e.into()
ë¡ ?
ëí ì€ëª
ì ììµëë€.throw;
ê° None
( impl<T> Throw<()> for Option<T>
ì ê°ì ê²ì íµíŽ)ì ìì±íë ë°©ë²ìŽ ë ìë ììµëë€. ìŽë throw NoneError;
ë³Žë€ íšì¬ ë«ìµëë€.throw LessOrGreater::Less
ë _ì ë§_ ìŽëŠ¬ììì ê²ìŽêž° ë묞ì ê·žê²ì ë¶ëŠ¬íë ê²ì ìŽìšë ì¢ì ì ììµëë€.ížì§: Ping @glaebhoerl , RFC 1859ì í° ì°žê°ìë¡ì ìŽì ëí ì견ì
ížì§ 2: https://github.com/rust-lang/rfcs/pull/1859#issuecomment -287402652ì ìŽ ì§ì ì ëíŽ @colin-kiegelë
ëë 볞ì§ì£Œìì ì ê·ŒìŽ ìì 목í륌 í¬ìíì§ ììŒë©Žì íì죌ììë€ì ì°ìíšì ìŒë¶ ë°ìë€ìŒ ì ìëì§ ê¶êží©ëë€.
ëë ê·ž ì ììŽ ì ë§ ë§ìì ë ë€.
throw êµ¬ë¬žìŽ ë¬Žììžì§ ëª ííì§ ììµëë€.
ë€ë¥ž ìžìŽìì throw í€ìëì ìí묌ì 묎ìíê³ "throw"ë ë ëì ë²ìê¹ì§ ê°ì "ëì§ê³ " ìë€ë ì ìì ìŒì¢ ì ìë¯žê° ììµëë€. Python곌 scalaë ëí ì€ë¥ ì¬ë¡ ìŽìžì ì ìŽ íëŠì ëíŽ ììžë¥Œ ì¬ì©íë¯ë¡(ì€ì¹ŒëŒì ê²œì° ìŒë°ì ìŒë¡ ì§ì try/catch륌 ì¬ì©íì§ ìì) ì±ê³µì ìž ê²œë¡ì throw륌 ì¬ì©íë ëª ê°ì§ ì ë¡ê° ììµëë€.
@tmccombs
ë€ë¥ž ìžìŽìì throw í€ìëì ìí묌ì 묎ìíê³ "throw"ë ë ëì ë²ìê¹ì§ ê°ì "ëì§ê³ " ìë€ë ì ìì ìŒì¢ ì ìë¯žê° ììµëë€.
ë¹ì·í ìí묌곌 íšê» ì ê³µëì§ë§ "raise"ê° ë ì í©íë€ê³ ìê°í©ëë€.
ëì§ë€(ëì¬): ëì§ë ê²ì²ëŒ ìŽë€ ì¥ì, ìì¹, ìí ë±ì ê°ê±°ë ì€ê² íë€:
ìì¹(v): ë ëì ìì¹ë¡ ìŽëí©ëë€. ë€ìŽ ì¬ëŠ¬ë€; ì¬ëŠ¬ë€
"raise"륌 ?
ë
ŒëŠ¬ì ê²°í©íë ë°©ë²ìŽ ìì ì ììµëë€. ìŠ, raiseê° "ìì§"ì ì믞í ìë ììµëë€. Ok(v) => v, Err(e) => raise From::from(e)
, ì¬êž°ì raise
ë ìŒì¹íë íšíŽì 몚방í©ëë€(ì: Err(e)
íšíŽìŽ 죌ìŽì§ë©Ž ControlFlow::Break(Err(...))
ëí 묞ë²ì ë§ì ì).
'ì¬ëŠŒ'ìŽ ë ì í©íë€ê³ ìê°í©ëë€.
ì¢ì ì§ì
@scottmcm
throw êµ¬ë¬žìŽ ë¬Žììžì§ ëª ííì§ ììµëë€.
from_err(value: Other)
ê°ì§ ì ìë ìŽì ê° ììµëê¹?
ì
ë°ìŽíž: ì¬ì€ Other
ì ìí ì ëíŽ íŒëì€ë¬ìž ì ììµëë€. ìŽ í¹ì±ì ì¢ ë ì°êµ¬íŽìŒ í©ëë€. =)
@nikomatsakis
from_err(value: Other)
ê°ì§ ì ìë ìŽì ê° ììµëê¹?
êžì, Other
ë ì 첎 ?
-able ì í(ì: Result
)ìŽë¯ë¡ throw Ok(4)
ê° ìëíë ê²ì ìíì§ ììµëë€. (ê·žëŠ¬ê³ ìžìì ìž ì€ë¥ ì íì ê°ì ë¡ ëì
íì§ ììŒë €ë©Ž ì 첎 ë¶ëŠ¬ê° íìí©ëë€.) ì륌 ë€ìŽ, íì¬ Option-Result interopì ë€ì곌 ê°ì ê²ìŽëŒê³ ìê°í©ëë€.
impl<T, F, U> Try<Option<U>> for Result<T, F>
where F: From<NoneError>
{
fn check(x: Option<U>) -> ControlFlow<U, Self> {
match x {
Some(x) => ControlFlow::Continue(x),
None => ControlFlow::Break(Err(From::from(NoneError))),
}
}
}
throw
ëí ëì íì¬ ì±í¥ì ë€ì곌 ê°ìµëë€.
trait TryBreak<T> : TryContinue { from_break(_: T) -> Self }
~ì íšê»
throw $expr ==> break 'closest_catch TryBreak::from_break($expr)
TryContinue
íì¥íì¬ ok-wrappingìŽ ì¬ì©ë ë©ìëì ë°í ì íìë ì¬ì©í ì ìëë¡ í©ëë€.TryBreak<TryFromIntError>
ë° TryBreak<io::Error>
륌 ë ë€ ììí ì ììµëë€.impl<T> TryBreak<()> for Option<T>
ëšì§ ì¬ì©íë €ë©Ž throw;
ì êŽë š ì€ë¥ ì íìë ë°©ë²ìŒë¡ ê·žëŽë¯í ëë ()
íì§ ììë€.impl<T> TryBreak<!> for T
ë ì¢ì§ë§ ìë§ë ìŒêŽì±ìŽ ìì ê²ì
ëë€.(ì ìž: ìŽë¬í í¹ì± ë° ë©ìë ìŽëŠì ëì°í©ëë€. ëì 죌ìžì!)
ì¬êž°ì ì êž°ë ë€ë¥ž 묞ì ì ëí ëŽ ìê°ì ìì§ ìœê² ì€ëª
í ì ìë íììŒë¡ ì 늬ëì§ ììì§ë§ From::from()
ëìê°ë§ê³Œ êŽë šë ì í ì¶ë¡ 묞ì ì êŽë šíì¬(ìµê·Œì ë€ë¥ž ê³³ììë ìŽ ë¬žì ê° ë
Œìëìëì§ êž°ìµëì§ ììµëë€. , ëë ì¬êž°ììë§?):
"ê·žë° ììŒë¡ ê±°ì§ë§ ì í ì¶ë¡ 몚ížì±"ìŽ ìë€ë 볞ë¥ì ê°ê° (íì€ìŒ 겜íìì)ì ìë RFCì ìŒë¶ë¡ From
ë³íì ìíì§ ìë ìŽì ì€ íëììµëë€(죌ìë ìëì§ë§). ê·žë¬ë ìŽì ìŒìŽí¬ì 구ìì¡ìŒë¯ë¡ ì í ì¶ë¡ íë¡ìžì€ì í¹ë³í Ʞ볞 ê·ì¹ì 'ê·žë¥' ì¶ê°íì¬ ìŒìŽí¬ë¥Œ ê°ì§ê³ ê·žê²ì ëš¹ìŒë €ê³ í ìë ìëì§ ê¶êží©ëë€.
ê·žê² ëŽê° ìê°ì
ëë€ : ì°ëŠ¬ë 볌 ëë§ë€ From::from()
:ì ìíŽ ìœì
ë íëì ìµì
ìŒë¡ ?
, ì°ëŠ¬ë ì íí ë ê°ì§ ì í ì€ íë륌 ìê³ (ì
ë ¥ desugaring볎ë€ë ìëìŒë¡ ìì±ì] ë ì¶ë ¥), ë€ë¥ž íëë 몚ížíì§ë§ ë€ë¥ž íëë Ʞ볞ì ìŒë¡ íëì ëìŒíê² ì€ì í©ëë€. ìŠ, ìŽë€ impl From
륌 ì¬ì©í ì§ íì€íì§ ìì ê²œì° êž°ë³žì ìŒë¡ impl<T> From<T> for T
í©ëë€. ìŽê²ì Ʞ볞ì ìŒë¡ íì ë¹ì ìŽ ì€ì ë¡ ìíë ê²ìŽëŒê³ ìê°í©ëë€. ìœê° ììì ìŒ ì ìì§ë§ ìëíë€ë©Ž ìŽì ì ë¹ì© IMHOì ê°ì¹ê° ìë ê² ê°ìµëë€.
(ëë ëí ìê° From
ì ííê² ìžíŽë¡, ìŽë¯ž ë í목ìŽìë€ ?
desugaringíì§ë§, ìŽë€ 겜ì°ìë, ê·ž ìŽì ë¡ ëª ê°ì§ í¹ë³ ìŽë¯žì
ëê¹? ë ê² ê°ì§ ììµëë€ .)
@scottmcm ì ì ììì From::from()
ë ëìê°ë§ì ìŒë¶ê° _ìë_ Try
ëí Result
ììµëë€.
@tmccombs ëë ê·žì ì ìì ëí ìì ìì ì ìí ê²ìŽ ìëëë€.
try{}
RFC(https://github.com/rust-lang/rfcs/pull/2388)ë 결곌ì ì 겜 ì°ì§ ìë try
ëžë¡ì ëíŽ ë
Œìíìµëë€. ìŽ ëìì ìí ê²œì° ì€ë¥ ì íì ìì í 묎ìíëë¡ ì íí ì ììŒë¯ë¡ ì ì íê² ì ì²ëŠ¬íë ê² ê°ìµëë€.
let IgnoreErrors = try {
error()?;
none()?;
};
ìŽì 곌 ëìŒí í¹ì±ì ì¬ì©í ê°ë ìŠëª 구í: https://play.rust-lang.org/?gist=e0f6677632e0a9941ed1a67ca9ae9c98&version=stable
ëë ê±°êž°ì ëª ê°ì§ í¥ë¯žë¡ìŽ ê°ë¥ì±ìŽ ìë€ê³ ìê°í©ëë€. í¹í ì¬ì©ì ì ì 구íì ê²°ê³Œë§ ê°ì žì€ê³ E: Debug
ë°ìžë©íì¬ ë°ìíë 몚ë ì€ë¥ë¥Œ ìëìŒë¡ êž°ë¡í ì ìêž° ë묞ì
ëë€. ìëë©Ž ë²ì ì ëí ë°í íììŒë¡ í¹ë³í êµ¬ì± í ì main
ì íšê» Termination
"ë°ë¡ ìë"ë¹ì ìŽ ì¬ì©í ì ìëë¡íêž° ?
ë³µì¡í ì íì ìëª
ìŽìë (HTTPS //github.com/rust-lang/rfcs/issues/2367).
Try
ížë ì ì êž°ì¡Ž ë²ì ì ì¬ì©íì¬ https://github.com/SergioBenitez/Rocket/issues/597#issuecomment -381533108ì ì°žì¡°
@scottmcm ìŽ ì ìí í¹ì± ì ìë ìŽë¬í 묞ì 륌 íŽê²°í©ëë€. ê·žë¬ë ê·žê²ë€ì íì ìŽììŒë¡ ë³µì¡íŽ 볎ì ëë€. ëë ê·žê²ë€ì ë€ì 구ííë ë° ê· ìŽì ëŽê³ ë€ìì ìê°íŽ ëìµëë€.
#[derive(Debug, Copy, Clone)]
enum ControlFlow<C, B> {
Continue(C),
Break(B),
}
// Used by `try { }` expansions.
trait FromTry: Try {
fn from_try(value: Self::Continue) -> Self;
}
// Used by `?`.
trait Try<T = Self>: Sized {
type Continue;
fn check(x: T) -> ControlFlow<Self::Continue, Self>;
}
죌ì ë³ê²œ ì¬íì FromTry
(ìŽì ìë TryContinue
)ì ë¬ëŠ¬ Try
Continue
êŽë š ì íìŽ Try
í¹ì±ì ìë€ë ê²ì
ëë€. ì ì륌 ëšìííë ê² ìžìë ìŽê²ì Try
ê° FromTry
ì ë
늜ì ìŒë¡ 구íë ì ìê³ FromTry
구íìŽ Try
ê° êµ¬íëììµëë€. (ì°žê³ : Try
ì FromTry
ëìì 구ííë €ë©Ž from_try
ë©ìë륌 Try
)
ìŽ íë ìŽê·žëŒìŽëìì Result
ë° Option
ë¿ë§ ìëëŒ Rocketì Outcome
ì ëí 구íìŽ í¬íšë ì 첎 íë ìŽê·žëŒìŽë륌 íìž íìžì.
ë³Žê³ íŽ ì£Œì ì ê°ì¬í©ëë€. @SergioBenitez! ê·ž 구íì RFC 1859ì ìë í¹ì± ì ìì "íì ë§€ê° ë³ì륌 ë€ì§ìŽ"ë€ë¥ž ë²ì 곌 ìŒì¹ : https://github.com/rust-lang/rfcs/blob/f89568b1fe5db4d01c4668e0d334d4a5abb023d8/text/0000-try-trait.md#unresolved -ì§ë¬ž
ê°ì¥ í° ìì€ì typeof(x?)
ê° typeof(x)
ìë§ ìì¡Žíë ìì±ì
ëë€. íŽë¹ ìì±ìŽ ìë€ë ê²ì ì볞ì ëí ì°ë € ì€ íëììµëë€("ìŽ ëŒìžì ë°ë¥ž ìœëì ê°ë
ì±ì ëíŽ ìœê° ê±±ì í©ëë€" https://github.com/rust-lang/rfcs/pull/1859#issuecomment-279187967). ìµì¢
íì죌ìì ì ì("죌ìŽì§ ì í Tì ëíŽ ?ë ì íí í ì¢
ë¥ì ok/error ê°ì ìì±í ì ììµëë€" https://github.com/rust-lang/rfcs/pull/1859#issuecomment-283104310). ë¬Œë¡ íŽë¹ ìì±ìŽ ë¶íìíê±°ë ë묎 ì íì ìŽëŒë 죌ì¥ë ììì§ë§ FCP ìŽì ì ìµì¢
ììœììë ì¬ì í ìŽì ìŒë¡ ìììµëë€(https://github.com/rust-lang/rfcs/pull/1859#issuecomment -295878466).
ì ì륌 ëšìííë ê² ìžìë
Try
ê°FromTry
ì ë 늜ì ìŒë¡ 구íë ì ìë€ë ì¥ì ìŽ ììµëë€.
íì€í ì€ëë from_ok
Try
ë° do catch
ê° ë¶ìì íêž° ë묞ì from_ok
ë ë ìŒë°ì ì
ëë€. ê·žëŠ¬ê³ do catch
ê° ìì ì ìŽëëŒë ì 첎ì ìŒë¡ ?
믞ë§ìŒë¡ ì¬ì©ëë€ë ë° ëìí©ëë€(ëë¶ë¶ì ìŽë¬í ëžë¡ìë ì¬ë¬ ê°ì ?
í¬íšëìŽ ìêž° ë묞ì).
ê·žë¬ë í¹ì±ê³Œ ê·ž ìì
ì êŽì ìì "ìºëŠ¬ìŽ ì íì 'ê³ì' ê°ì ëííë ê²"ì ?
ì ì ëì ìŒë¡ íìì ìž ë¶ë¶ìŽëŒê³ ìê°í©ëë€. ì€ëë ìë Ok(...)
ëë Some(...)
ëì ì¬ì©íë í¹ì±ì ê±°ì ê±°ì¹ì§ ìì§ë§ ìŒë°ì ìž ì¬ì©ììë ì€ìí©ëë€. ì: try_fold
:
íšìê° ìºëŠ¬ìŽ ì íì ë°íí ê²œì° íŽë¹ ìºëŠ¬ìŽ ì íì êŽì¬ ê°ì ë£ì ì ìë ë°©ë²ìŽ ììŽìŒ í©ëë€. ê·žëŠ¬ê³ ì€ìí ê²ì, ìŽê²ì ì ê³µíë ê²ìŽ ìŽë €ìŽ ìŒìŽ ìëëŒê³ ìê°í©ëë€. Result, Option, Outcome ë±ì ëí ë§€ì° ìì°ì€ë¬ìŽ ì ìê° ììµëë€.
@Centril ì ìŽì ì "ìºëŠ¬ìŽì ì€ì¹ŒëŒë¥Œ ëííë ê²"ë ìŽë¡ ì ìŒë¡ ë ê°ëší 구ì±ìŽëŒê³ ì§ì íìµëë€. ì륌 ë€ìŽ, íì€ìŒì ê·žê²ì ížì¶ Pointed
typeclass ëë ì°ëŠ¬ê° ë
¹ìì ë©ëŠ¬ _that_ì ìŒë°í í ìê°íì§ ììµëë€íì§ë§, : ì try { 4 }
⊠vec![4]
ëìê² ììží ê² ê°ì .
ëë ëí async
íšìê° ëžë¡ ê°ì 믞ëë¡ ëííêž° ìíŽ ì ìë ê²ì²ëŒ ëžë¡ ê°ì ì€ë¥ ê°ë¥í ì íìŒë¡ ëííë try
íšìê° ìì ì ìë 믞ë륌 ììíê³ ììµëë€. ì¬êž°ì ë€ì TryContinue
ê° ì€ìí ë¶ë¶ì
ëë€. throw
êµ¬ë¬žìŽ ìë ê²œì° ìŽë¬í íšìë ?
ë ì¬ì©íì§ ìì ì ììµëë€.
ë¶ííë ê·ž 몚ë ê²ì 구첎ì ìž ê²ë³Žë€ ë ì² íì ì ëë€. ê·žê²ìŽ ìë¯žê° ìëì§, ëë ë¶ë¶ìì ë°ëëŒê³ ìê°íëì§ ìë €ì£Œììì€ :slightly_smiling_face:
ížì§ : ìŽ ë²ì ì ìŽêž° ë²ì ìŽ í¬íšë ìŽë©ìŒì ë°ìë€ë©Ž ì£ì¡í©ëë€. ì ê° ëêžì ë묎 ìŒì° ëë ë€ì...
ê°ì¥ í° ìì€ì typeof(x?)ê° typeof(x)ìë§ ìì¡Žíë ìì±ì ëë€.
ì, ë¬Œë¡ ì ëë€. ì§ì íŽì£Œì ì ê°ì¬í©ëë€.
ë¬Œë¡ íŽë¹ ìì±ìŽ ë¶íìíê±°ë ë묎 ì íì ìŽëŒë 죌ì¥ë ììì§ë§ FCP ìŽì ì ìµì¢ ììœììë ì¬ì í ìŽì ìŒë¡ ìììµëë€(rust-lang/rfcs#1859(comment)).
ë묎 ì íì ìŒ ì ìë 구첎ì ìž ìê° ììµëê¹?
íšìê° ìºëŠ¬ìŽ ì íì ë°íí ê²œì° íŽë¹ ìºëŠ¬ìŽ ì íì êŽì¬ ê°ì ë£ì ì ìë ë°©ë²ìŽ ììŽìŒ í©ëë€. ê·žëŠ¬ê³ ì€ìí ê²ì, ìŽê²ì ì ê³µíë ê²ìŽ ìŽë €ìŽ ìŒìŽ ìëëŒê³ ìê°í©ëë€.
ì ë¹í ë¶ììŽëŒê³ ìê°í©ëë€. ëë ëìíë€.
@SergioBenitez https://github.com/rust-lang/rfcs/pull/1859#issuecomment -279187967ìì
ë°ëŒì 묞ì ë ì ìë ì í ì¬íìŽ ì¶©ë¶í©ëê¹? ì±ê³µ ì íì ê²°ì í ë ì€ë¥ ì¬ë¡ 컚í ì€ížë¥Œ ì ì¬ì©íê³ ììµëê¹? ëšì© ê°ë¥ì±ìŽ ììµëê¹?
ëë 믞ëì ëí ëì 겜íìŒë¡ ì¬êž°ì ëª ê°ì§ ì ì©í 겜ì°ê° ìì ì ìë€ê³ ë§í ì ììµëë€. í¹í, ë¹ì ìŽ ìŽìŒêž°íë Poll ì íì ëª ê°ì§ ë°©ë²ìŒë¡ ì²ëŠ¬ë ì ììµëë€. ëëë¡ ì°ëŠ¬ë NotReady ë³íìì ë°ìŽ ëì 볞ì§ì ìŒë¡ Result ê°ì ëšêž°ê³ ì¶ìµëë€. ëëë¡ ì°ëŠ¬ë Ready ë³íìë§ êŽì¬ìŽ ìê³ ë€ë¥ž ë³í(ì€ìŒì¹ììì ê°ìŽ) ì€ íëìì ë°ìŽëŽëŠ¬ê³ ì¶ì ëê° ììµëë€. ì±ê³µ ì íìŽ ì€ë¥ ì íì ìíŽ ë¶ë¶ì ìŒë¡ ê²°ì ëëë¡ íì©íë©Ž ìŽ ë 겜ì°ë¥Œ 몚ë ì§ìíê³ êž°ë³žì ìŒë¡ 컚í ì€ížë¥Œ ì¬ì©íì¬ ìíë ë¶íŽ ì íì ê²°ì íë ê²ìŽ ë ê·žëŽë¯í©ëë€.
OTOH, ìŽ ì€ì ë°ëŒ ìœëì ê°ë ì±ì ëíŽ ìœê° ê±±ì í©ëë€. ìŽê²ì ëšìí ì€ë¥ êµ¬ì± ìì륌 ë³ííë ê²ê³Œ ì§ì ìŒë¡ ë€ëŠ ëë€. ìŠ, Ʞ볞ì ìŒë¡ ? ìí© ì 볎ì ë°ëŒ ìíë©ëë€.
ë°ëŒì ë€ì곌 ê°ìŽ _ë ì í 몚ë륌 ì í 맀ê°ë³ìë¡ ìŽëí í¹ì±ì ììí ì ììµëë€.
trait Try<T,E> {
fn question(self) -> Either<T, E>;
}
ê·žëŠ¬ê³ ê·žê²ì ì¬ì©íë©Ž 몚ë
let x: Result<_,_> = blah.poll()?; // early-return if NotReady
let x: Async<_> = blah.poll()?; // early-return if Error
let x: i32 = blah.poll()?; // early-return both NotReady and Errors
ê·žë¬ë ëë ìŽê²ìŽ ìëíì§ ìëë€ë ê²ì ì믞íêž° ë묞ì íì€í ëì ìê°ìŽëŒê³ ìê°í©ëë€.
println!("{}", z?);
z?.method();
묎ìì ìì±í ì§ì ëí ì í 컚í ì€ížê° ìêž° ë묞ì ëë€.
ë€ë¥ž ë²ì ì ë€ì곌 ê°ì êž°ë¥ì íì±ííë ê²ì ëë€.
fn foo() -> Result<(), Error> {
// `x` is an Async<i32> because NotReady doesn't fit in Result
let x = something_that_returns_poll()?;
}
fn bar() -> Poll<(), Error> {
// `x` is just i32 because we're in a Poll-returning method
let x = something_that_returns_poll()?;
}
ëŽ ë³žë¥ì ì¶ë¡ ìŽ "?"ìì íë¬ ëìšë€ë ê²ì ëë€. ë묎 ëëŒìŽ ê²ìŽ ììŒë¯ë¡ ìŽê²ì "ë묎 ì늬í" ìëìŽì ììµëë€.
ë¹íì ìŒë¡, ëë ê·žê²ì ê°ì§ ìë ê²ìŽ ë묎 ì íì ìŽëŒê³ ìê°íì§ ììµëë€. my_result?
-> Poll
íšìì Result
륌 ë°ííë ë©ìëìì Poll
ì ?
륌 ì¬ì©íë ê²ì ìŒë°ì ìž ê²ìŽ ìëëŒ ìí° íšíŽì²ëŒ 볎ìŽêž° ë묞ì .wait(): T
ì ê°ì (ê°ìì) ì ì© ë©ìë륌 ì¬ì©í©ëë€. .ready(): Option<T>
(ìë£ ì¬ë¶ íìž) 몚ë륌 ì ííë ê²ìŽ ìŽìšë ë ëì ê²ì
ëë€.
"í¥ë¯žë¡ë€" https://play.rust-lang.org/?gist=d3f2cd403981a631f30eba2c3166c1f4&version=nightly&mode=debug
ëë ìŽ try (do catch) ëžë¡ìŽ ë§ìì ë€ì§ ììµëë€. ìŽ ëžë¡ì ìŽë³Žììê² ê·žë€ì§ ì¹ìíì§ ìì ê² ê°ìµëë€.
ì¬ë¬ ì견ì íŒì ž ìë ì ìì íì¬ ìí륌 ì¡°í©íë €ê³ í©ëë€. íì¬ ì ìë í¹ì± ìžíž( Error
êŽë š ì í ìì )ì ëí ëšìŒ ììœìŽ ììµëê¹?
ìŽ ì€ë ëì ìŽêž°ì Try
륌 ì€ë¥ í¹ì±ê³Œ ë³ê°ë¡ ë¶í íë ê²ì ëí 죌ìì 볎ììµëë€. íŽë¹ ë¶í ì 구íí ê³íìŽ ììµëê¹?
묌ìíìì Result<T, E>
ìì 몚ë ì íì Other<T2, E>
í¬ëª
íê² ë³ííë ê²ìŽ ì ì©í ê²ì
ëë€. ìŽë ê² íë©Ž êž°ì¡Ž IO íšì륌 ë³Žë€ ì 묞íë íšì ëŽìì ë©ì§ 구묞ìŒë¡ ížì¶í ì ììµëë€(ì: ê²ìŒëŠ) ë°í ì í.
pub fn async_handler() -> AsyncResult<()> {
let mut file = File::create("foo.txt")?;
AsyncResult::lazy(move || {
file.write_all(b"Hello, world!")?;
AsyncResult::Ok(())
})
}
ì믞ì ìŽê²ì From::from(E) -> Other<T2, E>
ì²ëŒ ë껎ì§ì§ë§ From
ì íì¬ êž°ì¡Ž Result
-ëë±í Try
구íìŒë¡ ì íë©ëë€.
NoneError
ìë ë³ëì ì¶ì 묞ì ê° ììŽìŒ íë€ê³ ìê°í©ëë€. Try
í¹ì±ìŽ ìì íëì§ ìëëŒë ?
ì Option
íšì¬ ë ìžì²Žê³µíì ìŽë¯ë¡ NoneError
ë ìì íëìŽìŒ í©ëë€. struct MyCustomSemanthicalError;
ì ê°ì ì€ë¥ ëë Default
구í ì€ë¥ì ëíŽ ìŽê²ì ê³ ë €íììì€. None
ë MyCustomSeemanthicalError
륌 íµíŽ From<NoneError>
MyCustomSeemanthicalError
ë¡ ìœê² ë³íí ì ììµëë€.
https://github.com/rust-analyzer/rust-analyzer/ ìì ìì
íë©Žì, í¹í ë°í ì íìŽ Result<Option<T>, E>
ë ?
ì°ì°ìì ë¶ì¶©ë¶íšê³Œ ìœê° ë€ë¥ž íìŽíŒì»·ì ë§ë¬ìµëë€ Result<Option<T>, E>
.
ìŽ ì íì ê²œì° ?
ì ìíŽ íšê³Œì ìŒë¡ ì€íì ì ê±°íë ê²ìŽ í©ëŠ¬ì ì
ëë€.
match value? {
None => return Ok(None),
Some(it)=>it,
}
ì¬êž°ì value
ë Result<Option<V>, E>
ì íìŽê±°ë ë€ì곌 ê°ìµëë€.
value?
ì¬êž°ì value
ë Result<V, E>
ì
ëë€. ëë ìŽê²ìŽ ê°ë¥íë€ê³ ìê°ëë©Ž íì€ ëŒìŽëžë¬ëŠ¬ 구í Try
ì ëí ë€ì곌 ê°ì ë°©ë²ìŒë¡ Option<T>
, ëŽê° ëª
ì ì ìŒë¡ í
ì€ížíì§ ìì ëŽê° ì 묞í 묞ì ê°ìì ì ììµëë€ ìê°íì§ë§.
enum NoneError<E> {
None,
Err(E),
}
impl From<T> for NoneError<T> {
fn from(v: T) -> NoneError<T> {
NoneError:Err(v)
}
}
impl<T, E> std::Ops::Try for Result<Option<T>, E> {
type OK = T;
type Error = NoneError<E>;
fn into_result(self) -> Result<Self::OK, Self::Error> {
match self {
Ok(option) => {
if let Some(inner) = option {
Ok(inner)
} else {
Err(NoneError::None)
}
}
Err(error) => {
Err(NoneError::Err(error));
}
}
}
fn from_error(v: Self::Error) -> Self {
match v {
NoneError::Err(error) => Err(error),
None => Some(None),
}
}
fn from_ok(v: Self::OK) -> Self {
Ok(Some(v))
}
}
impl<T> std::Ops::Try for Option<T> {
type OK = T;
type Error = NoneError<!>;
fn into_result(self) -> Result<Self::OK, Self::Error> {
match self {
None => Err(NoneError::None),
Some(v) => Ok(v),
}
}
fn from_error(v: Self::Error) -> Self {
match v {
NoneError::None => Some(None),
_ => unreachable!("Value of type ! obtained"),
}
}
fn from_ok(v: Self::OK) -> Self {
Ok(v)
}
}
@matklad ìê² ì Try
구ííë ì¬ì©ì ì§ì ìŽê±°íì ë§ë€ ì ììëì§ ë¬Œìì ë Cancellable
ëŒê³ íë std::ops::Try
ê° ë¶ìì íë€ê³ ì§ì íìµëë€. rust-analyzer
(íì¬) ìì ì ìž ë
¹ì 목íë¡ íë ê²œì° ìŽìšë ì¬ì©í ì ììµëë€.
https://github.com/rust-lang/rust/issues/31436#issuecomment -441408288ìì ë€ì ê²ìí©ëë€. ìŽì ëíŽ ìžêžíê³ ì¶ìì§ë§ ì못ë 묞ì ëŒê³ ìê°íêž° ë묞ì ëë€.
볞ì§ì ìŒë¡ ëŽê° ê°ì§ ìí©ì GUI íë ììí¬ì ìœë°±ì
ëë€. Option
ëë Result
륌 ë°ííë ëì UpdateScreen
륌 ë°ííì¬ íë©ŽìŽ ì
ë°ìŽížê° íìí©ëë€. ì¢
ì¢
ëë ë¡ê¹
ìŽ ì í íìíì§ ììŒë©°(몚ë ì¬ìí ì€ë¥ì ë¡ê·žìšíë ê²ìŽ ì€ì©ì ìŽì§ ìì) ì€ë¥ê° ë°ìíì ë ëšìí UpdateScreen::DontRedraw
륌 ë°íí©ëë€. ê·žë¬ë íì¬ ?
ì°ì°ì륌 ì¬ì©íë©Ž íì ë€ì곌 ê°ìŽ ìì±íŽìŒ í©ëë€.
let thing = match fs::read(path) {
Ok(o) => o,
Err(_) => return UpdateScreen::DontRedraw,
};
Try ì°ì°ì륌 íµíŽ Result::Err
ìì UpdateScreen::DontRedraw
ë¡ ë³íí ì ìêž° ë묞ì ìŽê²ì ë§€ì° ì§ë£ší©ëë€. ì¢
ì¢
íŽì 맵ìì ì€íší ì ìë ê°ëší ì¡°íê° ììµëë€(ì€ë¥ê° ìë). ) - ë묎 ì죌 íëì ìœë°±ìì ?
ì°ì°ì륌 5 - 10ë² ì¬ì©í©ëë€. ììì ì°êž°ì ë§€ì° ììžíêž° ë묞ì, ëŽ íì¬ì ì룚ì
ìŽë€ impl From<Result<T>> for UpdateScreen
곌 ê°ìŽ , ë€ì곌 ê°ìŽ ìœë°±ìì ëŽë¶ íšì륌 ì¬ì©
fn callback(data: &mut State) -> UpdateScreen {
fn callback_inner(data: &mut State) -> Option<()> {
let file_contents = fs::read_to_string(data.path).ok()?;
data.loaded_file = Some(file_contents);
Some(())
}
callback_inner(data).into()
}
ìœë°±ìŽ íšì í¬ìží°ë¡ ì¬ì©ëêž° ë묞ì -> impl Into<UpdateScreen>
ì¬ì©í ì ììµëë€(ìŽë€ ìŽì ë¡ impl
ë°ííë ê²ì íì¬ íšì í¬ìží°ì ëíŽ íì©ëì§ ììµëë€). ë°ëŒì Try
ì°ì°ì륌 ì¬ì©íë ì ìŒí ë°©ë²ì ëŽë¶ êž°ë¥ ížëŠì ìííë ê²ì
ëë€. ë€ì곌 ê°ìŽ ê°ëší í ì ìë€ë©Ž ì¢ì ê²ì
ëë€.
impl<T> Try<Result<T>> for UpdateScreen {
fn try(original: Result<T>) -> Try<T, UpdateScreen> {
match original {
Ok(o) => Try::DontReturn(o),
Err(_) => Try::Return(UpdateScreen::DontRedraw),
}
}
}
fn callback(data: &mut State) -> UpdateScreen {
// On any Result::Err, convert to an UpdateScreeen::DontRedraw and return
let file_contents = fs::read_to_string(data.path)?;
data.loaded_file = Some(file_contents);
UpdateScreen::Redraw
}
ìŽê²ìŽ íì¬ ì ììŒë¡ ê°ë¥íì§ íì€íì§ ììŒë©° ê³ ë €ë¥Œ ìíŽ ì ì¬ì© ì¬ë¡ë¥Œ ì¶ê°íê³ ì¶ììµëë€. ì¬ì©ì ì ì Try ì°ì°ìê° ìŽì ê°ì ê²ì ì§ìí ì ìë€ë©Ž ì¢ì ê²ì ëë€.
@joshtriplett ìê° ì ë€ì¬ ë€ì https://github.com/rust-lang/rust/compare/master...scottmcm :try-trait-v2ìì ì ìì ìì íë¡í íì ì 구ì±íì¬ êµ¬ì²Žì ìŒë¡ ë§ë€ììµëë€. ëë ê·žê²ìŒë¡ ëª ê°ì§ ë ë§ì ê²ì ìëíꞰ륌 ë°ëëë€.
@scottmcm ë³ê²œ ì¬íì ëí ìì ìì€ ì€ëª ìŽ ììµëê¹?
@scottmcm FWIW ë ìŽìšììë ë³ê²œì ìëíìµëë€.
https://github.com/rayon-rs/rayon/compare/master...cuviper :try-trait-v2
(ì¬ì í ë¶ìì í íëª©ìŽ ìë ê°ìž ì¬ë³žì ì¬ì© ì€)
ê·žë ë€ë©Ž Option NoneError륌 ë³ííë ì룚ì ì 묎ìì ëê¹? Try Trait륌 구ííêž° ë묞ì íŽë¹ í¹ì (ë¶ìì í?) êž°ë¥ì ì¬ì©íëë¡ ì€ì íì§ ìë í 컎íìŒëì§ ìë ê² ê°ìµëë€.
ë°ëŒì Ʞ볞ì ìŒë¡ ? ëŽê° ìë í ìµì ìŽ ìë ì°ì°ì?
@omarabid , ì°ì°ìë Option
ëë Result
ì íšê» ì¬ì©íêž°ì ìì ì ìŽì§ë§ ìì ë ëê¹ì§ Try
륌 ìŒë° ì ìœ ì¡°ê±ŽìŒë¡ ì¬ì©í ì ììµëë€. NoneError
륌 ì í í¬íší íìê° ììŒë¯ë¡ Option
ë°ííë íšììì Option
ì ?
륌 ì¬ì©íë ê²ì ì벜í©ëë€. ì íì ì§ì°ë©Ž Result
ë°íí ìë ììµëë€.
use std::fmt::Debug;
pub struct Error(Box<dyn Debug>);
impl<T: Debug + 'static> From<T> for Error {
fn from(error: T) -> Self {
Error(Box::new(error))
}
}
pub fn try_get<T>(slice: &[T], index: usize) -> Result<&T, Error> {
Ok(slice.get(index)?)
}
( ëìŽí° )
@scottmcm , íë¡í íì
try-trait-v2
ìŽ ìì ë ì€íší©ëë€!
ëŽ ìì ê° ì€ëšëë ê²ì ìíì§ ììŒë©Ž try-trait-v2
ë€ì곌 ê°ì ê²ìŽ íìí©ëë€.
#[unstable(feature = "try_trait_v2", issue = "42327")]
impl<T, U, E: From<NoneError>> ops::Bubble<Result<U, E>> for Option<T> {
fn bubble(self) -> ops::ControlFlow<T, Result<U, E>> {
match self {
Some(x) => ops::ControlFlow::Continue(x),
None => ops::ControlFlow::Break(Err(E::from(NoneError))),
}
}
}
ìŽ êž°ë¥ì íì¬ ìíë 묎ìì ëê¹?
ìŽí°ë ìŽí°ì ëíŽ try_fold
륌 구ííë 묞ìì ëí PR #62606ìŽ ìì íëë©Ž ë€ì ìŽìŽìŒ í©ëë€.
ížì§: ~ scottmcmì ëí ì¶ì í목ìŒë¡ ìì ì ì ë°ìŽížíìµëë€.
Try
í¹ì±ì ìŽ ì€ë ëìì ì ìë ëììŒë¡ ë첎í ê³íìŽ ììµëê¹? @scottmcmìŽ ì ìí ë²ì ì êŽì°®ì ê² ê°ìµëë€. Option
ì íšê» ?
ì°ì°ì륌 ê³ì ì¬ì©íê³ ì¶ìµëë€. Option
ì Result
ì믞 첎ê³ë¥Œ ê°ì íì§ ìëë¡ Try
ížë ìì ë³ê²œíŽìŒ íë€ê³ ìê°í©ëë€. Option
.
@scottmcm ì ëìì ì¬ì©íë©Ž ?
ì íšê» Option
íê³ NoneError
ììµëë€. ëë Try
í¹ì±ìŽ " Option
ì 'ì€íš'륌 ëíëŽë ì íì ìžê³µì ìŒë¡ ì ìí íìê° ìë€"ë @nikomatsakis ( comment )ì ëìí©ëë€.
pub struct Error(Box<dyn std::fmt::Debug>);
impl<T: std::fmt::Debug + 'static> From<T> for Error { fn from(error : T) -> Self { Error(Box::new(error)) } }
type Result<T> = std::result::Result<T, Error>;
ì¬êž° ìŽì¬ì, ëë ì»ê³ ì¶ì ê²ì ìœê° ê³ ì§ìŽ ìììµëê¹? ìëìŒë¡ 몚ë ì€ë¥ ë° ìµì
ì§ì°êž°ë¥Œ ì
ë ¥í©ëë€.
ë€ë¥ž ê°ë¥í ì룚ì
ì 구íí ì ìë ìŽì 륌 ìŽíŽíë €ê³ ë묎 ë§ì ìê°ì ë³Žëž í @cuviper ê° ëŽê° ì»ì ì ìë ê²ê³Œ ê°ì¥ ê°ê¹ë€ë ê²ì ìììµëë€.
ëª ê°ì§ ì€ëª
ìŽ ëììŽ ëìì§ë§ ì ìŽë Rust ë©ííë¡ê·žëë°ì ëª ê°ì§ ì í ì¬íì ëíŽ ììží ìê² ëììµëë€.
ê·žëì ê·žê²ì ìŽíŽíê³ êµ¬ì²Žì ìž ì©ìŽë¡ ì€ëª
íë €ê³ ë
žë ¥íìµëë€.
ìŽ ì€ë ëë ë ê°ì ì¬ëìŽ ìŽê²ì ê±žë € ëìŽì§ëë¡ ëìž ì ìë ê°ì¥ ê°ë¥ì± ìë êµì°šë¡ìž ê² ê°ìµëë€. ìì ë¡ê² ìì íììì€.
From<T: StdError> for Error
ë° í¹ì From<NoneError> for Error
충ëtype Error = Box<Debug>
ë From<T:Debug> for Error
륌 From<T> for T
ì 충ëíê² íë ëë²ê·žë¥Œ ë°ìžë©í©ëë€(멱ë±ì±ì ìí ì¬ê· From)ë°ëŒì Errorë Debug륌 구íí ì ìêž° ë묞ì ì ìŽì Debug륌 ì¬ì©íì¬ ê²°ê³Œë¡ ëí íŽì íë ëì°ë¯žë¥Œ ìí ì ììµëë€.
fn from<T>(result : Result<T>) -> std::result::Result<T, Box<dyn std::fmt::Debug>> { match result { Ok(t) => Ok(t), Err(e) => Err(e.0) } }
impl From<Result<T>> for StdResult<T>
ëë Into<StdResult> for Result<T>
ì ììµëë€(ì
ì€ížëŠŒ ì íì ëí ì
ì€ížëŠŒ í¹ì±ì ììí ì ìì).
ì륌 ë€ìŽ ìŽë¥Œ ì¬ì©íì¬ Terminationì ëí ëë²ê·ž ë°íì ì»ì ì ììµëë€.
fn main() -> std::result::Result<(), Box<dyn std::fmt::Debug>> { from(run()) }
ì¬ì
í ìê°: ìë§ë ?
ì°ì°ìë 몚ëë ââë°ìžë륌 ëíëŒ ì ììŒë¯ë¡
let x: i32 = something?;
rest of function body
ëë€
Monad::bind(something, fn(x) {
rest of function body
})
ëì°í ìê°ìŽì§ë§ ëŽ ìì ꎎì§ë¥Œ êž°ìê² í©ëë€.
@derekdreery return
ë° continue
ì ê°ì ëª
ë ¹í ì ìŽ íëŠììë ì ìëíì§ ìëë€ê³ ìê°í©ëë€.
?
ì°ì°ìì ì믞ë ìŽë¯ž ìì ì ì
ëë€. ì€ì Try
í¹ì±ë§ ë¶ìì íê³ ëªšë ë³ê²œ ì¬íì Option
ë° Result
ëíŽ ëìŒí ìì ì ìž íšê³Œë¥Œ ì ì§íŽìŒ í©ëë€.
@KrishnaSannasi
@derekdreery ë°í ë° ê³ì곌 ê°ì ëª ë ¹í ì ìŽ íëŠìì ì ìëíì§ ìì ê²ìŽëŒê³ ìê°í©ëë€.
ëë ìŽ ë§ì ëìíë€.
@cuviper
ì ì믞ë ? ìŽììë ìŽë¯ž ìì ì ì ëë€. ì€ì Try ížë ìŽížë§ ë¶ìì íë©° 몚ë ë³ê²œ ì¬íì Option ë° Resultì ëíŽ ëìŒí ìì ì ìž íšê³Œë¥Œ ì ì§íŽìŒ í©ëë€.
ìŽê²ì 몚ë ìëìë ë§ì°¬ê°ì§ì ëê¹?
ì¢ ë ìŒë°ì ìŒë¡ ë§íìë©Ž .await
, ?/
early return, Option::map, Result::map, Iterator::map in rust, ê·žë¬ë ìŽê²ë€ìŽ 몚ë ìŽë€ 구조륌 ê³µì íë€ë ê²ì ìŽíŽíë©Ž ë¶ëª
í ë ëì íë¡ê·žëëšžê° ëë ë° ëììŽ ë©ëë€.
OTê° ëìŽ ì£ì¡í©ëë€.
ì êž°ì/ìëì
ìŽ ?
ëìê°ë§ì ë³ê²œí ì ìëì§ íì€íì§ ìì§ë§ 맀í¬ë¡ì ê°ì êµì°š ìì 묞ì ê° ë§ìŽ ë³µì¡íŽì§ëë€.
ìì ì± ë³Žì¥ ë° ìí¬í¬ RFCì ëí ëì íŽìì ?
ëì(ì€í ëë êž°í)ìŽ ë³ê²œë ì ìì§ë§ Option
/ Result
ì íì ëí íì¬ ëìì ê·žëë¡ ì ì§ëìŽìŒ íë€ë ê²ì
ëë€. ê·žê²ì 깚ë ê²ì ì°ëŠ¬ê° ì ë¹íí ì ìë ê²ë³Žë€ íšì¬ ë ë§ì ìŽíì ìŒêž°í ê²ìŽêž° ë묞ì
ëë€.
Option
ê° Result
ëí ì í ë³ì¹ìŽëŒë©Ž ìŽë»ê² ë©ëê¹? ì륌 ë€ìŽ type Option<T> = Result<T, NoValue>
, Option::<T>::Some(x) = Result::<T, NoValue>::Ok(x)
, Option::<T>::None = Result::<T, NoValue>::Err(NoValue)
? 구ííë €ë©Ž ë§ë²ìŽ íìíê³ íì¬ ìžìŽ í겜ììë íì€ì ìŽì§ ìì§ë§ íìí ê°ì¹ê° ìì ì ììµëë€.
Option
Result
ê° ê³ ì í ì íìž ê²ì ìì¡Žíë í¹ì± implsê° ìêž° ë묞ì ìŽ ë³ê²œì ìíí ì ììµëë€.
ì°ëŠ¬ê° ê·žê²ì 묎ìíë©Ž, ì°ëŠ¬ë í ëšê³ ë 걞늎 ì ìê³ , ì¬ì§ìŽ ìëë¡ bool
ë³ì¹ì Result<True, False>
, True
ë° False
ëšì ì íì
ëë€.
Try
impl륌 ()
ëšìë¡ ì¶ê°íë ê²ìŽ ê³ ë €ëììµëê¹? ì묎 ê²ë ë°ííì§ ìë íšìì 겜ì°, ë¡ê¹
ìœë°±ê³Œ ê°ìŽ ì€ìíì§ ìì íšììì ì€ë¥ê° ë°ìí ê²œì° ì¡°êž° ë°íìŽ ì¬ì í ì ì©í ì ììµëë€. ìëë©Ž ìŽë€ ìí©ììë ì€ë¥ë¥Œ ì¡°ì©í 묎ìíì§ ìë ê²ìŽ ë°ëì§íêž° ë묞ì ì ëìŽ ì ìžëììµëê¹?
ìëë©Ž ìŽë€ ìí©ììë ì€ë¥ë¥Œ ì¡°ì©í 묎ìíì§ ìë ê²ìŽ ë°ëì§íêž° ë묞ì ì ëìŽ ì ìžëììµëê¹?
ìŽê². ì€ìíì§ ìì 컚í
ì€ížìì ì€ë¥ë¥Œ 묎ìíë €ë©Ž unwrap
ëë ê·ž ë³í ì€ íë륌 ì¬ì©íŽìŒ í©ëë€.
foo() -> ()
ì ê°ì ê²ì ?
륌 ì¬ì©í ì ìë€ë ê²ì ì¡°ê±Žë¶ ì»ŽíìŒ ì»ší
ì€ížìì ë§€ì° ì ì©í ê²ìŽë©° ê°ë ¥íê² ê³ ë €íŽìŒ í©ëë€. ëë ê·žê²ìŽ ë¹ì ì ì§ë¬žê³Œ ë€ë¥Žë€ê³ ìê°í©ëë€.
unwrap ëë ê·ž ë³í ì€ íë륌 ì¬ì©íŽìŒ í©ëë€.
unwrap()
ë íšëì ì ë°íë¯ë¡ ì€ìíì§ ìì 컚í
ì€ížììë ì¬ì©íì§ ìë ê²ìŽ ì¢ìµëë€. ëšì ë°íìŽ íìí ìí©ììë ì ì íì§ ììµëë€. ìì€ ìœëìì ?
ì ëª
ìì ìŽê³ ê°ìì ìž ì¬ì©ìŒë¡ ìžíŽ ?
ê° ìì í "칚묵"ëì§ ìëë€ë 죌ì¥ì í ì ììµëë€. ìŽë° ììŒë¡ ?
ë° unwrap()
ë ë°í ìë¯žê° ë€ë¥Œ ë¿ ëšì íšìì ì ì¬í©ëë€. ëŽê° 볌 ììë ì ìŒí ì°šìŽì ì unwrap()
ë ê°ìì ìž ë¶ìì©ì ë§ë€ê³ (íë¡ê·žëš ì€ëš / ì€í ì¶ì ìžì) ?
ë ê·žë ì§ ìë€ë ê²ì
ëë€.
íì¬ ëšì íšììì ì¡°êž° ë°íì ìžì²Ž ê³µíì Result
ëë Option
ë°ííë ê²ë³Žë€ ìë¹í ëì©ëë€. ìë§ë ìŽë¬í ìí©ì ì¬ì©ì ê° ìŽë¬í ê²œì° Result
ëë Option
ì ë°í ì íì ì¬ì©íŽìŒ íê³ API륌 ë³ê²œíëë¡ ìžìŒí°ëžë¥Œ ì ê³µíêž° ë묞ì ë°ëì§í ì ììµëë€. ìŽë 쪜ìŽë PRìŽë 묞ìì ëšì ë°í ì íì ëí ì€ëª
ì í¬íšíë ê²ìŽ ì¢ìµëë€.
foo() -> ()
ì ê°ì ê²ì?
륌 ì¬ì©í ì ìë€ë ê²ì ì¡°ê±Žë¶ ì»ŽíìŒ ì»ší ì€ížìì ë§€ì° ì ì©í ê²ìŽë©° ê°ë ¥íê² ê³ ë €íŽìŒ í©ëë€. ëë ê·žê²ìŽ ë¹ì ì ì§ë¬žê³Œ ë€ë¥Žë€ê³ ìê°í©ëë€.
ìŽë»ê² ìëí ê¹ì? íì Ok(())ë¡ íê°íê³ ë¬Žìíìê² ìµëê¹?
ëí ìŽê²ì ìŽëì ì¬ì©íê³ ì¶ìì§ ì륌 ë€ìŽì£Œì€ ì ììµëê¹?
ì, MyCollection::pushì ê°ì í목ì 컎íìŒ ìê° êµ¬ì±ì ë°ëŒ Result<(), AllocError> ë°í ê° ëë () ë°í ê°ì ê°ì§ ì ìë€ë ìê°ìŽ ë€ììµëë€. 컬ë ì
ì ì¬ì©íë ì€ê° ìœëë ê·žê²ì ëíŽ ìê°í íìê° ììŒë¯ë¡ ë°í ì íìŽ ()
겜ì°ìë _íì_ ?
륌 ì¬ì©í ì ìë€ë©Ž ížëŠ¬í ê²ì
ëë€.
ê±°ì 3ë ìŽ ì§ë ì§êž, ìŽ ë¬žì ê° íŽê²°ëêž°ì ë ê°ê¹ìµëê¹?
@Lokathor ë ë°í ì í Result<Result<X,Y>,Z>
ëë ìŽì ì ì¬í ê²ìŽ ê°ë¥íì§ ìì 겜ì°ìë§ ìëí©ëë€. íì§ë§ ê·žê²ì. ë°ëŒì ë¶ê°ë¥í©ëë€.
ê³ìžµíë ê²°ê³Œê° ë¬žì 륌 ìŒìŒí€ë ìŽì 륌 ìŽíŽíì§ ëª»í©ëë€. ììží ì€ëª íŽ ì£Œìê² ìµëê¹?
ìíž ì°žì¡° 목ì ì ìíŽ @dureuillìŽ ëŽë¶ì ëì ê³µìì ì ìíìµëë€.
@ë¡ì¹Ží 륎
ì¢ì, ëë ê·žê²ì ëíŽ ë ê¹ìŽ ìê°íê³ ëŽê° ì€íë € ì¢ì ì€ëª
ì ì°Ÿìì ìë ìë€ê³ ìê°í©ëë€.
묞ì ë ë°í ì íì íŽììŽë ìŽìí 죌ììŽ ìœë륌 ë³µì¡íê² ë§ëë ê²ì
ëë€. ê°ë¥íì§ë§ ìœë륌 ìœêž°ê° ë ìŽë €ìì§ëë€. (ì¬ì 조걎: #[debug_result]
ì ìíë ëìì ì ì©íê³ Result::Err(...)
륌 ë°ííë ëì ëŠŽëŠ¬ì€ ëªšëìì íšëíëë¡ íšì륌 ìì íê³ Result::Ok
íì§ë§ ê·ž ë¶ë¶ì ê¹ë€ë¡ìµëë€)
#[debug_result]
fn f() -> Result<X, Y>;
#[debug_result]
fn f2() -> Result<Result<A, B>, Y>;
#[debug_result]
fn g() -> Result<X, Y> {
// #[debug_result_spoiled]
let w = f();
// w could have type X or `Result<X,Y>` based on a #[cfg(debug_...)]
// the following line would currently only work half of the time
// we would modify the behavoir of `?` to a no-op if #[cfg(not(debug_...))]
// and `w` was marked as `#[debug_result]`-spoiled
let x = w?;
// but it gets worse; what's with the following:
let y = f2();
let z = y?;
// it has completely different sematics based on a #[cfg(debug_...)],
// but would (currently?) print no warnings or errors at all,
// and the type of z would be differently.
Ok(z)
}
ë°ëŒì ìœë륌 ìœêž°ê° ë ìŽë €ìì§ëë€.
ëšìí ?
ì ëìì no-opìŒë¡ ìì í ì ììµëë€.
í¹í #[debug_result]
ì ë°í ê°ìŽ ìì ë³ìì ì ì¥ëê³ ëì€ì ?
ì°ì°ìë¡ "ìë ì í"ëë 겜ì°. ê·žê²ì ?
ì ì믞륌 ì ë§ë¡ íŒëì€ëœê² ë§ë€ ê²ì
ëë€. ìëíë©Ž "ìì± ìê°"ì ë°ëì ìë €ì§ì§ ìê±°ë ìì€ ìœë륌 ìœë ê²ë§ìŒë¡ë ì¶ìž¡íêž° ìŽë €ìž ì ìë ë§ì "ë³ì"ì ìì¡Žíêž° ë묞ì
ëë€. #[debug_result]
ë íšì ê°ìŽ í ë¹ë ë³ì륌 ë§ì¹ íìê° ìì§ë§, íëì íšìê° #[debug_result]
ë¡ íìëê³ ë€ë¥ž íëë íìëì§ ììŒë©Ž ìëíì§ ììµëë€. ì륌 ë€ìŽ ë€ìì ì í ì€ë¥ì
ëë€.
// f3 is not annotated
fn f3() -> Result<X, Y>;
// later inside of a function:
// z2 needs to be both marked spoiled and non-spoiled -> type error
let z2 = if a() {
f3()
} else {
f()
};
// althrough the following would be possible:
let z2_ = if a() {
f3()?
} else {
f()?
};
"ì 늬í" ì룚ì
ì í¹ì 컎íìŒ íëê·žê° ì€ì ëê³ ì€ë¥ë¡ 구ì±ë ë íšëì ìŒìŒí€ë DebugResult<T, E>
ì íìŒ ì ìì§ë§ ê·žë ì§ ììŒë©Ž Result<T, E>
ì ëìŒí©ëë€. ê·žë¬ë ê·žê²ì íì¬ ì ììŒë¡ë ê°ë¥í ê²ìŽëŒê³ ìê°í©ëë€.
@zserik ì ë§ì§ë§ ê²ì묌ì ëµì¥: ì€ëª íì 맀í¬ë¡ë 묎ì믞í©ëë€. ë¹ë 구ì±ì êž°ë°ìŒë¡ íë ë°í ì íì íšì륌 ì²êµ¬íë©Ž ìíë ë°©ìì êŽê³ììŽ ì ìŒí ë¹ë 구ì±ì ì ìží 몚ë ê°ë¥í ë¹ë 구ì±ìì êž°ë¥ ê²°ê³Œì ëí 몚ë ìŒì¹ê° ì€ëšë©ëë€.
@tema3210 ìê² ìµëë€ . @Lokathor ì ììŽëìŽë ìŒë°ì ìŒë¡ ì€ì ë¡ ìëíì§ ìëë€ë ì ì ì§ì íê³ ì¶ììµëë€. ë¶ë¶ì ìŒë¡ ìëí ì ìë ì ìŒí ê²ì ë€ì곌 ê°ì§ë§ ë§ì ì í ì¬íìŽ ìêž° ë묞ì ì¥êž°ì ìŒë¡ ê°ì¹ê° ìë€ê³ ìê°í©ëë€.
// the result of the fn *must* have Try<Ok=()>
// btw. the macro could be already implemented with a proc_macro today.
#[debug_result]
fn x() -> Result<(), XError> {
/* ..{xbody}.. */
}
// e.g. evaluates roughly to:
//..begin eval
fn x_inner() -> Result<(), XError> {
/* ..{xbody}.. */
}
#[cfg(panic_on_err)]
fn x() {
let _: () = x_inner().unwrap();
}
#[cfg(not(panic_on_err))]
fn x() -> Result<(), XError> {
x_innner()
}
//..end eval
fn y() -> Result<(), YError> {
/* ... */
// #[debug_result] results can't be matched on and can't be assigned to a
// variable, they only can be used together with `?`, which would create
// an asymetry in the type system, but could otherwise work, althrough
// usage would be extremely restricted.
x()?;
// e.g. the following would fail to compile because capturing the result
// is not allowed
if let Err(z) = x() {
// ...
}
}
@zserik ì€ì ë¡ ìŽë° íí륌 ì·šíë ê²ìŽ ê°ë¥í©ëê¹?
#[cfg(panic_on_err)]
fn x() -> Result<(), !> {
let _: () = x_inner().unwrap();
}
#[cfg(not(panic_on_err))]
fn x() -> Result<(), XError> {
x_innner()
}
ì¢ì, ì¢ì ìê°ìŽìŒ.
ìŽê²ìŽ ìì í ìŽì ì ì€ëª
ëìŽìŒ íë ê²ìžì§ íì€íì§ ìì§ë§ ì€ë¥ ë°í ì¶ì ì 구ííë ë° êŽì¬ìŽ ììŒë©° Try
í¹ì± ëë ì ìŽë ì ê³µë implì ëí ë³ê²œìŽ í¬íšëë€ê³ ìê°í©ëë€. Result
륌 ì¬ì©íì¬ ìëíëë¡ í©ëë€. ê²°êµ ëë ìŽê²ì RFCë¡ ë°ê¿ ê³íìŽì§ë§, ëŽê° ë§í RFC륌 ìì±íë ë° ìê°ìŽ 걞늎 겜ì°ë¥Œ ëë¹íì¬ ëì€ì ì¶ê°í ì ìëë¡ íë ë°©ììŒë¡ try í¹ì±ìŽ ìì íëì§ ììëì§ íìžíê³ ì¶ìµëë€. Ʞ볞 ììŽëìŽë ìŽê²ìŽë€.
ìŽì ë²ì 곌ì ížíì±ì ì ì§íêž° ìíŽ Tì ëí í¹ìí ë° êž°ë³ž implì ì¬ì©íë ì¶ì ì 볎륌 ì ë¬íë ë° ì¬ì©íë í¹ì±ìŽ ììµëë€.
pub trait Track {
fn track(&mut self, location: &'static Location<'static>);
}
default impl<T> Track for T {
fn track(&mut self, _: &'static Location<'static>) {}
}
ê·žëŠ¬ê³ ë¹ì ì ìì Try
ëí 구í Result
ì¬ì©íì¬ track_caller
íê³ ëŽë¶ íìŒë¡ìŽ ì 볎륌 ì ë¬,
#[track_caller]
fn from_error(mut v: Self::Error) -> Self {
v.track(Location::caller());
Self::Err(v)
}
ê·žë° ë€ì ì¶ì ì 구ííêž° ìíŽ ìì¶ì ì ìì§íë €ë ì íì ëíŽ
#[derive(Debug, Default)]
pub struct ReturnTrace {
frames: Vec<&'static Location<'static>>,
}
impl Track for ReturnTrace {
fn track(&mut self, location: &'static Location<'static>) {
self.frames.push(location);
}
}
ì¬ì©ë²ì ë€ì곌 ê°ìŽ ëë©ëë€.
#![feature(try_blocks)]
use error_return_trace::{MyResult, ReturnTrace};
fn main() {
let trace = match one() {
MyResult::Ok(()) => unreachable!(),
MyResult::Err(trace) => trace,
};
println!("{:?}", trace);
}
fn one() -> MyResult<(), ReturnTrace> {
try { two()? }
}
fn two() -> MyResult<(), ReturnTrace> {
MyResult::Err(ReturnTrace::default())?
}
ê·žëŠ¬ê³ ìì¶ì ì ì죌 íížìë ë²ì ì ì¶ë ¥ì ë€ì곌 ê°ìµëë€.
ReturnTrace { frames: [Location { file: "examples/usage.rs", line: 18, col: 42 }, Location { file: "examples/usage.rs", line: 14, col: 16 }] }
ê·žëŠ¬ê³ ì¬êž°ì íëì ëí ê°ë ìŠëª ìŽ ììµëë€. https://github.com/yaahc/error-return-traces
ëë ì°ëŠ¬ê° ížë ìŽíž 구í ì륌 ìíŽ ë³íí ì ìë ì€ë¥ ì íì íëë§ ë¶ì¡±í ì ìë€ê³ ìê°íì¬ ë€ì곌 ê°ì ìží°íìŽì€ë¥Œ ì ê³µí ì ììµëë€.
trait Try{
type Error;
type Ok;
fn into_result(self)->Result<Self::Ok,Self::Error>;
fn from_ok(val: Self::Ok)->Self;
fn from_error<T>(val: T)->Self;
}
컎íìŒë¬ë From::from
ížì¶ì íŒíêž° ìíŽ from_error
ëšìŒííí ì ììŒë©° ë€ë¥ž ì€ë¥ ì íì ëíŽ ìëìŒë¡ impl ë©ìë륌 ì ê³µí ì ììŒë¯ë¡ ?
ì°ì°ìê° ë€ë¥ž "ìžëí" êž°ë¥ì ìíí ì ììµëë€. ì€ë¥ ì í.
fn from_error<T>(val: T)->Self;
ìì±ë ëë¡ êµ¬íìë _몚ë _ í¬êž°ì T
륌 ì í ììŽ ìëœíŽìŒ í©ëë€. ìŽê²ì ì¬ì©ì ì ì ì ííëë¡ íë €ë©Ž Try<T>
ì ê°ì í¹ì± 맀ê°ë³ìì¬ìŒ í©ëë€. ìŽê²ì @scottmcm ìŽ https://github.com/rust-lang/rust/issues/42327#issuecomment-457353299ì ììë TryBlock
/ Bubble<Other>
ì¡°í©ê³Œ ì ì¬ í©ëë€.
ìì±ë ëë¡ êµ¬íìë _any_ í¬êž°ì
T
륌 ì í ììŽ ìëœíŽìŒ í©ëë€. ìŽê²ì ì¬ì©ì ì ì ì ííë €ë©ŽTry<T>
ì ê°ì í¹ì± 맀ê°ë³ìì¬ìŒ í©ëë€. ìŽê²ì @scottmcm ìŽ #42327(comment) ì ììëTryBlock
/Bubble<Other>
ì¡°í©ê³Œ ì ì¬ í©ëë€.
ì¬ì©ë²ì ë€ì곌 ê°ììŒ í©ëë€.
trait Try{
//same from above
}
struct Dummy {
a: u8,
}
struct Err1();
struct Err2();
impl Try for Dummy {
type Ok=();
type Error=();
fn into_result(self)->Result<Self::Ok,Self::Error>{
std::result::Result::Ok(())
}
fn from_ok(val: Self::Ok)->Self{
Self{a: 0u8}
}
fn from_error<T>(val: Err1)->Self where T == Err1{
Self{a: 1u8}
}
fn from_error<T>(val: Err2)->Self where T == Err2{
Self{a: 2u8}
}
}
Tryì TryFromError륌 ë¶ëŠ¬íŽìŒ í©ëë€. ëë ìë ì ì fwiwë³Žë€ ê·žê²ì ë ì¢ìíì§ë§ ìë¡ìŽ RFCê° íìí ê²ìŽëŒê³ ìê°í©ëë€.
(ê·žëŠ¬ê³ ëë ì¬ì í "ìë"ëì "ì í"ëŒê³ ë¶ë¬ìŒíë€ê³ ìê°íì§ë§ ëë íì í©ëë€)
@tema3210 ëë ë¹ì ì ìë륌 ìŽíŽíë€ê³ ìê°íì§ë§ ê·žê²ì ì íší Rustê° ìëëë€.
@SoniEx2
Tryì TryFromError륌 ë¶ëŠ¬íŽìŒ í©ëë€.
ë§ì, ê·žëì ëŽê° TryBlock
/ Bubble<Other>
ëììžì ìžêží ê²ìŽë€. ëª
ëª
ì íì ëíŽ ë
Œìí ì ìì§ë§ ì¡°êž° ë°íìŽ íì _ì€ë¥_ì êŽí ê²ì ìëëŒë ììŽëìŽì
ëë€. ì륌 ë€ìŽ, ë§ì ëŽë¶ Iterator
ë©ìëê° ì¬ì©ì ì ì LoopState
ì íì ì¬ì©íê³ ììµëë€. find
ì ê°ì ê²œì° ì°Ÿê³ ìë ê²ì ì°Ÿë ê²ì ì€ë¥ê° ìëì§ë§ ì¬êž°ì ë°ë³µì ì€ì§íê³ ì¶ìµëë€.
ëª ëª ì íì ëíŽ ë Œìí ì ìì§ë§ ì¡°êž° ë°íìŽ íì ì€ë¥ ì첎ì êŽí ê²ì ìëëŒë ìê°ìŽììµëë€.
ì íí ëŽê° "ìë"ëŒë ìŽëŠì ì¢ìíì§ ìê³ "ì í"ëŒë ìŽëŠì ì ížíë ìŽì ë "ì¡°êž°"륌 "ì í"íêž° ë묞ì ëë€. return :p
(ìŽê²ìŽ ìë¯žê° ìëì§ íì€íì§ ììµëê¹? ì§ëë²ì "ì í"ëŒë ê²ì ìžêžíì ë ìŽë€ ìŽì ë¡ ëìê²ë§ ìë¯žê° ììê³ ë€ë¥ž ì¬ëë€ìê² ì€ëª í ì ìììµëë€.)
ëë²ê·ž ì 볎(ì: íìŒ/ëŒìž ë²íž)륌 êž°ë¡íêž° ìíŽ ë¡ê·ž íí¬ fe륌 ì¶ê°íêž° ìíŽ êž°ë³ž ?
ëì fe륌 ë®ìŽì°ë €ê³ í ë ìŽ í¹ì±ìŽ ëììŽ ë ê¹ì?
íì¬ stdlib 맀í¬ë¡ ë®ìŽì°êž°ê° ì§ìëì§ë§ ?
ì°ì°ìê° ëª
ìì ìŒë¡ try!
맀í¬ë¡ë¡ ë³íëì§ ìë ê² ê°ìµëë€. ìŽìŽ ìììŽ.
@stevenroose Try
ížë ì ìë§ ì§ìì ì¶ê°íë €ë©Ž ?
"ë°ìí" ìì¹ì ëí íìŒ ìì¹ ì 볎륌 í¬íšíëë¡ Try
ížë ìì ìì íŽìŒ í©ëë€. .
@stevenroose
Try
ížë ì ìë§ ì§ìì ì¶ê°íë €ë©Ž?
"ë°ìí" ìì¹ì ëí íìŒ ìì¹ ì 볎륌 í¬íšíëë¡Try
ížë ìì ìì íŽìŒ í©ëë€. .
ìŽê²ì ì¬ì€ìŽ ìëëë€. #[track_caller]ë í¹ì± ì ìì 죌ììŽ í¬íšëì§ ìì 겜ì°ìë í¹ì± implsì ì¬ì©í ì ììµëë€.
@stevenroose ê° ê·íì ì§ë¬žì ëëµí©ëë€. ì, íì§ë§ 몚ë ?
ìì¹ë¥Œ ìžìíë ë° êŽì¬ìŽ ìë€ë©Ž ì€ë¥ê° ì íëë ìì ì€ë¥ ë°í ì¶ì 죌ìì íìžíŽìŒ í©ëë€.
https://github.com/rust-lang/rust/issues/42327#issuecomment -619218371
ëêµ°ê° ìŽë¯ž ìŽê²ì ìžêžíëì§ íì€íì§ ììµëë€. impl Try for bool
, ìë§ë Try<Ok=(), Error=FalseError>
?
ì°ëŠ¬ê° ìŽë° ìŒì í ì ìëë¡
fn check_key(v: Vec<A>, key: usize) -> bool {
let x = v.get_mut(key)?; // Option
x.is_valid()?; // bool
x.transform()?; // Result
true
}
ìŽì ?
ê° ìœë륌 íšì¬ ë ëª
ííê² ë§ë€ ì ìë€ê³ ìê°íë ëë¶ë¶ì 겜ì°ì ë°í ì í Option<()>
ì ì¬ì©íŽìŒ í©ëë€.
ëêµ°ê° ìŽë¯ž ìŽê²ì ìžêžíëì§ íì€íì§ ììµëë€.
impl Try for bool
, ìë§ëTry<Ok=(), Error=FalseError>
?
ìŽê²ì ë§ë€ ê² Try
ì²ëŒ íë &&
ì ìŽìì bool
ë€. ììì ë€ë¥ž ì¬ëë€ìŽ ì§ì íë¯ìŽ ì±ê³µ ì ëšëœì ëí ì¬ì© ì¬ë¡ë ììµëë€. ìŽ ê²œì° Try
ë ||
ì²ëŒ ìëíŽìŒ í©ëë€. &&
ë° ||
ì°ì°ìë ì
ë ¥íë ë° ìê°ìŽ ì€ë ê±žëŠ¬ì§ ìêž° ë묞ì ìŽ êµ¬íì ìŽì ë ë³ë¡ ììµëë€.
@calebsander ì¹ì í ëµë³ ê°ì¬í©ëë€.
ê·žê²ì ëªëª ê°ëší 겜ì°ì íŽë¹íì§ë§, ì죌 ê·žë° ê²œì°ë ìëëŒê³ ìê°í©ëë€. í¹í ííììì let x = v.get_mut(key)?
ì ê°ì ëì
묞ì ê°ì§ ì ìììµëë€.
&&
ë° ||
ê° íì ížëŠì ìííë ê²œì° Option
ë° Error
ëíŽ Option
.unwrap_or_else()
, .and_then()
ë¡ íë ìŽí ìë ììµëë€. Error
ìŒìŽì€.
í륎ë ìœë륌 &&
ë° ||
ííí ì ììµëê¹?
fn check_key(v: Vec<A>, key: usize) -> bool {
let x = v.get_mut(key)?; // Option
x.not_valid().not()?; // bool
for i in x.iter() {
if i == 1 { return true }
if i == 2 { return false }
debug!("get {}" i);
}
let y = x.transform()?; // Result
y == 1
}
true
ì€íšë¥Œ ì믞íê³ false
ì±ê³µì ì믞íë ìŒë¶ 조걎ì ê²œì° !expr?
ê° íŒëë ì ìì§ë§ expr.not()?
륌 ì¬ì©íì¬ ížëŠì ìíí ì ììµëë€(ì°žê³ : ops::Try
, ì°ëŠ¬ë íì false
ëíŽ Error
)
ê·žê²ì ëªëª ê°ëší 겜ì°ì íŽë¹íì§ë§, ì죌 ê·žë° ê²œì°ë ìëëŒê³ ìê°í©ëë€. í¹í ííììì
let x = v.get_mut(key)?
ì ê°ì ëì 묞ì ê°ì§ ì ìììµëë€.
êžì, ëŽê° ë¹ì ì ì ìì ì€íŽíì§ ìë í Try<Ok = (), Error = FalseError>
ëíŽ bool
Try<Ok = (), Error = FalseError>
륌 구ííë ê²ì ìŽê²ì íì©íì§ ììµëë€. ?
ì°ì°ìê° None
륌 false
ë¡ ë³íí ì ìëë¡ impl From<NoneError> for FalseError
ë íìí©ëë€. (ê·žëŠ¬ê³ ë§ì°¬ê°ì§ë¡ ì ì© í ê²œì° ?
ì Result<T, E>
ë°ííë ëŽë¶ íšì bool
, ë¹ì ìŽ íì impl From<E> for FalseError
. ëë ê·žë° ìê° ìŒêŽ 구íì 묞ì ê° ë ì ììµëë€.) ë°í ê° Result<bool, bool>
묞ì ê° ìë ê²œì° some_option().ok_or(false)?
ë° some_result().map_err(|_| false)?
륌 ì¬ì©í ìë ììµëë€( .unwrap_or_else(|err| err)
ì¶ìí ì ìì).
ë€ë¥ž Try
ì€ë¥ë¥Œ bool
ë¡ ë³ííë 묞ì ë ì ì³ëê³ bool
ëíŽ ì ìíë Try
구íì &&
ì°ì°ì
fn using_try() -> bool {
some_bool()?;
some_bool()?;
some_bool()
}
귞늬ê³
fn using_and() -> bool {
some_bool() &&
some_bool() &&
some_bool()
}
(ë¬Œë¡ ()
ê° ìë ê°ì ë°ííë if
ë° loop
ê°ì ì ìŽ íëŠì ë²ìíêž°ê° ë ê°ëší©ëë€.)
true
ì€íšë¥Œ ì믞íê³false
ì±ê³µì ì믞íë ìŒë¶ 조걎ì 겜ì°!expr?
ê° íŒëë ì ìì§ë§expr.not()?
륌 ì¬ì©íì¬ ížëŠì ìíí ì ììµëë€(ì°žê³ :ops::Try
, ì°ëŠ¬ë íìfalse
forError
)
false
ê° Error
ì¬ë¡ë¥Œ ëíëŽìŒ íë€ë ê²ìŽ ëª
ííì§ ììµëë€. (ì륌 ë€ìŽ, Iterator.all()
ë false
ê° ëšëœëꞰ륌 ìíì§ë§ Iterator::any()
ë ëì true
륌 ìí©ëë€.) ì§ì íë¯ìŽ, ?
ì ë¬ë ê°ì ë°ì (ë° íšìì ë°í ê°ë ë°ì )íì¬ ë°ë ëšëœ ëì. íì§ë§ ê·žë ê² íŽì ê°ë
ì±ìŽ ì¢ì ìœëê° ëì¬ ê²ìŽëŒê³ ë ìê°íì§ ììµëë€. ë ê°ì§ ë€ë¥ž ëìì 구ííë ë³ëì struct
s And(bool)
ë° Or(bool)
륌 ê°ë ê²ìŽ ë í©ëŠ¬ì ìŒ ì ììµëë€.
ê·žëŠ¬ê³ ë§ì°¬ê°ì§ë¡ ì ì²íë €ë©Ž ? 결곌ì
boolì ë°ííë íšì ëŽìì ë€ìì ìííŽìŒ í©ëë€. FalseErrorì 겜ì°. ëë ê·žë¬í ì ë©Žì ìž êµ¬íìŽ ë¬žì ê° ë ê²ìŽëŒê³ ìê°í©ëë€.
ìëì, ì ë impl From<T> for FalseError
íê³ ì¶ì§ ììµëë€. ìë§ë result.ok()?
falseê° ì€ë¥ ì¬ë¡ë¥Œ ëíëŽìŒ íëì§ë ë¶ëª íì§ ììµëë€.
true
륌 Some
맀ííë bool::then
ê° ìì ë ìì°ì€ëœê² ìê°í©ëë€.
ëŽê° ëì³€ë€ë©Ž ì©ìíŽ ì£Œìžì - ì NoneError
impl std::error::Error
? ìŽê²ì Box<dyn Error>
ëë ìŽì ì ì¬í ê²ì ë°ííë 몚ë íšìì ìžëªšê° ììµëë€.
ëŽê° ëì³€ë€ë©Ž ì©ìíŽ ì£Œìžì - ì
NoneError
implstd::error::Error
? ìŽê²ìBox<dyn Error>
ëë ìŽì ì ì¬í ê²ì ë°ííë 몚ë íšìì ìžëªšê° ììµëë€.
ì 묞ê°ë ìëì§ë§ "ëê° None
ìŽê³ Some
ê° ë ê²ìŒë¡ ììíìµëë€"ì ëí ì ì©í ì€ë¥ ë©ìì§ë¥Œ ìì±íë €ê³ ìëíë ë° ì¬ê°í 묞ì ê° ììì ì ì ììµëë€(Ʞ볞ì ìŒë¡ ì¬êž°ìì ì»ì ì ììµëë€ -- ìœê°ì ì§ëš ë©ìì§). ëŽ ê²œíì Option::ok_or_else
ê²°í©ì륌 ëì ì¬ì©íì¬ ë€ë¥ž ì€ë¥ ì íì ì¬ì©íë ê²ìŽ íì ê°ì¥ í©ëŠ¬ì ìŽììµëë€.
@ErichDonGublerì ëìí©ëë€. ?
륌 Option
?
ì íšê» ì¬ì©í ì ìë€ë ê²ì ë§€ì° ì±ê°ì ìŒì
ëë€. ê·žë¬ë ìŽë íë¹í ìŽì ê° ììŒë©° ìžìŽ ì¬ì©ìë¡ì ì€ë¥ë¥Œ ì¬ë°ë¥Žê² ì²ëŠ¬íë ê²ìŽ 몚ë ì¬ëìê² ê°ì¥ ì¢ì ìŒìŽëŒê³ ìê°í©ëë€. ?
ìííë ëì None
ì€ë¥ 컚í
ì€ížë¥Œ ë°ìžë©íë ì¶ê° ìì
ì ìííë ê²ì ì ë§, ì ë§ ì§ìŠëë ìŒìŽì§ë§, ì€ë¥ë¥Œ ì ëë¡ ì ë¬íëë¡ ê°ì íë¯ë¡ 충ë¶í ê°ì¹ê° ììµëë€.
None
ì€ë¥ë¡ íŽìí ì ìë ì ìŒí 겜ì°ë íë¡í íìŽíìŽ ë§€ì° ê±°ì¹ ëì
ëë€. Option::todo_err()
ížì¶ê³Œ ê°ì ê²ì ì¶ê°íë©Ž ëŽë¶ ê°ì Ok
ê° ë°íëì§ë§ None
ì íšëìŽ ë°ìí ê²ìŽëŒê³ ìê°íìµëë€. ìœë ìì±ì "ê±°ì¹ íë¡í íìŽí" 몚ëì íìì±ì ë¶ìí ëê¹ì§ë ë§€ì° ì§êŽì ìŽì§ ììµëë€. Ok(my_option.unwrap())
ì ë§€ì° ì ì¬íì§ë§ Ok(...)
ëíìŽ íìíì§ ììµëë€. ëí "todo" í¹ì±ì ëª
ìì ìŒë¡ ì§ì íì¬ íë¡ëì
ë¡ì§ìì ìŽ ìœë륌 ì ê±°íê³ ì ì í ì€ë¥ ë°ìžë©ìŒë¡ ë첎íë €ë ìë륌 ì ë¬í©ëë€.
ê·žë¬ë ììì ë¹í©í ê²ì ëë€
ìŽê²ì unwrap
ëë¬ìŒ íë€ê³ ê°íê² ëëëë€. todo_errì ì¶ê°íë©Ž ì€ì ì€ë¥ ì íì ë°ííŽìŒ íë¯ë¡ ë°íí ì€ë¥ ì íì ëí ì§ë¬žìŽ íìí©ëë€.
ëí ëë fn todo_err(self) -> Result<Self, !>
ìŽ ìì í륌 ìíŽ !
륌 ì구íë ëª
ë°±í 묞ì ê° ìì ê²ìŽëŒê³ ìê°í©ëë€. ìŽ, êžìì, ìžì ê°.
ëŽ ì ì€ ìŒìŽì€ë ì€ì ë¡ ì€ë¥ì ëíŽ ë묎 ì 겜 ì°ì§ ìë ê±°ì¹ íë¡í íìŽíì
ëë€. NoneError
ì ì²Žê° ê·íê° ëìŽí ìŽë¬í 묞ì ë¡ ê³ íµë°ê³ ìì§ ììµëê¹? ê·žê²ìŽ ì¡Žì¬íŽìŒ íë€ê³ ê²°ì ëë©Ž(ì ìŽë íë¡í íìŽíì ììŽìë ì¢ì ìŒìŽëŒê³ ìê°í©ëë€), Error
ëŒë ìŽëŠìŽ ë¶ì ê²ì²ëŒ ììíŽìŒ íë€ê³ ìê°í©ëë€.
ìŽ implìŽ ìë ì í ë묞ì .ok_or("error msg")
륌 ëëëŠ¬êž°ë§ íìµëë€. ìŽ ë°©ë²ë ìëíì§ë§ ë ížëŠ¬í©ëë€.
ê°ì¥ ì ì©í ëêž
ìŽ êž°ë¥ì íì¬ ìíë 묎ìì ëê¹?