https://github.com/rust-lang/rfcs/pull/1859ããã®Try
ç¹æ§; PRhttps ïŒ//github.com/rust-lang/rust/pull/42275ã§å®è£
ãããŠã
ããããããããããã«https://github.com/rust-lang/rust/issues/31436ããåå²ã
Iterator::try_fold
ãå®è£
ã§ããããã«ãªããŸãfold
ãtry_fold
芳ç¹ããå®è£
ããŠãäž¡æ¹ããªãŒããŒã©ã€ãããå¿
èŠããªãããã«ãããšäŸ¿å©ã§ããïŒãã€ã¯ã·ã§ãã£ã³ã°ã®ããã€ãã®éšåïŒ
æã
ã¯ãé¢é£ããã¿ã€ããåŒã³åºãããã®ç¹å®ã®åæ©ãæã£ãŠããŸããError
ã®ä»£ããã«Err
ïŒ ãããåŒã³åºãErr
ããã¯ãšæŽåããã ããResult
ïŒä»ã®äžã€ã¯ãã§ã«åŒã³åºããOk
ã
ä»ã®into_result
ãšãã察称çãªåäžã®from_result
代ããã«ãå¥ã
ã®from_error
ã¡ãœãããšfrom_ok
ã¡ãœãããæã€ããšã«ç¹å¥ãªåæ©ããããŸããïŒç¹æ§ã®ååïŒ
ïŒ RFCããã®ãã¬ã€ã°ã©ãŠã³ããªã³ã¯ã®æŽæ°ããŒãžã§ã³ïŒ
@glaebhoerl
Error
ãšErr
ã¯ã httpsïŒ //github.com/rust-lang/rust/issues/33417#issuecomment -269108968ããã³TryFrom
ã«é¢é£ããŠè°è«ãããŸããã github.com/rust-lang/rust/pull/40281; åæ§ã®çç±ã§ããã§ååãéžã°ãããšæããŸããT:Try
ã«å€ããããšããŠããResult
ãæã£ãŠããããšã¯ãã£ãã«ãªããšæããŸãã ç§ã¯åžžã«Try::from_result(Ok(
ãšTry::from_result(Err(
åŒã³åºããããã Try::from_ok
ãšTry::from_error
ã奜ãã§ãäžèŽãæžãåºãããã2ã€ã®ã¡ãœãããåçŽåããã ãã§æºè¶³ããŠããŸãã ããããããã¯ã into_result
ãInto<Result>
ã§ã¯ãªãããåæ Œãäžåæ ŒãããšèããŠããããã§ããç¹å®ã®ã¿ã€ãã¯ãéèŠã§ãªãå®è£
ã®è©³çŽ°ãšããŠResult
ã§ãã ïŒãã ããããããã¥ãŒã¹ããªã¥ãŒãšã¢ãŒãªãŒãªã¿ãŒã³ã«ã¯æ°ããã¿ã€ããããã¯ãã§ãããææ¡ãããåéãããããããããŸãããïŒãããŠãããã¥ã¡ã³ãã«ã€ããŠã¯ã from_error
ã?
ã«ã€ããŠè©±ããŠããã®ã奜ãã§ãã throw
ïŒã from_ok
ã¯ãäž¡æ¹ãåãã¡ãœããã«ããã®ã§ã¯ãªããæåã©ããã³ã°ïŒïŒ41414ïŒã«ã€ããŠèª¬æããŸããããããã®ã³ã¡ã³ãã®æ£ãããã©ãŒã©ã ã§ãããã©ããã¯ããããŸãããããã§ãªãå Žåã¯ãªãã€ã¬ã¯ãããŠãã ããïŒ smiley:ã ããããããã¯https://github.com/rust-lang/rfcs/pull/1859ã«ããã¯ãã§ãã³ã¡ã³ãæéãéããŸããã ãã£ãšã£ãšïŒ
Try
ãã¬ã€ããåå²ãããã into_result
ã¡ãœãããåé€ãããããå Žåãããã®ã§ã¯ãªãããšæã£ãŠããŸããã ç§ã«ãšã£ãŠçŸåšã Try
ã¯ãç¹æ§FromResult
ïŒ from_error
ãšfrom_ok
ïŒãšIntoResult
ïŒ 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
ã§ãã
FromResult
ãstruct FutureResult: Future
ããã«èªç¶ã«å®è£
ã§ããŸãã
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
ã®æ£èŠã®éžæè¢ã¯ãããŸããã äžåºŠãããã¯ããããã¯ããŸãã¯ããŒãªã³ã°ããããšã¯æçšãããããŸãããããããã®ã©ããæ®éçã«æçšã§ã¯ãªãããã§ãã Try
ã«into_result
ããªãã£ãå Žåã¯ãäžèšã®ããã«æ©æçµäºãå®è£
ã§ããŸãããŸãã Future
ãResult
ã«å€æããå¿
èŠãããå Žåã¯ãä»»æã®Try
ïŒé©åãªã¡ãœããã§å€æã§ããŸãïŒãããã¯ããã«ã¯wait
ã¡ãœãããåŒã³åºãã poll_once() -> Result<T,E>
åŒã³åºããªã©ïŒã
Option
ãåæ§ã®ã±ãŒã¹ã§ãã from_ok
ã from_err
ã¯Try
ãã¬ã€ãRFCã®ããã«èªç¶ã«å®è£
ããã Option<T>
ão.ok_or(Missing)
ç°¡åã«Result<T, Missing>
å€æã§ããŸãã o.ok_or(Missing)
ãŸãã¯äŸ¿å©ãªã¡ãœããok_or_missing
ã
ã圹ã«ç«ãŠã°å¹žãã§ãã
ç§ã¯ããã«éåžžã«é
ããŠãããããããŸããããä»é±æ«ã ?
ã¯ã_success_ã§ç絡ãããå Žåã«ãããªãèªç¶ãªã»ãã³ãã£ã¯ã¹ãæã£ãŠããããšã«æ°ã¥ããŸããã
fn fun() -> SearchResult<Socks> {
search_drawer()?;
search_wardrobe()
}
ãã ãããã®å Žåã Try
ç¹æ§ã¡ãœããã®ååã¯é©åããŸããã
ãã ãã ?
æŒç®åã®æå³ãåºãããŸãã
ã¬ãŒãšã³ã®try_fold
ãããã¿ã€ããäœæããéã«ã Consumer::full()
ã¡ãœããã«Try::is_error(&self)
ãããªãã®ãå¿
èŠã§ããããšã«æ°ä»ããŸããã ïŒæ¶è²»è
ã¯åºæ¬çã«ããã·ã¥ã¹ã¿ã€ã«ã®ã€ãã¬ãŒã¿ã§ãããããRayonã«ã¯ããããããŸããããšã©ãŒãç絡ããããã®ã§ããïŒä»£ããã«äžéå€ãResult<T::Ok, T::Err>
ãšããŠæ ŒçŽããŠã Result::is_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ã¿ã€ãã®ããããã§ããã å解ãšåæ§ç¯ãååã«äžè¬çã§ããããããé©åã«æé©åãããç¹æ§ã«é¢ããäžé£ã®ç¹å¥ãªã¡ãœãããå¿
èŠãªãããšãé¡ã£ãŠããŸãã
@ErichDonGublerããã¯è¿œè·¡ã®åé¡ã§ããããã察å¿ããã³ãŒããå®å®ãããŸã§è§£æ±ºãããŸããã
äœéšã¬ããŒãïŒ
ç§ã¯ãã®ç¹æ§ãå®è·µããããšããŠå°ãã€ã©ã€ã©ããŸããã ãªãããã®çç±ã§Result
ã«ç¬èªã®ããªã¢ã³ããå®çŸ©ããããšæãããšãäœåºŠããããŸããããæçµçã«Result
ã«ãªã£ããšãã¯ãäž»ã«Try
å®è£
ããããã§ãã å®å
šã«ã¯ããããŸããã
äŸïŒ
Chalk VMã®æ°ãããœã«ããŒã§ã¯ããã¹ãã©ã³ããã解決ããçµæã瀺ãåæåãå¿ èŠã§ããã ããã«ã¯4ã€ã®å¯èœæ§ããããŸããã
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
ãåãã¿ã€ãã§ããã®ã¯èªç¶ãªããšOk
ã ããã§å®è£
ãèŠãããšãã§ããŸãïŒ https ïŒ
å®éããããæ©èœãããã«ã¯ããªãåçŽãªãã¿ãŒã³ãããããã§ãã
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
ïŒã§ããããšããããã代ããã«åæåãäœæããŸããã
itertoolsã§ãšãå
éšé¢æ°ãåžžã«Err
è¿ããšããå¥åŠãªNone
ãIterator::next()
ããã®ããšã©ãŒãã§ãããšãããã®å¥åŠãªåæããããŸãããåæã«ãæåŸã«å°éããå¿
èŠãããããã fold
ããã®ãæåãã§ããè¡ãããªããã°ã ãããŠãçµäºæ¡ä»¶ã®äŒæãåŠçããããã«?
ïŒRust 1.12ã§ã³ã³ãã€ã«ããå¿
èŠãããããããã®ã³ãŒãã§ã¯try!
ã䜿çšãããšéåžžã«äŸ¿å©ã§ãã
ãããã£ãŠãä»ã«äœããªããšããŠããç§ãTry
ã«ã€ããŠæžãã説æã¯ééã£ãŠãããšæããŸãããæå/倱æã®äºåæ³ãã«ã€ããŠè©±ãã®ã§ã¯ãªããããšã©ãŒãããæœè±¡åããå¿
èŠããããŸãã
ç§ãèããŠãããã1ã€ã®ããšã¯ã Try
å°ãã¯ã¬ã€ãžãŒãªå®è£
ãæ€èšããå¿
èŠããããšããããšã§ãã ããšãã°ã Ordering: Try<Ok = (), Error = GreaterOrLess>
ããtryfunctionsããšçµã¿åããããšã 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)?;
}
ãããã¯ã¬ã€ãžãŒãªã®ãæªãã®ãã¯ãŸã ããããŸããïŒç¬ãïŒç¢ºãã«ããã¯ããçšåºŠã®åªé ããæã£ãŠããŸããããããç©äºãç°ãªããšããªãã¯ããããç°ãªãããšãç¥ã£ãŠããããã§ãã ãããŠããã®ããããã®åŽã«ãæåãââãŸãã¯ããšã©ãŒããå²ãåœãŠãããšãããšãããŸãé©åããªãããã§ãã
ãŸããããã¯ããšã©ãŒå€æãã圹ã«ç«ããªããã1ã€ã®äŸã§ããããšã«ã泚æããŠãã ããã ãŸããäžèšã®ã欲ããã§ããïŒã§ããšã©ãŒã§ã¯ãããŸãããã®äŸã§ã¯äœ¿çšããŠããŸããã ãããŠãããã¯æšè«ã®æ²ãã¿ãåŒãèµ·ããããšã確ãã«ç¥ãããŠããã®ã§ãããã¯çµæã ãã«éå®ãããã¹ããã®ã§ãããã©ããçåã«æããŸãïŒãŸãã¯.map_err(Into::into)
ãæ¯æããŠåé€ãããå¯èœæ§ããããŸãããããã¯ããããå®è¡äžå¯èœã§ãïŒã
ç·šéïŒããããããŠãããããèªåã®ã¿ã€ãã«Try
ãå®è£
ãã代ããã«ããšã©ãŒã«Resultã䜿çšãç¶ãããã«å¯Ÿããçãããè¯ããããã¯æåŸ
ãããŠãããã§ãããã©ããçåã«æããŸãã
ç·šé2ïŒããã¯äžèšã®https://github.com/rust-lang/rust/issues/42327#issuecomment-318923393ãšåãã§ã
ç·šé3ïŒ Continue
ããªã¢ã³ããhttps://github.com/rust-lang/rfcs/pull/1859#issuecomment-273785250ã§ææ¡ãããããã§ã
ç§ã®2ã»ã³ãïŒ
ç¹æ§ã2ã€ã®ç¹æ§ã«åå²ãããšãã@fluffysquirrelsã®ææ¡ã奜ãinto_result
ãŸãã¯åçã®ãã®ãç¶æããå¿
èŠããããšæããŸãã ãããŠã Try
ãå®å®ããã®ã§ããã®æç¹ã§Option
ã䜿çšããå¿
èŠããããšæããŸãã
ãŸãããšã©ãŒ/ OKã§ã¯ãªããã¬ãŒã¯/ç¶è¡ã瀺åããååã䜿çšãããšãã@scottmcmã®ã¢ã€ãã¢ãæ°ã«å ¥ã£ãŠããŸãã
ããã«ç¹å®ã®ã³ãŒããå ¥ããããã«ãç§ã¯ãããã©ã®ããã«èªããã奜ãã§ãïŒ
ãã¡ãããã¹ãã¬ãŒãã«ãŒãã»ã©è¯ãã¯ãããŸãããããtryã¡ãœãããã䜿çšãããšã次ã®ããã«ãªããŸãã
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>
ãå®è£
ããå Žåãããã¯æ©èœãããšæããŸãã
ãã ããOptionãNoneã®å Žåã®ãšã©ãŒãæ瀺çã«æå®ã§ããããã«ã opt.ok_or(_)?
䜿çšããããšããå§ãããŸãã ããšãã°ãããªãã®äŸã§ã¯ã pb.file_stem
ãNoneã®å Žåãšã to_str()
ã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
䜿çšããŠãä»ã®ãšã©ãŒïŒstdããã®ãšã©ãŒãªã©ïŒãå
æ¬çãªfailure::Error
ã¿ã€ãã«Try
/ ?
ã§ããããã«ããŸãã
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
ãDisplay
implãæã£ãŠãã
å ·äœçãªææ¡ã«è¿ã¥ãããšããŠããŸã...
ç§ã¯TrySuccess
代æ¿åã奜ãã«ãªãå§ããŠããŸãã èå³æ·±ãããšã«ãç§ãå«ããŠ_nobody_ã¯ãããšããšããã奜ãã ã£ããšæããŸããRFCã®æçµããŒãžã§ã³ã«ãå«ãŸããŠããŸããã ããããããããããšã«ãããã¯æŽå²ã®äžã§çãç¶ããŠããŸãïŒ //github.com/rust-lang/rfcs/blob/f89568b1fe5db4d01c4668e0d334d4a5abb023d8/text/0000-try-trait.md#using -an-associated-type-for-the-success -䟡å€
ããã«å¯Ÿããæ倧ã®ç°è°ã¯ãé¢é£ããåïŒ 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;
}
?
æŒç®åããè¿ããããã®ãšããŠããã®é¢é£ä»ããããåã¯ãæããã«ååšããå¿
èŠãããåã§ããããŸãã ã€ãŸãããã³ãæ確ã«è¿°ã¹ããäžçš®ã®ãæ®äœãã¿ã€ããå®çŸ©ããå¿
èŠããã£ãããšããç
©ãããã«ã¯ã¶ã€ãããªããšããããšã§ãã ãããŠãããã()
ã¯åççã§ãããäžè¬çã§ããããã®ã§ã NoneError
ãããªããã¿ãé¿ããŸãã
ç·šéïŒãã€ã¯ã·ã§ããã®å Žåããreturnãã¯è¯ãèšèãããããŸãããããã¯ã try
ã¡ãœããïŒå¥åok-wrappingïŒããreturn
ãããšãã«çºçããããã§ãã return
ã¯ããã®iiucã®ã¢ããæŒç®ååã§ããããŸãã
ç·šé2ïŒä»ã®ç¹æ§/æ¹æ³ã«é¢ããç§ã®èãã¯ãŸã å®å®ããŠããŸããã@ tmccombsã
@scottmcmæ確ã«ããããã«ããŸãã¯æ¬¡ã®2ã€ã®ç¹æ§ãææ¡ããŸããïŒ
trait TryContinue {
type Continue;
fn from_continue(_: Self::Continue) -> Self;
}
trait Try<E>: TryContinue {
fn try(self) -> Result<Self::Continue, E>
}
ãããŠã x?
ãéé£ãããšã次ã®ããã«ãªããŸãã
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),
}
ããŸããŸãªæ£åœåïŒ
x?
åŒã®åãåžžã«åãã«ãªãããã«ãåŒæ°ã®åã«TryContinue
ãå¿
èŠã§ããtry_fold
ãããªåçŽãªã±ãŒã¹ã§ã¯ãtypeãã©ã¡ãŒã¿ãŒãããã©ã«ãã§Self
ã«èšå®ããããã T: Try
ã ãã§åé¡ãããŸãããTryContinue
æ¡åŒµããŸããããã¯ãæ»ãåãšããŠäœ¿çšãããåãæ¬äœã§?
ãèš±å¯ããå Žåãok-wrappingããµããŒãããå¿
èŠãããããã§ãã?
ã®åŒæ°ã¯æ±çšåã§ããããã TryContinue
ããäœãããSelf
ãçæãããããã«ãªããŸããtry{}
/ ?
ãã¯ããšã Option
ã Result
ãããã³Ordering
å®è£
ãå«ãå®å
šãªæŠå¿µå®èšŒãã¢ïŒ 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;
ïŒ impl<T> Throw<()> for Option<T>
ãããªãã®ãä»ããŠïŒ None
ãçæããæ¹æ³ã«ããããšãã§ããŸããããã¯ã throw NoneError;
ãããã¯ããã«åªããŠããŸããthrow LessOrGreater::Less
ã¯_æ¬åœã«_ã°ãããŠããããã§ããç·šéïŒPing @ glaebhoerl ã æãã§ããæèŠã
ç·šé2ïŒ https ïŒ ãã ããã
æ¬è³ªäž»çŸ©çã¢ãããŒãã¯ãäžèšã®ç®æšãç ç²ã«ããããšãªããéå 䞻矩è ã®åªé ãã®äžéšãæ¡çšã§ããã®ã ãããã
ç§ã¯ãã®ææ¡ãæ¬åœã«å¥œãã§ãã
ã¹ããŒæ§æãäœã§ãããã¯ããã»ã©æçœã§ã¯ãããŸãã
ä»ã®èšèªããã®throwããŒã¯ãŒãã®æè·ç©ãç¡èŠãããšããthrowãã¯ãããé«ãã¹ã³ãŒããŸã§å€ããã¹ããŒããããšããç¹ã§ãããæå³ã§æå³ããããŸãã Pythonãšscalaã¯ããšã©ãŒã®å Žå以å€ã«å¶åŸ¡ãããŒã®äŸå€ã䜿çšããŸãïŒãã ããscalaã®å Žåãéåžžã¯çŽæ¥try / catchã䜿çšããŸããïŒããã®ãããæåãããã¹ã«throwã䜿çšããåäŸãããã€ããããŸãã
@tmccombs
ä»ã®èšèªããã®throwããŒã¯ãŒãã®æè·ç©ãç¡èŠãããšããthrowãã¯ãããé«ãã¹ã³ãŒããŸã§å€ããã¹ããŒããããšããç¹ã§ãããæå³ã§æå³ããããŸãã
åæ§ã®æè·ç©ãä»å±ããŠããŸããããã¬ã€ãºãã®æ¹ãé©ããŠãããšæããŸãã
æããïŒvïŒïŒæãã€ããããã«ãããå Žæãäœçœ®ãç¶æ ãªã©ã«å ¥ããããå ¥ããããå ¥ãããããããšïŒ
äžããïŒvïŒïŒããé«ãäœçœ®ã«ç§»åããŸãã æã¡äžãã; ææ Œ
ãraiseãã?
ã®ããžãã¯ãšçµã¿åãããæ¹æ³ããããããããŸãããããã¯ãraiseããcollectããæå³ããå Žåãããããã§ãã Ok(v) => v, Err(e) => raise From::from(e)
ã«ãªããŸããããã§ã raise
ã¯äžèŽãããã¿ãŒã³ãæš¡å£ããŸãïŒããšãã°ããã¿ãŒã³Err(e)
äžãããããšã ControlFlow::Break(Err(...))
æ§æäžã®éæ³ã«ãªããŸãïŒã
ãã¬ã€ãºãã®æ¹ãé©ããŠãããšæããŸã
ããèŠç¹ã
@scottmcm
ã¹ããŒæ§æãäœã§ãããã¯ããã»ã©æçœã§ã¯ãããŸãã
from_err(value: Other)
ãæãŠãªãçç±ã¯ãããŸããïŒ
æŽæ°ïŒå®éã Other
ã®åœ¹å²ã«ã€ããŠæ··ä¹±ããŠãããããããŸããã ç§ã¯ãã®ç¹æ§ãããå°ãç 究ããå¿
èŠããããŸãã =ïŒ
@nikomatsakis
from_err(value: Other)
ãæãŠãªãçç±ã¯ãããŸããïŒ
ãããšã Other
ã¯å®å
šã«?
ãªã¿ã€ãïŒ Result
ãããªïŒãªã®ã§ã throw Ok(4)
ãæ©èœãããããããŸããã ïŒãããŠã人çºçãªãšã©ãŒã¿ã€ãã®å°å
¥ã匷å¶ããããšãé¿ããããã«ãå®å
šãªè«çåã§ããå¿
èŠããããŸããïŒããšãã°ãçŸåšã®Option-Resultçžäºéçšã¯ããïŒããã³ãã®éïŒãšåçã§ãããšæããŸãã
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>
äž¡æ¹ãå®è£
ã§ããŸããthrow;
ã ããæå¹ã«ããimpl<T> TryBreak<()> for Option<T>
ã¯ãé¢é£ãããšã©ãŒã¿ã€ã()
ãããã§ã¯ãªãã£ãæ¹æ³ã§ãã£ãšãããããšæããŸããimpl<T> TryBreak<!> for T
ãããã§ãããããããããäžè²«æ§ããããŸãããïŒäœè«ã§ããããããã®ç¹æ§ãšã¡ãœããåã¯ã²ã©ãã§ããå©ããŠãã ããïŒïŒ
ããã§æèµ·ãããä»ã®åé¡ã«ã€ããŠã®ç§ã®èãã¯ããŸã æ確ã«è¡šçŸã§ãã圢ã«ã¯ãªããŸãããã From::from()
è±ç³ã«é¢ããåæšè«ã®åé¡ã«é¢ããŠïŒãããæè¿ã©ããã§è°è«ããããã©ããã¯æãåºããŸããïŒ ããŸãã¯ããã ãïŒïŒïŒ
ããã®ããã«åæšè«ã®ãããŸãããããããšããæ¬èœçãªæèŠïŒäž»ãªãã®ã§ã¯ãããŸãããïŒã¯ãå
ã®RFCã®äžéšãšããŠFrom
å€æãæãŸãªãã£ãçç±ã®
ã€ãŸãã From::from()
[ãªãã·ã§ã³ïŒæåã§èšè¿°ãããã®ã§ã¯ãªãã ?
è±ç³ã«ãã£ãŠæ¿å
¥ããããã®]ã衚瀺ããã2ã€ã®ã¿ã€ãã®ã©ã¡ãããæ£ç¢ºã«ç¥ã£ãŠãããšæããŸãïŒå
¥å察åºåïŒãããäžæ¹ã¯ãããŸãã§ãããããã©ã«ãã§ã¯ããäžæ¹ã¯1ã€ãšåãã«ãªããŸãã ã€ãŸããã©ã®impl From
ã䜿çšããããæ確ã§ãªãå Žåãããã©ã«ãã§impl<T> From<T> for T
èšå®ããããšæããŸãã ããã¯ãåºæ¬çã«åžžã«ããªããå®éã«æ¬²ãããã®ã ãšæããŸããïŒ ããã¯å°ãã¢ãããã¯ãããããŸãããããããæ©èœããå Žåãã¡ãªããã¯ç§èŠã®ã³ã¹ãã«èŠåãã ãã®äŸ¡å€ãããããã§ãã
ïŒ From
ã¯ãæ£ç¢ºã«ã¯?
è±ç³ã®ããã«ããã§ã«langã¢ã€ãã ã ãšæããŸããããããã§ã¯ãªãããã§ãïŒãããã«ããããã®çç±ã§ãã§ã«ããã€ãã®ç¹ã§ç¹å¥ã§ãã ãïŒ
@scottmcmã®ææ¡ã§ã¯ã From::from()
ã¯è±ç³ã®äžéšã§ã¯ãªãã Result
ã®Try
ã®å®è£
ã«å«ãŸããŠããŸãã
@tmccombsç§ã¯åœŒã®ææ¡ã®ä¿®æ£ãææ¡ããŠããŸããã§ããã
try{}
RFCïŒhttps://github.com/rust-lang/rfcs/pull/2388ïŒã¯ãçµæãæ°ã«ããªãtry
ãããã¯ã«ã€ããŠè°è«ããŠããŸããã ãã®ä»£æ¿æ段ã¯ãå¿
èŠã«å¿ããŠãšã©ãŒã¿ã€ããå®å
šã«ç¡èŠããããšãéžæã§ããããããããé©åã«åŠçã§ããããã§ãã
let IgnoreErrors = try {
error()?;
none()?;
};
以åãšåãç¹æ§ã䜿çšããæŠå¿µå®èšŒã®å®è£ ïŒ https ïŒ stable
ç¹ã«ãã«ã¹ã¿ã å®è£
ã§ã¯çµæãååŸããŠE: Debug
ããã€ã³ãããã ãã§ãçºçãããšã©ãŒãèªåçã«ãã°ã«èšé²ã§ãããããèå³æ·±ãå¯èœæ§ãããã€ããããšæããŸãã ãŸãã¯ã main
ãšTermination
ãªã¿ãŒã³åãšããŠç¹å¥ã«æå³ãããããŒãžã§ã³ãäœæããŠãè€éãªåã®çœ²åãªãã§?
ã䜿çšã§ããããã«ããããšãã§ããŸãïŒhttps ïŒ//github.com/rust-lang/rfcs/issues/2367ïŒã
@nikomatsakisãæ¢åã®ããŒãžã§ã³ã®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>;
}
äž»ãªå€æŽç¹ã¯ã Continue
é¢é£ä»ããããã¿ã€ããã FromTry
ïŒä»¥åã®TryContinue
ïŒã§ã¯ãªãTry
ãã¬ã€ãã«ããããšã§ãã å®çŸ©ãåçŽåããã ãã§ãªããããã¯ãšããå©ç¹ãããTry
ãšã¯ç¬ç«ããŠå®è£
ããããšãã§ããŸãFromTry
ç§ã¯ããäžè¬çã§ãããšæå®ããããããŠããã¯å®è£
FromTry
ç°¡ç¥åãããŠããããäžåºŠTry
ãå®è£
ãããŠããŸãã ïŒæ³šïŒ Try
ãšFromTry
åæã«å®è£
ããå¿
èŠãããå Žåã¯ã from_try
ã¡ãœãããTry
移åããã ãã§ãïŒ
Result
ãšOption
å®è£
ãå«ãå®å
šãªéã³å Žãšããã®éã³å Žã§ã®Rocketã®Outcome
ãã芧ãã ããã
å ±åããŠãããŠããããšãã@ SergioBenitezïŒ ãã®å®è£ ã¯ãRFC 1859ã®å ã®ç¹æ§ææ¡ã®ãã¿ã€ããã©ã¡ãŒã¿ãå転ããã代æ¿ããŒãžã§ã³ãšäžèŽããŸãïŒ https ïŒ
倱ãæ倧ã®ããšã¯ã typeof(x?)
ãtypeof(x)
ã®ã¿ã«äŸåãããšããç¹æ§ã§ãã ãã®ããããã£ã®æ¬ åŠã¯ããªãªãžãã«ã®æžå¿µäºé
ã®1ã€ã§ããïŒããããã®è¡ã«æ²¿ã£ãã³ãŒãã®èªã¿ãããã«ã€ããŠå°ãå¿é
ããŠããŸããhttps://github.com/rust-lang/rfcs/pull/1859#issuecomment-279187967ïŒãå©ç¹ããããŸããæçµçãªåæžäž»çŸ©è
ã®ææ¡ã®ïŒãä»»æã®ã¿ã€ãTã«å¯ŸããŠãïŒã¯æ£ç¢ºã«1çš®é¡ã®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
ãšã¯ç¬ç«ããŠå®è£ ã§ãããšããå©ç¹ããããŸããããã¯ãç§ãããäžè¬çã§ãããšèããŠããŸãã
確ãã«ä»æ¥ã Try
ãšdo catch
ã¯äžå®å®ã§ããããã from_ok
ã¯ããŸãäžè¬çã§ã¯ãããŸããã ãŸãã do catch
ãå®å®ããŠããŠããå
šäœã§?
æªæºã§äœ¿çšãããããšã«åæããŸãïŒãã®ãããªãããã¯ã®ã»ãšãã©ã«ã¯è€æ°ã®?
ãå«ãŸããŠããããïŒã
ãã ããç¹æ§ãšãã®æäœã®èŠ³ç¹ãããããã£ãªã¢ã¿ã€ãã§ãç¶ç¶ãå€ãã©ãããããããšã¯?
絶察ã«äžå¯æ¬ ãªéšåã ãšæããŸãã ä»æ¥ããã®ç¹æ§ãééããããšã¯ãã£ãã«ãããŸãã-代ããã«Ok(...)
ãŸãã¯Some(...)
䜿çšããã ãã§ã-ããããããã¯äžè¬çãªäœ¿çšæ³ã«ãšã£ãŠéèŠã§ãã ããšãã°ã try_fold
ïŒ
é¢æ°ããã£ãªã¢ã¿ã€ããè¿ãå Žåã¯ã察象ã®å€ããã®ãã£ãªã¢ã¿ã€ãã«å ¥ããæ¹æ³ãããããšãéèŠã§ãã ãããŠãéèŠãªããšã«ããããæäŸããããšã¯å°é£ã§ã¯ãªããšæããŸãã çµæããªãã·ã§ã³ãçµæãªã©ã®éåžžã«èªç¶ãªå®çŸ©ããããŸãã
@Centrilã¯ãŸãããã¹ã«ã©ãŒããã£ãªã¢ã«ã©ããããããçè«çã«ã¯ããåçŽãªæ§æã§ããããšã以åã«ææããŸããã ããšãã°ãHaskellã¯ãããPointed
ã¯ã©ã¹ãšåŒãã§ããŸãããRustã§ã¯äžè¬åããããªããšæããŸãã try { 4 }
èš±å¯ãã⊠vec![4]
ã¯ç§ã«ã¯ããéãã®ããã§ãã
ãŸãããããã¯å€ãæªæ¥ã«ã©ããããããã«async
é¢æ°ãææ¡ãããŠããããã«ããããã¯å€ããã©ãŒã«ãã«ã¿ã€ãã«ã©ããããtry
é¢æ°ããããããããªãæªæ¥ãæ³åããŠããŸãã ããã§ãã TryContinue
ãéèŠãªéšåã§ãã throw
æ§é ãååŸããå Žåããã®ãããªé¢æ°ã¯?
䜿çšããªãå¯èœæ§ããããŸãã
ã€ãŸããæ®å¿µãªãããããã¯å ·äœçãªãã®ãããå²åŠçãªãã®ã§ãã ãããæå³ããªããã©ããããŸãã¯ããªããããããã®éšåã§å察ã ãšæããã©ããç§ã«ç¥ãããŠãã ããïŒslightly_smiling_faceïŒ
ç·šéïŒããã®åæããŒãžã§ã³ãèšèŒãããã¡ãŒã«ãåãåã£ãå Žåã¯ãè©«ã³ããŸãã ãã³ã¡ã³ãããæŒãã®ãæ©ããã...
倱ãããæ倧ã®ããšã¯ãtypeofïŒxïŒïŒãtypeofïŒxïŒã®ã¿ã«äŸåãããšããç¹æ§ã§ãã
ããã絶察ã«ã ãããææããŠãããŠããããšãã
ãã¡ãããããããã£ãäžèŠãŸãã¯å¶éãå€ããããšããè°è«ããããŸããããFCPã®åã®æçµçãªèŠçŽã§ã¯ãããã¯ãŸã å©ç¹ãšããŠãããŸããïŒrust-lang / rfcsïŒ1859ïŒã³ã¡ã³ãïŒïŒã
å¶éãå³ããããå¯èœæ§ã®ããå ·äœçãªäŸã¯ãããŸããïŒ
é¢æ°ããã£ãªã¢ã¿ã€ããè¿ãå Žåã¯ã察象ã®å€ããã®ãã£ãªã¢ã¿ã€ãã«å ¥ããæ¹æ³ãããããšãéèŠã§ãã ãããŠãéèŠãªããšã«ããããæäŸããããšã¯å°é£ã§ã¯ãªããšæããŸãã
ããã¯å ¬æ£ãªåæã ãšæããŸãã åæããŸãã
@SergioBenitezhttps ïŒ //github.com/rust-lang/rfcs/pull/1859#issuecommentãã-279187967
ã ããåé¡ã¯ãææ¡ãããå¶éã¯ååã§ããïŒ æåã¿ã€ãã決å®ããéã«ãšã©ãŒã±ãŒã¹ã³ã³ããã¹ãã®é©åãªäœ¿çšæ³ã¯ãããŸããïŒ èåŸ ã®å¯èœæ§ã¯ãããŸããïŒ
å°æ¥ã®ç§ã®çµéšãããããã«ã¯ããã€ãã®æçšãªã±ãŒã¹ããããããããªããšèšãããšãã§ããŸãã ç¹ã«ãããªãã話ããŠããæ祚ã¿ã€ãã¯ãããã€ãã®æ¹æ³ã§åŠçã§ããŸãã 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
é¢æ°ã®my_result?
ã¯ãæåã¿ã€ããéåžžãšåãã§ããïŒåæã³ãŒããéåæã³ã³ããã¹ãã§åãããã«æ©èœãç¶ããããã«éèŠïŒããšã©ãŒããªã¢ã³ããæ£åžžã«å€æããããããããã¯å¿
èŠãããŸããã ã 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
ç¹æ§ãå®å®åããããšã¯æ±ºããŠãããŸããNoneError
ããã䜿çšããŸãã®ã§ãå®å®ãããŸã§å¿
èŠããããŸã?
ã«Option
ã¯ããã«äººéå·¥åŠã«åºã¥ããŸããã struct MyCustomSemanthicalError;
ãããªãšã©ãŒããŸãã¯Default
å®è£
ãããšã©ãŒã«ã€ããŠã¯ããããèæ
®ããŠãã ããã None
ã¯ã 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>
ã§ãã ããã¯ãæšæºã©ã€ãã©ãªãOption<T>
ã«å¯ŸããŠæ¬¡ã®ããã«Try
ãå®è£
ããŠããå Žåã«å¯èœã§ãããšæããŸããããããæ瀺çã«ãã¹ãããŠããããç¹æ®åã®åé¡ããããšæããŸãã
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
å€æã§ããªããããããã¯éåžžã«é¢åã«ãªããŸããããã·ã¥ãããã§åçŽãªã«ãã¯ã¢ããã倱æããããšããããããŸãïŒããã¯ãšã©ãŒã§ã¯ãããŸããïŒã ïŒ-1åã®ã³ãŒã«ããã¯ã§?
æŒç®åã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 ïŒ
@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ã¯ããããå®å®ãããå床éãå¿
èŠããããŸãã
ç·šéïŒãã®ããã®è¿œè·¡ã¢ã€ãã ã§opãæŽæ°ããŸãããscottmcm
Try
ç¹æ§ããã®ã¹ã¬ããã§ææ¡ãããŠãã代æ¿æ¡ã®ããããã«çœ®ãæããèšç»ã¯ãããŸããïŒ @scottmcmã«ãã£ãŠææ¡ãããããŒãžã§ã³ã¯åé¡ãªãããã§ãã ç§ã¯åŒãç¶ã䜿çšãã?
ãšæŒç®åOption
ããšç§ã¯èããŠTry
圢質ã¯åŒ·å¶ããªãããã«å€æŽããå¿
èŠããããŸãResult
äžã®ã»ãã³ãã£ã¯ã¹ãOption
ã
@scottmcmã®ä»£æ¿æ段ã䜿çšãããšã ?
ãOption
ãšãšãã«äœ¿çšããŠã NoneError
ãåãé€ãããšãã§ããŸãã ç§ã¯@nikomatsakis ïŒã³ã¡ã³ãïŒã«åæããŸãã Try
ç¹æ§ã¯ãã Option
ã倱æããè¡šãã¿ã€ãã人çºçã«å®çŸ©ãããå¿
èŠæ§ãä¿é²ãããã®ã§ã¯ãããŸããã
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ã¯ãããã°ãå®è£ ã§ããªããããæšç§»çãªãããã°ã䜿çšããŠçµæã«ã¢ã³ã©ãããããã«ããŒãå¿ èŠã«ãªãå ŽåããããŸãã
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>
ããŸããŸããïŒã¢ããã¹ããªãŒã ã¿ã€ãã®ã¢ããã¹ããªãŒã ç¹æ§ãæ瀺ããããšã¯ã§ããŸããïŒ
ããšãã°ãããã䜿çšããŠãçµäºã®ãããã°ãªã¿ãŒã³ãååŸã§ããŸãã
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
ã ?/
ã¢ãŒãªãŒãªã¿ãŒã³ãOption :: mapãResult :: mapãIterator :: map in rustãã®ãããªæŠå¿µãçµ±äžããããšã¯äžå¯èœã ãšæããŸããããããããããã¹ãŠãäœããã®æ§é ãå
±æããŠããããšãç解ããããšã¯ãç§ãããåªããããã°ã©ããŒã«ãªãã®ã«ééããªã圹ç«ã¡ãŸãã
OTã§ããããšããè©«ã³ããŸãã
ãšããã¯/ãšãã£ã·ã§ã³ã§?
è±ç³ãå€æŽã§ãããã©ããã¯ããããŸããããããã¯ç¢ºãã«ãã¯ãã®ãããªå€ãã®ã¯ãã¹ã¯ã¬ãŒãã®æžå¿µãè€éã«ããŸãã
å®å®æ§ã®ä¿èšŒãšãšããã¯RFCã®ç§ã®è§£éã§ã¯ã ?
åäœïŒç ç³ãŸãã¯ãã®ä»ïŒã¯å€æŽãããå¯èœæ§ããããŸããã Option
/ Result
ã¿ã€ãã§ã®çŸåšã®åäœã¯ç¶æããå¿
èŠããããŸããããç Žããšãç§ãã¡ãæ£åœåããããšãæãã§ãããããã¯ããã«å€ãã®è§£çŽãçºçãããããåãã§ãã
Option
ã©ããããããResult
ã¿ã€ããšã€ãªã¢ã¹ã ã£ãå ŽåOption
ã©ããªããŸããïŒ ã€ãŸãã 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
ãç°ãªãã¿ã€ãã§ããããšã«äŸåãããã¬ã€ãã®å®è£
ãããããããã®å€æŽãè¡ãããšã¯ã§ããŸããã
ãããç¡èŠãããšãããã«äžæ©é²ãã§ã bool
ãResult<True, False>
ãšã€ãªã¢ã¹ã«ããããšãã§ããŸããããã§ã True
ãšFalse
ã¯ãŠãããã¿ã€ãã§ãã
ãŠããã()
Try
implãè¿œå ããããšã¯æ€èšãããŠããŸããïŒ äœãè¿ããªãé¢æ°ã®å Žåããã®ã³ã°ã³ãŒã«ããã¯ãªã©ã®éèŠã§ãªãé¢æ°ã§ãšã©ãŒãçºçããå Žåã§ããæ©æã®æ»ãã圹ç«ã€å ŽåããããŸãã ãŸãã¯ãã©ã®ãããªç¶æ³ã§ããšã©ãŒãé»ã£ãŠç¡èŠããªãããšãæãŸããããããŠãããã¯é€å€ãããŸãããïŒ
ãŸãã¯ãã©ã®ãããªç¶æ³ã§ããšã©ãŒãé»ã£ãŠç¡èŠããªãããšãæãŸããããããŠãããã¯é€å€ãããŸãããïŒ
ãã®ã éèŠã§ãªãã³ã³ããã¹ãã§ãšã©ãŒãç¡èŠãããå Žåã¯ã unwrap
ãŸãã¯ãã®ããªã¢ã³ãã®1ã€ã䜿çšããå¿
èŠããããŸãã
foo() -> ()
ãããªãã®ã§?
ã䜿çšã§ããããšã¯ãæ¡ä»¶ä»ãã³ã³ãã€ã«ã®ã³ã³ããã¹ãã§éåžžã«åœ¹ç«ã€ããã匷ãæ€èšããå¿
èŠããããŸãã ããã¯ããªãã®è³ªåãšã¯éããšæããŸãã
unwrapãŸãã¯ãã®ããªã¢ã³ãã®1ã€ã䜿çšããå¿ èŠããããŸãã
unwrap()
ã¯ãããã¯ãåŒãèµ·ããã®ã§ãéèŠã§ãªãç¶æ³ã§äœ¿çšããããšã¯ãå§ãããŸããã åçŽãªè¿åãå¿
èŠãªç¶æ³ã§ã¯é©åã§ã¯ãããŸããã ãœãŒã¹ã³ãŒãã§?
ãæ瀺çãã€ç®ã«èŠãã圢ã§äœ¿çšãããŠããããã ?
ã¯å®å
šã«ããµã€ã¬ã³ããã§ã¯ãªããšããè°è«ãããããšãã§ããŸãã ãã®ããã«ã ?
ãšunwrap()
ã¯ãŠãããé¢æ°ã«é¡äŒŒããŠããŸãããæ»ãã®ã»ãã³ãã£ã¯ã¹ãç°ãªããŸãã ç§ãèŠãå¯äžã®éãã¯ã unwrap()
ã¯ç®ã«èŠããå¯äœçšïŒããã°ã©ã ã®å®è¡/ã¹ã¿ãã¯ãã¬ãŒã¹ã®åºåïŒãäœæãã ?
ã¯äœæããªãããšã§ãã
çŸåšããŠãããé¢æ°ãæ©æã«è¿ã人éå·¥åŠã¯ã Result
ãŸãã¯Option
è¿ã人éå·¥åŠãããããªãå£ã£ãŠããŸãã ãããã®å ŽåããŠãŒã¶ãŒã¯Result
ãŸãã¯Option
ãªã¿ãŒã³ã¿ã€ãã䜿çšããå¿
èŠãããããããããããã®ç¶æ³ãæãŸããã§ããããããã«ãããAPIãå€æŽããã€ã³ã»ã³ãã£ããæäŸãããŸãã ãããã«ãããPRãŸãã¯ããã¥ã¡ã³ãã«ãŠããããªã¿ãŒã³ã¿ã€ãã®èª¬æãå«ãããšããã§ãããã
foo() -> ()
ãããªãã®ã§?
ã䜿çšã§ããããšã¯ãæ¡ä»¶ä»ãã³ã³ãã€ã«ã®ã³ã³ããã¹ãã§éåžžã«åœ¹ç«ã€ããã匷ãæ€èšããå¿ èŠããããŸãã ããã¯ããªãã®è³ªåãšã¯éããšæããŸãã
ããã¯ã©ã®ããã«æ©èœããŸããïŒ åžžã«OkïŒïŒïŒïŒã«è©äŸ¡ãããç¡èŠãããŸããïŒ
ãŸãããããã©ãã§äœ¿ãããã®ããäŸãæããŠããã ããŸããïŒ
ãããMyCollection :: pushã®ãããªãã®ã¯ãã³ã³ãã€ã«æã®æ§æã«å¿ããŠãã³ã¬ã¯ã·ã§ã³ããšã©ãŒæã«ãããã¯ã«ãªãããã«æ§æãããŠããå ŽåãResult <ïŒïŒãAllocError>ã®æ»ãå€ãŸãã¯ïŒïŒã®æ»ãå€ãæã€å¯èœæ§ããããšããèãã§ããã ã³ã¬ã¯ã·ã§ã³ã䜿çšããäžéã³ãŒãã¯ããã«ã€ããŠèããå¿
èŠã¯ãªãã®ã§ããªã¿ãŒã³ã¿ã€ãã()
å Žåã§ããåã«_åžžã«_ ?
䜿çšã§ããã®ã§ããã°äŸ¿å©ã§ãã
ã»ãŒ3幎åŸãããã¯è§£æ±ºã«è¿ã¥ããŠããŸããïŒ
@Lokathorã¯ããªã¿ãŒã³ã¿ã€ãResult<Result<X,Y>,Z>
ãŸãã¯åæ§ã®ãã®ãäžå¯èœãªå Žåã«ã®ã¿æ©èœããŸãã ããããããã§ãã ãããã£ãŠãäžå¯èœã§ãã
éå±€åãããçµæãåé¡ãåŒãèµ·ããçç±ãããããŸããã 詳ããæããŠããã ããŸããïŒ
çžäºåç §ã®ç®çã§ã @ dureuillã«ãã£ãŠå éšã§ä»£æ¿ã®å®åŒåãææ¡ãããŠã
@Lokathor
ããããŸãããç§ã¯ããã«ã€ããŠãã£ãšæ·±ãèããŸããããããŠç§ã¯ããªãè¯ã説æãèŠã€ãããããããªããšæããŸãã
åé¡ã¯ãæ»ãå€ã®åã®è§£éããŸãã¯å¥åŠãªæ³šéãã³ãŒããä¹±éã«ããããšã§ãã ããã¯å¯èœã§ãããã³ãŒããèªã¿ã«ãããªããŸãã ïŒåææ¡ä»¶ïŒ #[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]
ã®æ»ãå€ãäžæå€æ°ã«ä¿åãããåŸã§?
æŒç®åã䜿çšããŠãtry-propagatedããããå Žåã ?
ã®ã»ãã³ãã£ã¯ã¹ã¯ãå€ãã®ãå€æ°ãã«äŸåãããããéåžžã«æ··ä¹±ããŸãããããã®å€æ°ã¯ããæžã蟌ã¿æãã«å¿
ãããèªèãããŠããªããããœãŒã¹ã³ãŒããèªã¿åãã ãã§ã¯æšæž¬ãé£ããå ŽåããããŸãã #[debug_result]
ã¯ãé¢æ°å€ãå²ãåœãŠãããå€æ°ãå°ç¡ãã«ããå¿
èŠããããŸããã1ã€ã®é¢æ°ã#[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ã®æåŸã®æçš¿ãžã®è¿ä¿¡ïŒããªãã説æãããã¯ãã¯ç¡æå³ã§ã-ãã«ãæ§æã«åºã¥ããŠé¢æ°ã®returnã¿ã€ãã課éãããšãå®è¡æ¹æ³ã«é¢ä¿ãªãã1ã€ã ããé€ããã¹ãŠã®å¯èœãªãã«ãæ§æã§é¢æ°ã®ãã¹ãŠã®äžèŽãå£ããŸãã
@ 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
ãã¬ã€ããŸãã¯å°ãªããšãæäŸãããŠããå®è£
ã®å€æŽãå«ãŸããŠãããšæããŸããããæ©èœãããããã«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)
}
ãããŠãããã¯ãã¬ãŒã¹ãåéãããã¿ã€ãã®å Žåã¯ãTrackãå®è£ ããŸã
#[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_error
åäžåããŠã From::from
åŒã³åºããåé¿ã§ããããŸããŸãªãšã©ãŒã¿ã€ãã®ã¡ãœãã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>
çµã¿åããã«äŒŒãŠããŸãã
æžãããŠããããã«ãå®è£ è ã¯å¶çŽã®ãªãä»»æã®ãµã€ãºã®
T
ãåãå ¥ããå¿ èŠããããŸãã ãããã«ã¹ã¿ã å¶çŽã«ããå Žåã¯ãTry<T>
ãããªãã¬ã€ããã©ã¡ãŒã¿ãŒã§ããå¿ èŠããããŸãã ããã¯ã @ scottmcmãïŒ42327ïŒã³ã¡ã³ãïŒã§æã£ãŠãã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
ãããªãã®ã®å Žåãæ¢ããŠãããã®ãèŠã€ããã®ã¯ãšã©ãŒã§ã¯ãããŸããããããã§å埩ãåæ¢ããããšæããŸãã
ãã®åœåã®éžæã«ã€ããŠã¯è°è«ã®äœå°ããããŸãããã¢ãŒãªãŒãªã¿ãŒã³ã¯å¿ ããããšã©ãŒãã®ãã®ã§ã¯ãªããšããèãã§ããã
æ£ç¢ºã«ã¯ããtryããšããååã奜ãã§ã¯ãªãããpropagateããšããååã奜ãçç±ã§ããããã¯ããåæã®ãæ»ãå€ããäŒæãããããã§ãïŒp
ïŒãããçã«ããªã£ãŠãããã©ããããããŸãããïŒååãããåãäžãããšãããäŒæãããããšã¯äœããã®çç±ã§ç§ã«ã¯çã«ããªã£ãŠãããä»ã®äººã«ããã説æããããšã¯ã§ããŸããã§ãããïŒ
ãã®ç¹æ§ã¯ãããã©ã«ãã®?
åäœfeãäžæžãããŠããããã°æ
å ±ïŒãã¡ã€ã«/è¡çªå·ãªã©ïŒããã°ã«èšé²ãããã°ããã¯feãè¿œå ããããšãããšãã«åœ¹ç«ã¡ãŸããïŒ
çŸåšãstdlibãã¯ãã®äžæžãã¯ãµããŒããããŠããŸããã ?
æŒç®åãtry!
ãã¯ãã«æ瀺çã«å€æãããŠããªãããã§ãã ããã¯æ®å¿µã§ãã
@stevenroose Try
ãã¬ã€ãã®ã¿ã«ãµããŒããè¿œå ããã«ã¯ã ?
ãçºçãããå Žæã«é¢ãããã¡ã€ã«ã®å Žææ
å ±ãå«ããããã«Try
ãã¬ã€ããå€æŽããå¿
èŠããããŸãã ã
@stevenroose
Try
ãã¬ã€ãã®ã¿ã«ãµããŒããè¿œå ããã«ã¯ã?
ãçºçãããå Žæã«é¢ãããã¡ã€ã«ã®å Žææ å ±ãå«ããããã«Try
ãã¬ã€ããå€æŽããå¿ èŠããããŸãã ã
ããã¯æ£ãããããŸããããã¬ã€ãå®çŸ©ã«ã¢ãããŒã·ã§ã³ãå«ãŸããŠããªãå Žåã§ããïŒ[track_caller]ããã¬ã€ãimplã§äœ¿çšã§ããŸãã
@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)?
ãããªå²ãåœãŠã¹ããŒãã¡ã³ããå«ããããšã¯ã§ããŸããã
&&
ãš||
ãåžžã«ããŸãããå Žåã¯ã .unwrap_or_else()
ã .and_then()
ãOption
ãš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
ã Error
ã«å¯ŸããŠåžžã«false
ããããŸãïŒ
ããã¯ããã€ãã®åçŽãªã±ãŒã¹ã«åœãŠã¯ãŸããŸããããããªãããšã¯ããŸããªããšæããŸããç¹ã«ãåŒã«
let x = v.get_mut(key)?
ãããªå²ãåœãŠã¹ããŒãã¡ã³ããå«ããããšã¯ã§ããŸããã
ãããšãç§ãããªãã®ææ¡ã誀解ããªãéãã bool
Try<Ok = (), Error = FalseError>
ãå®è£
ããã ãã§ã¯ããã¯èš±ãããŸããã ?
æŒç®åãNone
ãfalse
å€æã§ããããã«ã impl From<NoneError> for FalseError
ãå¿
èŠã«ãªããŸãã ïŒåæ§ã«ã bool
ãè¿ãé¢æ°å
ã®Result<T, E>
?
ãé©çšããå Žåã¯ã impl From<E> for FalseError
ãå®è¡ããå¿
èŠããããŸãããã©ã³ã±ããã®å®è£
ã«ã¯åé¡ããããŸããïŒæ»ãå€Result<bool, bool>
ïŒ .unwrap_or_else(|err| err)
æããããããšãã§ããŸãïŒã§åé¡ããªããã°ã 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
ãError
ã«å¯ŸããŠåžžã«false
ããããŸãïŒ
false
ãError
å Žåãè¡šãå¿
èŠããããã©ããã¯ç§ã«ã¯ããããŸããã ïŒããšãã°ã Iterator.all()
ã¯false
ãç絡ããããã®ã§ããã Iterator::any()
ã¯ä»£ããã«true
ãæ±ããŸããïŒãææã®ãšããã ?
æž¡ãããå€ãå転ããïŒãããŠé¢æ°ã®æ»ãå€ãå転ããïŒããšã«ããå察ã®ç絡åäœã ãããããããéåžžã«èªã¿ãããã³ãŒãã«ãªããšã¯æããŸããã 2ã€ã®ç°ãªãåäœãå®è£
ããå¥ã
ã®struct
s And(bool)
ãšOr(bool)
ã䜿çšããæ¹ãçã«ããªã£ãŠããå ŽåããããŸãã
åæ§ã«ãããªããé©çšãããå Žåã¯ïŒ çµæã«
boolãè¿ãé¢æ°å ã§ã¯ãFromãå®è£ ããå¿ èŠããããŸãã FalseErrorã®å Žåã ãã®ãããªå æ¬çãªå®è£ ã«ã¯åé¡ããããšæããŸãã
ããããç§ã¯ããããªãimpl From<T> for FalseError
å€åç§ãã¡ãè¡ãããšãã§ãã result.ok()?
falseããšã©ãŒã®å Žåãè¡šãå¿ èŠããããã©ããã¯ç§ã«ã¯ããããŸããã
true
ãSome
ãããããtrue
bool::then
ãããšãã©ããããããèªç¶ã ãšæããŸãã
ç§ã¯ãããéããå Žåãç§ãèš±ããŠ-ãªãdoesntã®NoneError
IMPL std::error::Error
ïŒ ããã«ããã Box<dyn Error>
ãªã©ãè¿ãé¢æ°ã«ã¯äœ¿çšã§ããªããªããŸãã
ç§ã¯ãããéããå Žåãç§ãèš±ããŠ-ãªãdoesntã®
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
å
šäœãããªãããªã¹ããããããã®åé¡ã«èŠããã§ããŸãããïŒ ãããååšããã¹ãã§ãããšæ±ºå®ãããå ŽåïŒå°ãªããšããããã¿ã€ãã³ã°ã«ãšã£ãŠã¯è¯ãããšã ãšæããŸãïŒã1ã€ãšåä»ããããŠããã®ã§Error
ãæ瀺ããå¿
èŠããããšæããŸãã
ãã®implããªãã¿ã€ãã®ãããç§ã¯ããã«.ok_or("error msg")
ããããã ãã«é ŒããŸããããããæ©èœããŸãããããŸã䟿å©ã§ã¯ãããŸããã
æãåèã«ãªãã³ã¡ã³ã
ãã®æ©èœã®çŸåšã®ã¹ããŒã¿ã¹ã¯äœã§ããïŒ