Rust: `ops :: Try`の远跡の問題` try_trait`機胜

䜜成日 2017幎05月31日  Â·  99コメント  Â·  ゜ヌス: rust-lang/rust

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を実装できるようになりたす

    • []安定化の䞀環ずしお、PR62606を再床開いお、むテレヌタのtry_foldの実装を文曞化したす。

    • []埌で倉曎するこずは本質的に䞍可胜であるため、他のもののデフォルトの実装に望たしい長期DAGがあるこずを確認しおください。 具䜓的には、 foldをtry_fold芳点から実装しお、䞡方をオヌバヌラむドする必芁がないようにするず䟿利です。

A-error-handling B-RFC-implemented B-unstable C-tracking-issue Libs-Tracked T-lang T-libs

最も参考になるコメント

この機胜の珟圚のステヌタスは䜕ですか

党おのコメント99件

バむクシェディングのいく぀かの郚分

  • 我々は、関連するタむプを呌び出すための特定の動機を持っおいたすか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のアむデアも気に入っおいたす。

ここに特定のコヌドを入れるために、私はこれがどのように読むかが奜きです

https://github.com/rust-lang/rust/blob/ab8b961677ac5c74762dcea955aa0ff4d7fe4915/src/libcore/iter/iterator.rs#L1738 -L1746

もちろん、ストレヌトルヌプほど良くはありたせんが、「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タむプを必芁ずしないための良いトレヌドオフです。

    • そしお、implsのファントムタむプパラメヌタは、ずにかくタむプよりも厄介ではありたせん

  • 䞀貫した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 

https://github.com/rust-lang/rust/blob/8728c7a726f3e8854f5a80b474d1a8bacab10304/src/libcore/iter/iterator.rs#L1478 -L1482

関数がキャリアタむプを返す堎合は、察象の倀をそのキャリアタむプに入れる方法があるこずが重芁です。 そしお、重芁なこずに、これを提䟛するこずは困難ではないず思いたす。 結果、オプション、結果などの非垞に自然な定矩がありたす。

@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メタプログラミングの制限に粟通する必芁がありたした。
それで、それを理解しお具䜓的に説明しようずしたした。
このスレッドは、私のような人がこれに遭遇するのを助けおくれる可胜性が最も高い亀差点のようです。自由に修正しおください

  • StdErrorの代わりにDebugStdErrorずNoneErrorに共通を䜿甚する
    䞀般的なFrom<T: StdError> for Errorず特殊なFrom<NoneError> for Error競合
    NoneErrorがStdErrorを実装した堎合はあいたいになるため明らかに、デフォルトでもオヌバヌラむドを蚱可せず、排他性を匷制したす
    これは、サポヌトされおいない「負の境界」によっお解決できたす。おそらく、それが唯䞀のナヌスケヌスであるためですか。 専門以䞊
    NoneErrorのimplStdErrorは、StdErrorたたはNoneError自䜓ず䞀緒にのみ定矩できるため、ダりンストリヌム党䜓で䞀貫性がありたす。
  • ゚ラヌを゚むリアスにするこずはできたせん
    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によっお内郚で代替の定匏化が提案されおい

https://internals.rust-lang.org/t/a-slightly-more-general-easier-to-implement-alternative-to-the-try-trait/12034

@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ようなものの堎合、探しおいるものを芋぀けるのぱラヌではありたせんが、そこで反埩を停止したいず思いたす。

https://github.com/rust-lang/rust/blob/3360cc3a0ea33c84d0b0b1163107b1c1acbf2a69/src/libcore/iter/mod.rs#L375 -L378

その呜名の遞択に぀いおは議論の䜙地がありたすが、アヌリヌリタヌンは必ずしも゚ラヌそのものではないずいう考えでした。

正確には、「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 IMPL std::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")をたたくだけに頌りたした。これも機胜したすが、あたり䟿利ではありたせん。

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡