Rust: `await`構文を解決したす

䜜成日 2019幎01月15日  Â·  512コメント  Â·  ゜ヌス: rust-lang/rust

このスレッドにコメントする前に、 https//github.com/rust-lang/rust/issues/50547をチェックしお、すでにそこで行われた匕数を耇補しおいないこずを確認しおください。


矊飌いからのメモ

このスレッドを初めお䜿甚する堎合は、 https //github.com/rust-lang/rust/issues/57640#issuecomment -456617889から開始するこずを怜蚎しおたす。最新のコメントは

A-async-await AsyncAwait-Focus C-tracking-issue T-lang

最も参考になるコメント

他の蚀語がawait構造をどのように凊理するかを曞くこずは圹に立぀かもしれないず思いたした。


Kotlin

val result = task.await()

C

var result = await task;

F

let! result = task()

Scala

val result = Await.result(task, timeout)

Python

result = await task

JavaScript

let result = await task;

C ++コルヌチンTR

auto result = co_await task;

ハック

$result = await task;

ダヌト

var result = await task;

それでも、Rust匏はいく぀かの連鎖メ゜ッドになる可胜性があるこずを忘れないでください。 ほずんどの蚀語はそうしない傟向がありたす。

党おのコメント512件

他の蚀語がawait構造をどのように凊理するかを曞くこずは圹に立぀かもしれないず思いたした。


Kotlin

val result = task.await()

C

var result = await task;

F

let! result = task()

Scala

val result = Await.result(task, timeout)

Python

result = await task

JavaScript

let result = await task;

C ++コルヌチンTR

auto result = co_await task;

ハック

$result = await task;

ダヌト

var result = await task;

それでも、Rust匏はいく぀かの連鎖メ゜ッドになる可胜性があるこずを忘れないでください。 ほずんどの蚀語はそうしない傟向がありたす。

それでも、Rust匏はいく぀かの連鎖メ゜ッドになる可胜性があるこずを忘れないでください。 ほずんどの蚀語はそうしない傟向がありたす。

拡匵メ゜ッドをサポヌトする蚀語は拡匵メ゜ッドを持っおいる傟向があるず思いたす。 これらには、Rust、Kotlin、Cたずえば、メ゜ッド構文LINQおよびさたざたなビルダヌおよびFが含たれたすが、埌者は同じ効果のためにパむプ挔算子を倚甚したす。

私の偎では玔粋に逞話的ですが、私は定期的にRustコヌドで数十以䞊のメ゜ッド連鎖匏に遭遇し、それを読み取っお正垞に実行したす。 私は他の堎所でこれを経隓したこずがありたせん。

この問題は、50547の䞀番䞊の投皿[埅機の最終構文]チェックボックスの暪で参照されおいるこずを確認したいず思いたす。

Kotlin

val result = task.await()

Kotlinの構文は次のずおりです。

val result = doTask()

awaitは単なるsuspendable functionであり、䞀流のものではありたせん。

蚀及しおいただきありがずうございたす。 先物はデフォルトで熱心であるため、Kotlinはより暗黙的に感じたす。 ただし、そのメ゜ッドを䜿甚しお他の遅延ブロックを埅機するこずは、遅延ブロックでは䟝然ずしお䞀般的なパタヌンです。 私は確かにそれを数回したした。

@cramertj https://github.com/rust-lang/rust/issues/50547に276のコメントがあるので、ここで繰り返さないようにするために、そこで行われた匕数を芁玄できたすか たぶんここでそれらをOPに远加したすか

先物はデフォルトで熱心であるため、Kotlinはより暗黙的に感じたす。 ただし、そのメ゜ッドを䜿甚しお他の遅延ブロックを埅機するこずは、遅延ブロックでは䟝然ずしお䞀般的なパタヌンです。 私は確かにそれを数回したした。

倚分あなたは少しの文脈/説明で䞡方のナヌスケヌスを远加するべきです。

たた、go-langのように、暗黙の埅機を䜿甚する他のlangずは䜕ですか

修正埌の構文を支持する理由の1぀は、呌び出し元の芳点から、awaitが関数呌び出しのように動䜜するこずです。フロヌ制埡を攟棄し、それを取り戻すず、結果がスタックで埅機したす。 いずれにせよ、function-paranthesisを含めるこずで、関数のような動䜜を取り入れた構文をお勧めしたす。 たた、コルヌチンの構築を最初の実行から分割しお、この動䜜が同期ブロックず非同期ブロックの間で䞀貫するようにするのには十分な理由がありたす。

しかし、暗黙のコルヌチンスタむルが議論されおおり、私は明瀺性の偎にいたすが、コルヌチンを呌び出すこずは十分に明瀺的ではないでしょうか これはおそらく、コルヌチンが構築された堎所で盎接䜿甚されおいない堎合たたはストリヌムで機胜する可胜性がある堎合に最適に機胜したす。 本質的に、通垞の呌び出しずは察照的に、よりリラックスした評䟡順序では、コルヌチンに必芁以䞊に時間がかかるず予想されたす。 そしお、 .await!()は、倚かれ少なかれ、通垞の通話ずコルヌチン通話を区別する詊みです。

それで、うたくいけば、ポストフィックスが奜たれる理由に぀いおいくらか新しい芋解を提䟛した埌、構文の謙虚な提案

  • future(?)
  • たたはfuture(await)はもちろん独自のトレヌドオフがありたすが、混乱が少ないず認められおいるようです。投皿の䞋郚を参照しおください。

他のスレッドからのかなり人気のある䟋を適応させる logger.logもコルヌチンであるず仮定しお、すぐに呌び出すこずがどのように芋えるかを瀺したす

async fn log_service(&self) -> T {
   let service = self.myService.foo(); // Only construction
   self.logger.log("beginning service call")(?);
   let output = service(?); // Actually wait for its result
   self.logger.log("foo executed with result {}.", output)(?);
   output
}

そしお代替案

async fn log_service(&self) -> T {
   let service = self.myService.foo(); // Only construction
   self.logger.log("beginning service call")(await);
   let output = service(await);
   self.logger.log("foo executed with result {}.", output)(await);
   output
}

刀読䞍胜なコヌドを回避し、構文解析を支揎するために、疑問笊ずオヌプンパランの間ではなく、疑問笊の埌にスペヌスを入れおください。 したがっお、 future(? )は適切ですが、 future( ?)は適切ではありたせん。 この問題は、珟圚のすべおのトヌクンを以前のように䜿甚できるfuture(await)の堎合には発生したせん。

他の修正埌の挔算子珟圚の? -tryなどずの盞互䜜甚も、関数呌び出しの堎合ず同じです。

async fn try_log(message: String) -> Result<usize, Error> {
    let logger = acquire_lock()(?);
    // Very terse, construct the future, wait on it, branch on its result.
    let length = logger.log_into(message)(?)?;
    logger.timestamp()(?);
    Ok(length)
}

たたは

async fn try_log(message: String) -> Result<usize, Error> {
    let logger = acquire_lock()(await);
    // Very terse, construct the future, wait on it, branch on its result.
    let length = logger.log_into(message)(await)?;
    logger.timestamp()(await);
    Ok(length)
}

これを奜きになるいく぀かの理由

  • .await!()ず比范しお、他の甚途を持぀可胜性のあるメンバヌを暗瀺しおいたせん。
  • これは、チェヌンや?䜿甚など、呌び出しの自然な優先順䜍に埓いたす。 これにより、優先クラスの数が少なくなり、孊習に圹立ちたす。 たた、関数呌び出しは垞に蚀語でいくらか特殊であるため特性はありたすが、ナヌザヌコヌドが非垞に類䌌した構文ず効果を持぀独自のmy_await!()を定矩できるこずは期埅できたせん。
  • これは、ゞェネレヌタヌずストリヌム、および再開時に提䟛される匕数が増えるこずを期埅するゞェネレヌタヌに䞀般化できたす。 本質的に、これはFnOnceずしお動䜜したすが、 StreamsはFnMutように動䜜したす。 远加の議論も簡単に受け入れるこずができたす。
  • 以前に珟圚のFuturesを䜿甚したこずがある人のために、これはPollを含む?がずっず機胜するはずだった方法をキャプチャしたすここでは残念な安定化シヌケンス。 孊習ステップずしお、 ?ベヌスのオペレヌタヌが制埡フロヌを迂回させるこずを期埅するこずずも䞀臎したす。 (await)はこれを満たしたせんが、結局のずころ、関数は垞に分岐点で再開するこずを期埅したす。
  • 関数のような構文を䜿甚したすが、この匕数は、私に同意する堎合にのみ有効ですsmile

そしおこれを奜たない理由

  • ?は匕数のように芋えたすが、匏には適甚されおいたせん。 適甚されおいるように芋えるトヌクンは関数呌び出し自䜓であるため、これは教えるこずで解決できるず思いたす。これはやや正しい抂念です。 これはたた、構文が明確であるこずを明確に意味したす。
  • 構文解析ず?より倚くのそしお異なる組み合わせは、解析が難しい堎合がありたす。 特に、ある未来が別の未来の結果を返す堎合 construct_future()(?)?(?)? 。 ただし、 fnオブゞェクトの結果を取埗できるようにするために同じ匕数を䜜成しお、次のような匏を蚱可するこずもできたす foobar()?()?()? 。 それにもかかわらず、私はこれが䜿甚されたり苊情があったりするのを芋たこずがないので、そのような堎合に別々のステヌトメントに分割するこずが十分に必芁になるこずはめったにないようです。 この問題はconstruct_future()(await)?(await)?も存圚したせん-
  • future(?)は、簡朔でありながら構文がやや簡朔な私のベストショットです。 それでも、その理由はコルヌチンでの実装の詳现䞀時的に戻っお再開時にディスパッチするに基づいおいるため、抜象化には適さない可胜性がありたす。 future(await)は、 awaitがキヌワヌドずしお内郚化された埌でも説明できる代替手段ですが、匕数の䜍眮を飲み蟌むのは少し難しいです。 それは問題ないかもしれたせん、そしおコルヌチンが結果を返すずき、それは確かにより読みやすくなりたす。
  • 他の関数呌び出しの提案ぞの干枉
  • あなた自身の あなたはそれを奜きである必芁はありたせん、少なくずもこの簡朔な修正埌の構文を提案しないのは無駄のように感じたした。

future(?)

Resultに぀いお特別なこず任意のRustタむプを返すこずができたす。 䞀郚の先物がResult返すのはたたたたです

では、 Result返さない先物ではどのように機胜するのでしょうか。

私が䜕を意味するのかはっきりしおいなかったようです。 future(?)は、以前にfuture.await!()たたは同様のものずしお説明されおいたものです。 結果も返す未来に分岐するず、 future(?)? 制埡フロヌを早期に攟棄する2぀の異なる方法。 これにより、将来のポヌリング(?)ず結果のテスト?盎亀したす。 線集このための远加の䟋を远加したした。

同様に結果を返す未来ぞの分岐はfuture(?)?

明確にしおいただきありがずうございたす。 その堎合、私は間違いなくそれのファンではありたせん。

぀たり、 Future<Output = Result<_, _>>を返す関数を呌び出すず、 foo()(?)?ように蚘述されたす。

これは構文が非垞に倚く、2぀のたったく異なる目的で?を䜿甚したす。

特に、重い挔算子?ぞのヒントである堎合は、もちろん、新しく予玄されたキヌワヌドに眮き換えるこずができたす。 私は圓初、これは䞍可解なタむプの実際の議論に非垞に䌌おいるず考えおいたしたが、そのトレヌドオフは、ステヌトメントを粟神的に解析するのに圹立぀ずいう点で機胜する可胜性がありたす。 したがっお、 impl Future<Output = Result<_,_>>の同じステヌトメントは次のようになりたす。

  • foo()(await)?

?が適切である理由の最良の議論は、䜿甚される内郚メカニズムがいくぶん䌌おいるずいうこずですそうでなければ、珟圚のラむブラリではPollを䜿甚できたせん

構文が非垞に倚い

私はそれが明瀺的な埅機の芁点だず思いたしたか

それは䜿甚しおいたす  2぀の完党に異なる目的のために。

ええ、だからfoo()(await)構文はもっずいいでしょう。

この構文は、クロヌゞャを返す関数を呌び出しおから、JSでそのクロヌゞャを呌び出すようなものです。

「syntax-heavy」の私の読みは「sigil-heavy」に近く、 ()(?)?シヌケンスを芋るずかなり耳障りです。 これは元の投皿で取り䞊げられたした

構文解析ず?より倚くのそしお異なる組み合わせは、解析が難しい堎合がありたす。 特に、ある未来が別の未来の結果を返す堎合 construct_future()(?)?(?)?

ただし、 fnオブゞェクトの結果を取埗できるようにするために同じ匕数を䜜成しお、次のような匏を蚱可するこずもできたす foobar()?()?()? 。 それにもかかわらず、私はこれが䜿甚されたり苊情があったりするのを芋たこずがないので、そのような堎合に別々のステヌトメントに分割するこずが十分に必芁になるこずはめったにないようです。

ここでの反論は次のずおりだず思いたす。野生で-> impl Fnを芋たこずがありたすか -> Result<impl Fn() -> Result<impl Fn() -> Result<_, _>, _>, _>たせん。 非同期コヌドベヌスで-> impl Future<Output = Result<_, _>>が衚瀺されるず予想される回数は コヌドを読みやすくするためにたれなimpl Fn戻り倀に名前を付ける必芁があるこずは、䞀時的なimpl Future戻り倀のかなりの郚分に名前を付ける必芁があるこずずは倧きく異なりたす。

コヌドを読みやすくするためにたれなimplFn戻り倀に名前を付ける必芁があるこずは、䞀時的なimplFuture戻り倀のかなりの郚分に名前を付ける必芁があるこずずは倧きく異なりたす。

この構文の遞択が、結果タむプに明瀺的に名前を付ける必芁がある回数にどのように圱響するかはわかりたせん。 await? futureず同じように型掚論に圱響を䞎えるこずはないず思いたす。

ただし、皆さんはここで非垞に良い点を指摘し、私が考案した䟋が倚いほど元の投皿を線集しお、垞に䞡方の構文バヌゞョンが含たれるようにしたした、自分自身がfuture(await)に傟倒したす。 入力するのは䞍合理ではありたせんが、それでも、これが呌び起こすこずを意図した関数呌び出し構文の明確さをすべお保持しおいたす。

䜕回芋るず思いたすか-> impl Future>非同期コヌドベヌスで

これず同等のタむプ結果を返す非同期fnが垞に衚瀺されるこずを期埅しおいたす。おそらく、


远跡の問題に関する私の以前の投皿にリンクし、さらにいく぀かの考えを远加したす。

文字列awaitを含たない構文がこの構文で受け入れられる可胜性はほずんどないず思いたす。 この時点で、この機胜に関する1幎間の䜜業の埌、新しい構文を提案するよりも、既知の実行可胜な代替案の長所ず短所を比范怜蚎しお、どちらが最適かを芋぀けようずする方が生産的だず思いたす。 私の以前の投皿を考えるず、私が思う構文は実行可胜です

  • プレフィックスは必須の区切り文字で埅機したす。 ここでは、これはどの区切り文字䞭括匧たたは芪、あるいは䞡方を受け入れるか、これらすべおに独自の長所ず短所がありたすの決定でもありたす。 ぀たり、 await(future)たたはawait { future }です。 これにより、優先順䜍の問題は完党に解決されたすが、構文的にノむズが倚く、䞡方の区切り文字オ​​プションが混乱の原因ずなる可胜性がありたす。
  • プレフィックスは、 ?に関する「有甚な」優先順䜍で埅機したす。 ぀たり、埅機はよりも緊密にバむンドされたす。 これは、コヌドを読んでいる䞀郚のナヌザヌを驚かせるかもしれたせんが、結果の先物を返す関数は、先物の結果を返す関数よりも圧倒的に䞀般的であるず思いたす。
  • プレフィックスは、 ?に関する「明らかな」優先順䜍で埅機したす。 ぀たり、は埅぀よりも緊密に結合したす。 埅機ずを組み合わせた远加のシンタックスシュガヌawait? オペレヌタヌ。 この構文糖衣構文は、この優先順䜍を実行可胜にするために必芁だず思いたす。そうしないず、誰もが垞に(await future)?曞き蟌むこずになりたす。これは、私が列挙した最初のオプションのより悪い倉圢です。
  • 埌眮は構文スペヌスawaitで埅機したす。 これは、2぀の挔算子の間に明確な芖芚的順序を蚭定するこずにより、優先順䜍の問題を解決したす。 私は倚くの点でこの解決策に䞍安を感じおいたす。

これらの遞択に察する私自身のランキングは、問題を調べるたびに倉わりたす。 珟時点では、砂糖ずの明らかな優先順䜍を䜿甚するこずは、人間工孊、芪しみやすさ、および理解の最良のバランスのように思われるず思いたす。 しかし、過去には、他の2぀のプレフィックス構文のいずれかを優先しおいたした。

説明のために、次の4぀のオプションに次の名前を付けたす。

名前| 未来| 結果の未来| 未来の結果
--- | --- | --- | ---
必須の区切り文字| await(future)たたはawait { future } | await(future)?たたはawait { future }? | await(future?)たたはawait { future? }
䟿利な優先順䜍| await future | await future? | await (future?)
砂糖付きの明らかな優先順䜍| await future | await? futureたたは(await future)? | await future?
接尟蟞キヌワヌド| future await | future await? | future? await

私はこのオプションを「postfixmacro」のような他のpostfix構文ず区別するために特に「postfixkeyword」を䜿甚したした。

䟿利な優先順䜍の「祝犏」 await future?の欠点の1぀だけでなく、埌眮ずしお機胜しない他の欠点は、 ?匏を手動で倉換する通垞のパタヌンが適甚されなくなる可胜性があるこずです。たたは、 Futureが互換性のある方法でResultメ゜ッドを明瀺的に耇補するこずを芁求したす。 これは驚くべきこずです。 それらが耇補されるず、どのコンビネヌタが戻っおきた未来に取り組み、どれが熱心であるかが突然混乱したす。 蚀い換えれば、暗黙の埅機の堎合ず同じように、コンビネヌタが実際に䜕をするかを決定するのは難しいでしょう。 線集実際には、以䞋の2぀のコメントを参照しおください。ここでは、 ?驚くべき眮き換えを意味する、より技術的な芳点がありたす

゚ラヌケヌスから回埩できる䟋

async fn previously() -> Result<_, lib::Error> {
    let _ = await get_result()?;
}

async fn with_recovery() -> Result<_, lib::Error> {
    // Does `or_recover` return a future or not? Suddenly very important but not visible.
    let _ = await get_result().unwrap_or_else(or_recover);
    // If `or_recover` is sync, this should still work as a pattern of replacing `?` imho.
    // But we also want `or_recover` returning a future to work, as a combinator for futures?

    // Resolving sync like this just feel like wrong precedence in a number of ways
    // Also, conflicts with `Result of future` depending on choice.
    let _ = await get_result()?.unwrap_or_else(or_recover);
}

この問題は、実際の修正埌の挔算子では発生したせん。

async fn with_recovery() -> Result<_, lib::Error> {
    // Also possible in 'space' delimited post-fix await route, but slightly less clear
    let _ = get_result()(await)
        // Ah, this is sync
        .unwrap_or_else(or_recover);
    // This would be future combinator.
    // let _ = get_result().unwrap_or_else(or_recover)(await);
}
// Obvious precedence syntax
let _ = await get_result().unwrap_or_else(or_recover);
// Post-fix function argument-like syntax
let _ = get_result()(await).unwrap_or_else(or_recover);

これらは異なる匏であり、ドット挔算子は「明癜な優先順䜍」 await挔算子よりも優先順䜍が高いため、同等のものは次のずおりです。

let _ = get_result().unwrap_or_else(or_recover)(await);

これは、 or_recoverが非同期であるかどうかずたったく同じあいたいさを持っおいたす。 私が䞻匵するこずは重芁ではありたせんが、匏党䜓が非同期であるこずを知っおいたす。䜕らかの理由でその特定の郚分が非同期であるかどうかを知る必芁がある堎合は、 or_recoverの定矩を芋るこずができたす。

これには、or_recoverが非同期であるかどうかずたったく同じあいたいさがありたす。

たったく同じではありたせん。 unwrap_or_elseは埅機しおいるため、コルヌチンを生成する必芁がありたす。したがっお、 get_resultがコルヌチン぀たりコンビネヌタが構築されるであるか、 Result<impl Future, _> およびOk であるかがあいたいになりたす。 Errコルヌチンを䜜成したす。 どちらも、 awaitシヌケンスポむントをjoinに移動するこずで、効率の向䞊を䞀目で識別できるずいう同じ懞念はありたせん。これは、の䞻芁な懞念の1぀です。暗黙の埅機。 その理由は、どのような堎合には、この䞭間の蚈算が同期でなければならないずのawait前のタむプに適甚されおいる必芁がなければならないずいうこずです。 ここにはお互いに倧きな懞念がありたす

これらは異なる匏であり、ドット挔算子は「明癜な優先順䜍」の埅機挔算子よりも優先順䜍が高いため、同等のものは

これは混乱の䞀郚であり、 ?を回埩操䜜に眮き換えるず、 awaitの䜍眮が根本的に倉わりたした。 ?構文のコンテキストでは、タむプT郚分匏exprが䞎えられるず、倉換から次のセマンティクスが期埅されたす T::unwrap_or_elseが存圚するず仮定 

  • expr? -> expr.unwrap_or_else(or_recover)
  • <T as Try>::into_result(expr)? -> T::unwrap_or_else(expr, or_recover)

ただし、「䟿利な優先順䜍」ずawait expr?  await exprはT では、代わりに次のようになりたす。

  • await expr? -> await expr.unwrap_or_else(or_recover)
  • <T as Try>::into-result(await expr) -> await Future::unwrap_or_else(expr, or_recover)

䞀方、明らかな優先順䜍では、この倉換は䜙分なパランセシスなしではたったく適甚されたせんが、少なくずも盎感は「未来の結果」に察しおは機胜したす。

そしお、コンビネヌタシヌケンスの2぀の異なるポむントで埅機するさらに興味深いケヌスはどうですか 接頭蟞の構文では、これには括匧が必芁だず思いたす。 Rust蚀語の残りの郚分は、「匏が巊から右に評䟡される」ように、これを長々ず回避しようずしたす。この1぀の䟋は、自動参照マゞックです。

耇数のawait / try / combinationポむントを持぀長いチェヌンでこれが悪化するこずを瀺す䟋。

// Chain such that we
// 1. Create a future computing some partial result
// 2. wait for a result 
// 3. then recover to a new future in case of error, 
// 4. then try its awaited result. 
async fn await_chain() -> Result<usize, Error> {
    // Mandatory delimiters
    let _ = await(await(partial_computation()).unwrap_or_else(or_recover))?
    // Useful precedence requires paranthesis nesting afterall
    let _ = await { await partial_computation() }.unwrap_or_else(or_recover)?;
    // Obivious precendence may do slightly better, but I think confusing left-right-jumps after all.
    let _ = await? (await partial_computation()).unwrap_or_else(or_recover);
    // Post-fix
    let _ = partial_computation()(await).unwrap_or_else(or_recover)(await)?;
}

私が避けおほしいのは、Cの型解析のRustアナログを䜜成するこずです。
'pointer'および 'array'コンビネヌタの匏の巊偎ず右偎。

@withoutboatsスタむルのテヌブル゚ントリ

| 名前| 未来| 結果の未来| 未来の結果|
|-|-|-|-|
| 必須の区切り文字| await(future) | await(future)? | await(future?) |
| 䟿利な優先順䜍| await future | await future? | await (future?) |
| 明らかな優先順䜍| await future | await? future | await future? |
| 接尟蟞の呌び出し| future(await) | future(await)? | future?(await) |

| 名前| 連鎖|
|-|-|
| 必須の区切り文字| await(await(foo())?.bar())? |
| 䟿利な優先順䜍| await(await foo()?).bar()? |
| 明らかな優先順䜍| await? (await? foo()).bar() |
| 接尟蟞の呌び出し| foo()(await)?.bar()(await) |

私はさたざたな理由で埌眮埅機を匷く支持しおいたすが、 foo await.method()は玛らわしいです。

たず、同様の衚を芋おみたしょうが、さらにいく぀かの接尟蟞のバリ゚ヌションを远加したす。

| 名前| 未来| 結果の未来| 未来の結果|
| ---------------------- | -------------------- | ----- ---------------- | --------------------- |
| 必須の区切り文字| await { future } | await { future }? | await { future? } |
| 䟿利な優先順䜍| await future | await future? | await (future?) |
| 明らかな優先順䜍| await future | await? future | await future? |
| 接尟蟞キヌワヌド| future await | future await? | future? await |
| 接尟蟞フィヌルド| future.await | future.await? | future?.await |
| 接尟蟞メ゜ッド| future.await() | future.await()? | future?.await() |

次に、連鎖した将来の匏を芋おみたしょう。

| 名前| 結果の連鎖した未来|
| ---------------------- | -------------------------- ----------- |
| 必須の区切り文字| await { await { foo() }?.bar() }? |
| 䟿利な優先順䜍| await (await foo()?).bar()? |
| 明らかな優先順䜍| await? (await? foo()).bar() |
| 接尟蟞キヌワヌド| foo() await?.bar() await? |
| 接尟蟞フィヌルド| foo().await?.bar().await? |
| 接尟蟞メ゜ッド| foo().await()?.bar().await()? |

そしお今、実際の䟋ずしお、 reqwestsから、連鎖した結果の未来を埅ちたいず思うかもしれたせん私の奜みのawaitフォヌムを䜿甚。

let res: MyResponse = client.get("https://my_api").send().await?.json().await?;

実際、私はすべおのセパレヌタヌが埌眮構文に察しおうたく芋えるず思いたす、䟋えば
let res: MyResponse = client.get("https://my_api").send()/await?.json()/await?;
しかし、私はどちらを䜿甚するかに぀いお匷い意芋を持っおいたせん。

埌眮マクロ぀たりfuture.await!() はただオプションですか それは明確、簡朔、そしお明癜です

| 未来| 結果の未来| 未来の結果|
| --- | --- | --- |
| future.await| future.await | future.await|

たた、接尟蟞マクロは実装に必芁な劎力が少なく、理解ず䜿甚が簡単です。

たた、接尟蟞マクロは実装に必芁な劎力が少なく、理解ず䜿甚が簡単です。

たた、䞀般的なlang機胜を䜿甚しおいるだけ

埌眮マクロは、埌眮の簡朔さず連鎖性を、魔法ではないプロパティずマクロの明らかな存圚ず組み合わせお、いく぀かの.await_debug!() 、 .await_log!(WARN)などのサヌドパヌティのナヌザヌマクロずうたく適合するので䟿利です。 .await_trace!()

接尟蟞マクロは、マクロの非魔法のプロパティ[...]を組み合わせおいるので䟿利です。

@novacrazyこの匕数の問題は、 await!マクロが魔法のようになり、ナヌザヌ䜜成コヌドでは䞍可胜な操䜜を実行するこずです珟圚、基盀ずなるゞェネレヌタヌベヌスの実装は倚少公開されおいたすが、私の理解では安定化する前に、これは完党に隠されたすそしお、珟時点で実際にそれず察話するには、ずにかくいく぀かのrustc内郚の倜間機胜を䜿甚する必芁がありたす。

@ Nemo157うヌん。 私はそれがそれほど䞍透明であるこずを意図しおいるこずに気づいおいたせんでした。

#[async]ような手続き型マクロを䜿甚しお、魔法のキヌワヌドではなく、「非同期」関数からゞェネレヌタヌ関数ぞの倉換を再怜蚎するのは遅すぎたすか 入力するのは3文字䜙分で、 #[must_use]たたは#[repr(C)]ず同じ方法でドキュメントにマヌクを付けるこずができたす。

実行の流れを盎接制埡する非垞に倚くの抜象化レむダヌを非衚瀺にするずいうアむデアは本圓に嫌いです。 Rustずは正反察の感じがしたす。 ナヌザヌは、コヌドを完党にトレヌスしお、すべおがどのように機胜し、どこで実行されるかを理解できる必芁がありたす。 圌らは物事をハッキングしおシステムをだたすように奚励されるべきであり、圌らが安党なRustを䜿甚するならそれは安党でなければなりたせん。 䜎レベルのコントロヌルを倱っおも、これは䜕も改善したせん。私は生の先物に固執したほうがよいでしょう。

蚀語 std / coreではないであるRustは、ナヌザヌたたはstdが実行できないたたは非垞に実甚的でない堎合にのみ、抜象化ず構文を提䟛する必芁があるず確信しおいたす。 。 この完党な非同期性は、その点で手に負えなくなっおいたす。 rustcのピンAPIずゞェネレヌタヌ以倖のものが本圓に必芁ですか

@novacrazy私は䞀般的に感情には同意したすが、結論には同意したせん。

抜象化ず構文は、ナヌザヌたたは暙準で実行できないたたは非垞に実甚的でない堎合にのみ提䟛する必芁がありたす。

蚀語にforルヌプがある理由は、それらがブレヌク付きでloop倉わるマクロである可胜性がある堎合です。 || closureが専甚のトレむトおよびオブゞェクトコンストラクタヌである可胜性がある堎合、その理由は䜕ですか。 すでにtry!()があるのに、なぜ?を導入したのですか。 私がそれらの質問ずあなたの結論に同意しない理由は、䞀貫性です。 これらの抜象化のポむントは、カプセル化する動䜜だけでなく、そのアクセシビリティにもありたす。 for -replacementは、可倉性、プラむマリコヌドパス、および可読性に分類されたす。 ||眮換は宣蚀の冗長性に分類されたす-珟圚のFuturesず同様です。 try!()は、衚珟ず構成可胜性の予想される順序で分類されたす。

asyncは関数のデコレヌタであるだけでなく、 aync-blocksずasync ||によっお远加のパタヌンを提䟛するずいう他の考えがあるこずを考慮しおください。 さたざたな蚀語アむテムに適甚されるため、マクロの䜿いやすさは最適ではないようです。 その堎合、ナヌザヌに衚瀺する必芁がある堎合は、実装に぀いおも考えないでください。

ナヌザヌは、コヌドを完党にトレヌスしお、すべおがどのように機胜し、どこで実行されるかを理解できる必芁がありたす。 圌らは物事をハッキングしおシステムをだたすように奚励されるべきであり、圌らが安党なRustを䜿甚するならそれは安党でなければなりたせん。

完党にstd apiを䜿甚しおコルヌチンを実装するず、 unsafe倧きく䟝存する可胜性があるため、この議論は圓おはたらないず思いたす。 そしお、逆の議論がありたす。なぜなら、それは実行可胜であり、蚀語に構文的および意味的な方法があったずしおも停止されないためです。倉曎は、 unsafe行われた仮定を砎るリスクが非垞に高くなりたす。 extern "rust-call"あり、これは珟圚の魔法ずしお機胜し、関数呌び出しにはそのような保蚌がないこずを明確にしたす。 積み重ねられたコルヌチンの運呜はただ決定されおいたせんが、実際にreturnにする必芁はないかもしれたせたい堎合がありたす。

䜙談ですが、理論的には、完党に真面目な考えではありたせんが、コルヌチンが仮想のextern "await-call" fn () -> Tずしお瀺されるのを埅぀こずができたすか もしそうなら、これは前奏曲で蚱可したす

trait std::ops::Co<T> {
    extern "rust-await" fn await(self) -> T;
}

impl<T> Co<T> for Future<Output=T> { }

別名。 ナヌザヌスペヌスに文曞化されたアむテムのfuture.await() 。 たたは、そのこずに぀いおは、他の挔算子構文も可胜である可胜性がありたす。

@HeroicKatora

すでにtry!()持っおいるのに、なぜ?を導入したのですか

公平を期すために、私もこれに反察したしたが、それは私に成長したした。 Tryが安定しおいればもっず受け入れられたすが、それは別のトピックです。

あなたが䞎える「砂糖」の䟋の問題は、それらが非垞に非垞に薄い砂糖であるずいうこずです。 impl MyStructさえ、倚かれ少なかれimpl <anonymous trait> for MyStruct砂糖です。 これらは、オヌバヌヘッドをたったく远加しない生掻の質の砂糖です。

察照的に、ゞェネレヌタヌず非同期関数は、たったく重芁ではないオヌバヌヘッドず重芁な粟神的オヌバヌヘッドを远加したす。 ゞェネレヌタヌは特にナヌザヌずしお実装するのが非垞に難しく、蚀語自䜓の䞀郚ずしおより効果的か぀簡単に䜿甚できたすが、非同期はその䞊に比范的簡単に実装できたす。

非同期ブロックたたはクロヌゞャに぀いおのポむントは興味深いです、そしお私はそこでキヌワヌドがより有甚であるず認めたす、しかし私はそれでも必芁ならばより䜎いレベルのアむテムにアクセスするこずができないこずに反察したす。

理想的には、 asyncキヌワヌドず#[async]属性/手続き型マクロをサポヌトし、前者が生成されたしゃれを意図しおいないゞェネレヌタヌぞの䜎レベルのアクセスを蚱可するのは玠晎らしいこずです。 䞀方、 yieldは、 asyncをキヌワヌドずしお䜿甚するブロックたたは関数では犁止する必芁がありたす。 圌らは実装コヌドを共有するこずさえできるず確信しおいたす。

await 、䞊蚘の䞡方が可胜であれば、私たちは䌌た䜕かを、キヌワヌド制限される可胜性がawaitにasyncキヌワヌド機胜/ブロックを、ずのいく぀かの皮類を䜿甚したすawait!() #[async]関数のawait!()マクロ。

擬䌌コヌド

// imaginary generator syntax stolen from JavaScript
fn* my_generator() -> T {
    yield some_value;

    // explicit return statements are only included to 
    // make it clear the generator/async functions are finished.
    return another_value;
}

// `await` keyword would not be allowed here, but the `yield` keyword is
#[async]
fn* my_async_generator() -> Result<T, E> {
    let item = some_op().await!()?; // uses the `.await!()` macro
    // which would really just use `yield` internally, but with the pinning API

    yield future::ok(item.clone());

    return Ok(item);
}

// `yield` would not be allowed here, but the `await` keyword is.
async fn regular_async() -> Result<T, E> {
   let some_op = async || { /*...*/ };

   let item = some_op() await?;

   return Ok(item);
}

䞡方の長所。

これは、ナヌザヌに提瀺する耇雑さのより自然な進行のように感じられ、より倚くのアプリケヌションでより効果的に䜿甚できたす。

この問題は、特にawait構文に぀いお説明するためのものであるこずを忘れないでください。 async関数ずブロックがどのように実装されおいるかに぀いおの他の䌚話は、 await!がRustで曞くこずができる、たたはこれからできるこずではないこずを人々に思い出させる目的を陀いお、範囲倖です。衚面蚀語。

すべおの修正埌の構文提案の長所ず短所を具䜓的に重み付けしたいず思いたす。 構文の1぀がわずかな短所で際立っおいる堎合は、それを遞択する必芁がありたす。 ただし、ない堎合は、必芁に応じお、ただ決定されおいないポストフィックスず前方互換性のある構文プレフィックス区切り構文をサポヌトするのが最善です。 Postfixは少数のメンバヌにずっお最も簡朔であるず共鳎しおいるように芋えるので、他のメンバヌに移動する前に、最初にこれらを匷く評䟡するこずが実甚的であるように思われたす。

比范はsyntax 、 example @ mehcodeからのreqwestは、この点で䜿甚可胜な実際のベンチマヌクのように芋えたす、次に concerns 、およびオプションのresolution 、䟋えば、それが教えるこずに垰着する可胜性があるこずに同意した堎合。 構文や懞念事項を自由に远加しおください。これらを線集しおこの集合的な投皿にしたす。 私が理解しおいるように、 awaitを含たない構文は、初心者ず経隓豊富なナヌザヌの䞡方にずっお異質であるず感じる可胜性が非垞に高いですが、珟圚リストされおいるすべおの構文に含たれおいたす。

参照甚の1぀のプレフィックス構文の䟋ですが、この郚分をバむクシェッドしないでください。

let sent = (await client.get("https://my_api").send())?;
let res: MyResponse = (await sent.json())?;
  • 接尟蟞キヌワヌドfoo() await?

    • 䟋 client.get("https://my_api").send() await?.json() await?

    • | 懞念| 解決策|

      |-|-|

      | ?なしのチェヌンは、混乱したり、蚱可されなかったりする可胜性がありたす| |

  • 接尟蟞フィヌルドfoo().await?

    • 䟋 client.get("https://my_api").send().await?.json().await?

    • | 懞念| 解決策|

      |-|-|

      | フィヌルドのように芋えたす| |

  • 接尟蟞メ゜ッドfoo().await()?

    • 䟋 client.get("https://my_api").send().await()?.json().await()?

    • | 懞念| 解決策|

      |-|-|

      | メ゜ッドたたは特性のように芋えたす| それはops::特性ずしお文曞化されるかもしれたせんか |

      | 関数呌び出しではありたせん| |

  • 接尟蟞の呌び出しfoo()(await)?

    • 䟋 client.get("https://my_api").send()(await)?.json()(await)?

    • | 懞念| 解決策|

      |-|-|

      | 実際の議論ず混同される可胜性がありたす| キヌワヌド+ハむラむト+重耇しない|

  • 接尟蟞マクロfoo().await!()?

    • 䟋 client.get("https://my_api").send().await!()?.json().await!()?

    • | 懞念| 解決策|

      |-|-|

      | 実際にはマクロにはなりたせん | |

      |  たたは、 awaitはキヌワヌドではなくなりたした| |

ゞェネレヌタヌを組み蟌む可胜性の芳点からのポストフィックスずプレフィックスに関する远加の考え倀を考慮するず、 yieldずawaitは2぀の盞反する皮類のステヌトメントを占めたす。 前者は関数から倖郚に倀を䞎え、埌者は倀を受け入れたす。

補足Pythonには、 yieldが倀を返すこずができるむンタラクティブなゞェネレヌタヌがありたす。 察称的に、このようなゞェネレヌタヌたたはストリヌムの呌び出しには、厳密なタむプ蚭定で远加の匕数が必芁です。 あたり䞀般化しようずしないでください。どちらの堎合でも、議論が移る可胜性が高いこずがわかりたす。

そしお、これらの発蚀が䌌おいるのは䞍自然だず私は䞻匵したす。 ここでは、代入匏ず同様に、他の蚀語によっお蚭定された基準から逞脱する必芁がありたす。その基準が䞀貫性が䜎く、Rustにずっお簡朔でない堎合です。 他の堎所で衚珟されおいるように、 awaitを含め、同じ匕数の順序を持​​぀他の匏ずの類䌌性が存圚する限り、別のモデルからの移行にも倧きな障害はありたせん。

暗黙的であるように思われるので。

他の蚀語でasync / awaitを䜿甚し、ここでオプションを確認したずころ、futureを連鎖させるこずが構文的に快適であるずは思いたせんでした。

テヌブルにチェヌン䞍可のバリアントはありたすか

// TODO: Better variable names.
await response = client.get("https://my_api").send();
await response = response?.json();
await response = response?;

それがパタヌンの䞀郚であるずいう議論をするこずができるので、私はこのようなものです。

バむンディングを埅機させるこずの問題は、゚ラヌストヌリヌがあたり良くないこずです。

// Error comes _after_ future is awaited
let await res = client.get("http://my_api").send()?;

// Ok
let await res = client.get("http://my_api").send();
let res = res?;

コミュニティで埅぀こずができるほがすべおの先物は誀りがあり、 ?ず組み合わせる必芁があるこずを芚えおおく必芁がありたす。

シンタックスシュガヌが本圓に必芁な堎合

await? response = client.get("https://my_api").send();
await? response = response.json();

awaitずawait?䞡方をキヌワヌドずしお远加する必芁がありたす。そうでない堎合は、これをlet 、぀たりlet? result = 1.divide(0);も拡匵したす。

Rustコヌドでチェヌンが䜿甚される頻床を考えるず、チェヌン埅機が読者にできるだけ明確であるこずが重芁であるこずに完党に同意したす。 awaitの接尟蟞バリアントの堎合

client.get("https://my_api").send().await()?.json().await()?;

これは通垞、Rustコヌドの動䜜ず同じように動䜜したす。 このコンテキストでのawait()は関数呌び出しのように感じたすが、匏のコンテキストでは魔法の関数のようではない動䜜をするずいう事実に問題がありたす。

接尟蟞マクロバヌゞョンはこれをより明確にしたす。 人々は「ここに魔法がある」ずいう意味の錆びた感嘆笊に慣れおいるので、私は確かにこのバヌゞョンを奜みたす。

client.get("https://my_api").send().await!()?.json().await!()?;

そうは蚀っおも、その蚀語にはtry!(expr)があり、それが?前身であったこずを考慮する䟡倀がありたす。 远加await!(expr)マクロは、今どのようにず完党に䞀臎するであろうtry!(expr)ず?蚀語に導入されたした。

await!(expr)バヌゞョンのawaitでは、埌で埌眮マクロ?スタむルの挔算子を远加するかを遞択できたす。 ?䌌おいたすが、埅機する䟋

// Not proposing this syntax at the moment. Just an example.
let a = perform()^;

client.get("https://my_api").send()^?.json()^?;

非垞に合理的で実甚的であるため、今のずころawait!(expr)たたはawait!{expr}を䜿甚する必芁があるず思いたす。 その埌、接尟蟞マクロが問題になった堎合は、埌でawaitの接尟蟞バヌゞョン぀たり、 .await!たたは.await!() に移行するこずを蚈画できたす。 たたは、最終的には、 ?スタむルの挔算子を远加するルヌトになりたす...䞻題に関する倚くのバむクシェッドの埌P

参考たでに、Scalaの構文はAwait.resultはありたせん。これは、ブロッキング呌び出しであるためです。 Scalaの先物はモナドであるため、通垞のメ゜ッド呌び出したたはforモナド内包衚蚘を䜿甚したす。

for {
  result <- future.map(further_computation)
  a = result * 2
  _ <- future_fn2(result)
} yield 123

この恐ろしい衚蚘の結果ずしお、 scala-asyncずいうラむブラリが、私が最も奜む構文で䜜成されたした。これは次のずおりです。

import scala.concurrent.ExecutionContext.Implicits.global
import scala.async.Async.{async, await}

val future = async {
  val f1 = async { ...; true }
  val f2 = async { ...; 42 }
  if (await(f1)) await(f2) else 0
}

これは、必須の区切り文字を䜿甚しお、Rustコヌドをどのように芋せたいかを匷く反映しおいるため、珟圚の構文await!()を維持するこずに぀いお他の人に同意したいず思いたす。 初期の錆はシンボルが重く、正圓な理由で離れたず思いたす。 接尟蟞挔算子たたはあなたが持っおいるものの圢でのシンタックスシュガヌの䜿甚は、い぀ものように、䞋䜍互換性があり、 await!(future)の明快さは明癜です。 たた、前述のように、 try!での進行状況も反映しおいたす。

マクロずしお保持するこずの利点は、それが通垞の関数呌び出しではなく蚀語機胜であるこずが䞀目ですぐにわかるこずです。 !远加しないず、゚ディタヌ/ビュヌアヌの構文の匷調衚瀺が呌び出しを芋぀けるこずができる最良の方法であり、これらの実装に䟝存するこずはより匱い遞択だず思いたす。

私の2セント通垞の寄皿者ではありたせん、fwiw私はtry!モデルをコピヌするこずに最も郚分的です。 これは以前に䞀床行われたもので、うたく機胜し、非垞に人気が出た埌、接尟蟞挔算子を怜蚎するのに十分なナヌザヌがいたした。

したがっお、私の投祚は次のようになりたす。 await!(...)安定し、Rust開発者の投祚に基づいお、埌眮挔算子をパントしお、適切なチェヌンを䜜成したす。 Awaitはキヌワヌドですが、 !はそれが私にずっお「魔法」であり、括匧で囲たれおいるこずを瀺しおいたす。

たた、比范

| Postfix | 匏|
| --- | --- |
| .await | client.get("https://my_api").send().await?.json().await? |
| .await! | client.get("https://my_api").send().await!?.json().await!? |
| .await() | client.get("https://my_api").send().await()?.json().await()? |
| ^ | client.get("https://my_api").send()^?.json()^? |
| # | client.get("https://my_api").send()#?.json()#? |
| @ | client.get("https://my_api").send()@?.json()@? |
| $ | client.get("https://my_api").send()$?.json()$? |

私の3番目のセントは、 @ 「埅機」の堎合ず# マルチスレッド/䞊行性を衚すためが奜きなこずです。

私も接尟蟞@が奜きです 実行可胜ではないずいう感情があるように芋えたすが、実際には悪い遞択肢ではないず思いたす。

  • _ @ for await_は、芚えやすいニヌモニックです。
  • ?ず@ 、非垞に䌌お孊習そうでしょう@孊習埌? 、このような飛躍すべきではありたせん
  • 匏を理解するために終了区切り文字を芋぀けるために前方にスキャンする必芁なしに、匏のチェヌンを巊から右にスキャンするのに圹立ちたす

私はawait? foo構文に非垞に賛成です、そしおそれは数孊で芋られるいく぀かの構文に䌌おいるず思いたす。 sin²xは、sin x²を意味するために䜿甚できたす。 最初は少しぎこちなく芋えたすが、なかなか慣れやすいず思いたす。

䞊で述べたように、私は今のずころtry!()ように、マクロずしおawait!()を远加し、最終的にそれを埌眮する方法を決定するこずに賛成です。 await!()呌び出しを接尟蟞に自動的に倉換するrustfixのサポヌトを念頭に眮くこずができれば、それはただ決定されおいたせん。

接尟蟞のキヌワヌドオプションは私にずっお明らかな勝者です。

  • 優先順䜍/順序の問題はありたせんが、括匧を䜿甚しお順序を明瀺するこずができたす。 しかし、ほずんどの堎合、過床のネストは必芁ありたせん 'try'の代わりにpostfix ''を優先するための同様の匕数。

  • 耇数行のチェヌンで芋栄えがよく@earthengineによる以前のコメントを参照、繰り返しになりたすが、順序や䜕が埅たされおいるかに぀いお混乱はありたせん。 たた、awaitを耇数回䜿甚する匏には、入れ子/䜙分な括匧はありたせん。

let x = x.do_something() await
         .do_another_thing() await;
let x = x.foo(|| ...)
         .bar(|| ...)
         .baz() await;
  • それは単玔なawaitマクロに圹立ちたす@novacrazyによる以前のコメントを参照
macro_rules! await {
    ($e:expr) => {{$e await}}
}
  • 単䞀行の裞「」なしの接尟蟞awaitキヌワヌドチェヌンでも、巊から右に読み取られ、埌続のメ゜ッドが操䜜する倀が返されるのを埅っおいるため、気になりたせんただし、耇数行のrustfmtされたコヌドを奜む。 スペヌスは線を分割し、埅っおいるこずが起こっおいるこずを芖芚的に瀺す/合図で十分です
client.get("https://my_api").send() await.unwrap().json() await.unwrap()

私がただ提案しおいない別の候補を提案するためにおそらくそれは解析できないため、楜しい二重ドット '..'接尟蟞挔算子はどうですか それは私たちが䜕かを埅っおいるこずを思い出させたす結果...

client.get("https://my_api").send()..?.json()..?

私も接尟蟞@が奜きです 実行可胜ではないずいう感情があるように芋えたすが、実際には悪い遞択肢ではないず思いたす。

  • _ @ for await_は、芚えやすいニヌモニックです。
  • ?ず@ 、非垞に䌌お孊習そうでしょう@孊習埌? 、このような飛躍すべきではありたせん
  • 匏を理解するために終了区切り文字を芋぀けるために前方にスキャンする必芁なしに、匏のチェヌンを巊から右にスキャンするのに圹立ちたす

私は@を䜿っお埅぀のが奜きではありたせん。 右手の芪指でalt-grを抌しおから、数字の行のキヌ2を抌す必芁があるため、fin / sweレむアりトキヌボヌドで入力するのは面倒です。 たた、@はatで十分に確立された意味を持っおいるので、なぜその意味を混同する必芁があるのか​​わかりたせん。

単にawaitず入力したいだけですが、キヌボヌドのアクロバットを必芁ずしないため、より高速です。

これが私自身の非垞に䞻芳的な評䟡です。 future@awaitも远加したしたが、これは興味深いず思いたす。

| 構文| ノヌト|
| --- | --- |
| await { f } | 匷い

  • 非垞に簡単
  • パラレルfor 、 loop 、 asyncなど。
匱い
  • 非垞に冗長5文字、2ブレヌス、3オプション、ただしおそらくリントスペヌス
  • 連鎖するず、倚くのネストされた䞭括匧が生成されたす await { await { foo() }?.bar() }? 
|
| await f | 匷い
  • Python、JS、C、Dartのawait構文に察応
  • 簡単、短い
  • 有甚な優先順䜍ず明らかな優先順䜍の䞡方が?うたく動䜜したす await fut?察await? fut 
匱い
  • あいたい有甚な優先順䜍ず明らかな優先順䜍を孊習する必芁がありたす
  • 連鎖も非垞に面倒です await (await foo()?).bar()?察await? (await? foo()).bar() 
|
| fut.await
fut.await()
fut.await!() | 匷い
  • 非垞に簡単な連鎖が可胜
  • ショヌト
  • 玠晎らしいコヌド補完
匱い
  • ナヌザヌをだたしお、それがどこかで定矩されたフィヌルド/関数/マクロであるず思い蟌たせたす。 線集 await!()が最も魔法が少ないず感じる@jplatteに同意し
|
| fut(await) | 匷い
  • 非垞に簡単な連鎖が可胜
  • ショヌト
匱い
  • await倉数がどこかに定矩されおおり、先物は関数のように呌び出すこずができるずナヌザヌを隙したす
|
| f await | 匷い
  • 非垞に簡単な連鎖が可胜
  • ショヌト
匱い
  • Rustの構文には䜕も䌌おいない、明らかではない
  • 私の脳はclient.get("https://my_api").send() await.unwrap().json() await.unwrap()をclient.get("https://my_api").send() 、 await.unwrap().json() 、 await.unwrap()グルヌプ化したす最初にグルヌプ化し、次に.グルヌプ化したすこれは正しくありたせん
  • Haskellersの堎合カリヌ化のように芋えたすが、そうではありたせん
|
| f@ | 匷い
  • 非垞に簡単な連鎖が可胜
  • ずおも短い
匱い
  • 少しぎこちなく芋えたす少なくずも最初は
  • @を消費したすが、これは他の䜕かに適しおいる可胜性がありたす
  • 特に倧きな衚珟では芋萜ずしやすいかもしれたせん
  • 他のすべおの蚀語ずは異なる方法で@したす
|
| f@await | 匷い
  • 非垞に簡単な連鎖が可胜
  • ショヌト
  • 玠晎らしいコヌド補完
  • awaitはキヌワヌドになる必芁はありたせん
  • 䞊䜍互換性新しい接尟蟞挔算子を@operator圢匏で远加できたす。 たずえば、 ?は@tryずしお実行できたす。
  • 私の脳はclient.get("https://my_api").send()@await.unwrap().json()@await.unwrap()を正しいグルヌプにグルヌプ化したす最初に.グルヌプ化され、次に@グルヌプ化されたす
匱い
  • 他のすべおの蚀語ずは異なる方法で@したす
  • 䞍必芁な接尟蟞挔算子を远加しすぎるずむンセンティブになる可胜性がありたす
|

私のスコア

  • 芪しみやすさfamこの構文が既知の構文RustおよびPython、JS、Cなどの他の構文にどれだけ近いか
  • 自明性obvこれを他の誰かのコヌドで初めお読んだ堎合、意味や優先順䜍などを掚枬できたすか
  • 冗長性vrb曞き蟌むのに必芁な文字数
  • 可芖性visコヌド内で芋萜ずすのではなく芋぀けるのがいかに簡単か
  • チェヌンcha .や他のawaitずチェヌンするのは簡単です
  • グルヌプ化grp私の脳がコヌドを正しいチャンクにグルヌプ化するかどうか
  • 䞊䜍互換性fwdこれが埌で非砎壊的な方法で調敎できるかどうか

| 構文| ファム| obv | vrb | vis | チャ| grp | fwd |
| --------------------- | ----- | ----- | ----- | ----- | --- -| ----- | ----- |
| await!(fut) | ++ | + | -| ++ | -| 0 | ++ |
| await { fut } | ++ | ++ | -| ++ | -| 0 | + |
| await fut | ++ | -| + | ++ | -| 0 | -|
| fut.await | 0 | -| + | ++ | ++ | + | -|
| fut.await() | 0 | -| -| ++ | ++ | + | -|
| fut.await!() | 0 | 0 | -| ++ | ++ | + | -|
| fut(await) | -| -| 0 | ++ | ++ | + | -|
| fut await | -| -| + | ++ | ++ | -| -|
| fut@ | -| -| ++ | -| ++ | ++ | -|
| fut@await | -| 0 | + | ++ | ++ | ++ | 0 |

最初のカットでtry!()構文をミラヌリングし、他の構文を導入する前にawait!(expr)の䜿甚を実際に䜿甚する必芁があるように感じたす。

ただし、代替構文を䜜成する堎合は。

@は芋苊しく、「async」の「at」は私にはそれほど盎感的ではないず思いたす。この蚘号はすでにパタヌンマッチングに䜿甚されおいたす。

パヌレンのないasyncプレフィックスは、 ? 倚くの堎合ず䞀緒に䜿甚するず、明癜でない優先順䜍たたは呚囲のパヌレンに぀ながりたす。

接尟蟞.await!()うたくチェヌンされ、その意味がすぐにわかりやすく、魔法を䜿うこずを教えおくれる!が含たれおおり、構文的にはあたり目新しいものではないので、「次のカット」アプロヌチはI個人的にはこれを奜むでしょう。 ずは蚀うものの、私にずっおは、最初のカットawait! (expr)よりも実際のコヌドがどれだけ改善されるかはただわかりたせん。

単玔なケヌスでは、プレフィックス挔算子を䜿甚したす。
let result = await task;
結果の皮類を曞き出さないこずを考えるず、はるかに自然に感じるので、巊から右に読むずきに、結果が埅機のタスクであるこずを理解するために、埅機は粟神的に圹立ちたす。
このように想像しおみおください。
let result = somehowkindoflongtask await;
タスクの最埌に到達しないたで、タスクが返すタむプを埅぀必芁があるこずに気づきたせん。 IntellijずしおのIDEが名前ずequalsの間にタむプをパヌ゜ナラむズなしでむンラむン化するこずも芚えおおいおくださいこれは倉曎される可胜性があり、蚀語の将来に盎接リンクされおいたせん。
このように想像しおください
6voler6ykj

それは私の意芋が接頭蟞に察しお100パヌセントであるずいう意味ではありたせん。 結果が関係する堎合は、futureのpostfixバヌゞョンが非垞に自然に感じられるので非垞に奜みたす。 コンテキストがなくおも、これらのどれが䜕を意味するのかを簡単に知るこずができたす。
future await?
future? await
代わりに、初心者の芳点から、これら2぀のうちどちらが正しいかを芋おください。
await future? === await (future?)
await future? === (await future)?

私はプレフィックスキヌワヌドawait futureに賛成です。

これは、async / awaitを備えたほずんどのプログラミング蚀語で䜿甚されおいるものであるため、それらの1぀を知っおいる人にはすぐに銎染みがありたす。

await future?の優先順䜍に぀いお、䞀般的なケヌスは䜕ですか

  • 埅たなければならないResult<Future>を返す関数。
  • Result  Future<Result>を返す、埅たなければならない未来。

I / O操䜜が倱敗する可胜性があるため、䞀般的なシナリオを凊理する堎合は、2番目のケヌスの方がはるかに䞀般的だず思いたす。 したがっお

await future? <=> (await future)?

あたり䞀般的ではない最初のケヌスでは、括匧を付けおもかたいたせん await (future?) 。 try!マクロが非掚奚になっおいない堎合、これはawait try!(future)䜿甚にも適しおいる可胜性がありたす。 このように、 awaitず疑問笊の挔算子は将来の異なる偎面にありたせん。

awaitを最初のasync関数パラメヌタヌずしお䜿甚しおみたせんか

async fn await_chain() -> Result<usize, Error> {
    let _ = partial_computation(await)
        .unwrap_or_else(or_recover)
        .run(await)?;
}

client.get("https://my_api")
    .send(await)?
    .json(await)?

let output = future
    .run(await);

ここで、 future.run(await)はawait future代わりになりたす。
それは、futureを取り、単にawait!()マクロを実行する通垞のasync関数である可胜性がありたす。

C ++同時実行TR

auto result = co_await task;

これはコルヌチンTSにあり、䞊行性ではありたせん。

別のオプションは、 await代わりにbecomeキヌワヌドを䜿甚するこずです。

async fn become_chain() -> Result<usize, Error> {
    let _ = partial_computation_future(become)
        .unwrap_or_else(or_recover_future)
        .start(become)?;
}

client.get("https://my_api")
    .send_future(become)?
    .json_future(become)?

let output = future.start(become);

becomeは、保蚌されたTCOのキヌワヌドになる可胜性がありたす

その[抂芁]を@EyeOfPythonに感謝したす。 これは、自転車小屋に参加したばかりの人にずっお特に䟿利です。

個人的には、 f awaitから離れるこずを望んでいたす。なぜなら、構文が非垞に玠朎でなく、特別で魔法のように芋えるからです。 Rustを初めお䜿甚するナヌザヌが倚くのこずに぀いお混乱するこずは、これらのこずの1぀になりたす。そしお、Rustのベテランでさえ、その䟡倀があるほど明確にはならないように感じたす。

@novacrazyこの匕数の問題は、 await!マクロが魔法のようになり、ナヌザヌ䜜成のコヌドでは䞍可胜な操䜜を実行するこずです。

@ Nemo157 await!マクロが魔法になるこずに同意したすが、これは問題ではないず䞻匵したす。 stdは、そのようなマクロがすでに耇数ありたす。たずえば、 compile_error! 、誰もそれらに぀いお䞍満を蚀っおいるのを芋たこずがありたせん。 マクロを䜿甚するのは、それがどのように行われるかではなく、䜕をするかを理解するだけであるのが普通だず思いたす。

私はPostfixが最も人間工孊的であろうず、以前のコメンタヌに同意するが、私はむしろ、接頭マクロから始めたすawait!(expr)それがものになるずし、埌眮マクロぞの朜圚的移行ではなく、持っおいるexpr.await マゞックコンパむラ組み蟌みフィヌルドたたはexpr.await() マゞックコンパむラ組み蟌みメ゜ッド。 どちらも、玔粋にこの機胜のための完党に新しい構文ず、蚀語の䞀貫性を損なうだけのIMOを導入したす。

@EyeOfPythonマむンドはあなたのリストずテヌブルにfuture(await)を远加したすか future.await()評䟡のすべおの肯定的な点は、匱点なしに移行しおいるようです

構文の匷調衚瀺にもかかわらず、 foo.awaitはフィヌルドアクセスに非垞に䌌おいるず䞻匵する人もいるため、トヌクン.を# 、代わりにfoo#awaitず曞くこずができたす。 。 䟋えば

let foo = alpha()#await?
    .beta#await
    .some_other_stuff()#await?
    .even_more_stuff()#await
    .stuff_and_stuff();

GitHubがこれを構文の匷調衚瀺でどのようにレンダリングするかを説明するために、 awaitをmatch眮き換えおみたしょう。これらは同じ長さなので、次のようになりたす。

let foo = alpha()#match?
    .beta#match
    .some_other_stuff()#match?
    .even_more_stuff()#match
    .stuff_and_stuff();

これは明確で人間工孊的であるように思われたす。

#の論理的根拠は特定されおいたせんが、トヌクンは非垞に目立ちたす。

だから、別の抂念未来が参照だった堎合

async fn log_service(&self) -> T {
   let service = self.myService.foo(); // Only construction
   *self.logger.log("beginning service call");
   let output = *service.exec(); // Actually wait for its result
   *self.logger.log("foo executed with result {}.", output);
   output
}

async fn try_log(message: String) -> Result<usize, Error> {
    let logger = *acquire_lock();
    // Very terse, construct the future, wait on it, branch on its result.
    let length = (*logger.log_into(message))?;
    *logger.timestamp();
    Ok(length)
}

async fn await_chain() -> Result<usize, Error> {
    *(*partial_computation()).unwrap_or_else(or_recover);
}

(*(*client.get("https://my_api").send())?.json())?

let output = *future;

これは本圓に醜くお䞀貫性がありたせん。 少なくずもその構文を明確にしたしょう。

async fn log_service(&self) -> T {
   let service = self.myService.foo(); // Only construction
   $self.logger.log("beginning service call");
   let output = $service.exec(); // Actually wait for its result
   $self.logger.log("foo executed with result {}.", output);
   output
}

async fn try_log(message: String) -> Result<usize, Error> {
    let logger = $acquire_lock();
    // Very terse, construct the future, wait on it, branch on its result.
    let length = ($logger.log_into(message))?;
    $logger.timestamp();
    Ok(length)
}

async fn await_chain() -> Result<usize, Error> {
    $($partial_computation()).unwrap_or_else(or_recover);
}

($($client.get("https://my_api").send())?.json())?

let output = $future;

より良いですが、それでも醜いですさらに悪いこずに、githubの構文が匷調衚瀺されたす。 ただし、これに察凊するために、プレフィックス挔算子を

async fn log_service(&self) -> T {
   let service = self.myService.foo(); // Only construction
   self.logger.$log("beginning service call");
   let output = service.$exec(); // Actually wait for its result
   self.logger.$log("foo executed with result {}.", output);
   output
}

async fn try_log(message: String) -> Result<usize, Error> {
    let logger = $acquire_lock();
    // Very terse, construct the future, wait on it, branch on its result.
    let length = logger.$log_into(message)?;
    logger.$timestamp();
    Ok(length)
}

async fn await_chain() -> Result<usize, Error> {
    ($partial_computation()).$unwrap_or_else(or_recover);
}

client.get("https://my_api").$send()?.$json()?

let output = $future;

これはたさに私が欲しいものです await $ だけでなく、deref * ずnegate ! も同様です。

この構文のいく぀かの譊告

  1. オペレヌタヌの優先順䜍私にずっおは明らかですが、他のナヌザヌにずっおは
  2. マクロの盞互運甚 $シンボルはここで問題を匕き起こしたすか
  3. 匏の䞍敎合先頭のプレフィックス挔算子は匏党䜓に適甚されたすが、遅延プレフィックス挔算子は.区切られた匏にのみ適甚されたす await_chain fnはそれを瀺しおいたす、それは混乱したすか
  4. 構文解析ず実装その構文はたったく有効ですか

@Centril
IMOが生のリテラル構文に近すぎたすr#"A String with "quotes""#

IMOが生のリテラル構文に近すぎたすr#"A String with "quotes""#

この堎合の違いは、コンテキストからはかなり明らかなようです。

@Centril
そうですが、構文もRustがIMHOを䜿甚するスタむルずはたったく異質です。 これは、同様の機胜を持぀既存の構文ずは䌌おいたせん。

@Laaas導入されたずき、 ?もしたせんでした。 .await行けたら嬉しいです; しかし、他の人はそれに䞍満を持っおいるように芋えるので、私はうたくいく䜕かを芋぀けようずしおいたす぀たり、明確で、人間工孊的で、入力が十分に簡単で、連鎖可胜で、優先順䜍が高い、 foo#awaitはそれをすべお満たすようです。

?は他にもたくさんの良い点がありたすが、 .awaitようなものが必芁な堎合は、 .await!ないでしょうか。

@Centrilこれがfuture(await)背埌にある䞻な理由であり、䜙分な挔算子や倖郚構文を远加する必芁がなく、フィヌルドアクセスを回避するためです。

#awaitはかなり恣意的です。

#は恣意的です、はい-それは成功ですか、それずも倱敗ですか ある時点で新しい構文が発明されたずき、誰かがそれが芋栄えが良いか理にかなっおいるず思ったので、それは恣意的でなければなりたせん。

なぜ.await!ないのですか

それも同様に恣意的ですが、私はそれに反察しおいたせん。

@Centrilこれがfuture(await)背埌にある䞻な理由であり、䜙分な挔算子や倖郚構文を远加する必芁がなく、フィヌルドアクセスを回避したした。

代わりに、 awaitをfuture枡す関数適甚のように芋えたす。 それは「フィヌルドアクセス」よりも混乱しおいるように私を襲いたす。

代わりに、それはあなたが通過しおいる関数適甚のように芋えたす。 それは「フィヌルドアクセス」よりも混乱しおいるように私を襲いたす。

私にずっお、それは簡朔さの䞀郚でした。 Awaitは、関数呌び出し呌び出し先があなたずあなたの結果の間で実行されるのような倚くの偎面であり、その関数にキヌワヌドを枡すこずで、これが別の皮類の呌び出しであるこずが明らかになりたした。 しかし、キヌワヌドが他の匕数ず類䌌しおいるこずがどのように混乱する可胜性があるかがわかりたす。 マむナスの構文の匷調衚瀺ず、そのメッセヌゞを補匷しようずするコンパむラ゚ラヌメッセヌゞ。先物は、埅機する以倖の方法で呌び出すこずはできたせん。その逆も同様です。

@Centril

恣意的であるこずは吊定的なこずではありたせんが、既存の構文に類䌌しおいるこずは肯定的なこずです。 .await!は完党に新しい構文ではないため、それほど恣意的ではありたせん。 結局のずころ、これはawaitずいう名前の修正埌のマクロにすぎたせん。

特にawait新しい構文に぀いお明確にする/芁点を远加するために、私が意味するのは、既存の構文ずは異なる新しい構文を導入するこずです。 プレフィックスキヌワヌドはたくさんあり、そのうちのいく぀かはRust 1.0の埌に远加されおいたす䟋 union が、AFAIKは単䞀のポストフィックスキヌワヌドではありたせんスペヌス、ドット、たたは他の䜕かで区切られおいおも 。 たた、接尟蟞のキヌワヌドを持぀他の蚀語は考えられたせん。

私芋では、Rustの奇劙さを倧幅に増加させない唯䞀の接尟蟞構文は、メ゜ッド呌び出しを反映しおいるが、以前にRustマクロを芋たこずがある人なら誰でもマクロずしお明確に識別できるため、接尟蟞マクロです。

暙準のawait!()マクロも気に入りたした。 それは明確で単玔です。
awaitedずしお共存するよりも、フィヌルドのようなアクセスたたは他の接尟蟞を奜みたす。

  • Awaitは、次の/正しいものが来るのを埅っおいるず感じおいたす。 埅っおいた、前に来た/去ったものに。
  • むテレヌタのcloned()メ゜ッドに䞀貫性がありたす。

たた、 @?が?ような砂糖ずしお奜きでした。
これは個人的なこずですが、 @は高すぎおラむンをアンダヌシュヌトする傟向があり、非垞に気が散るので、実際には&?組み合わせを奜みたす。 &も背が高い良いが、アンダヌシュヌトはしない良い。 残念ながら、 &すでに意味がありたすが、垞に?が続きたす。

䟋えば。

Lorem@?
  .ipsum@?
  .dolor()@?
  .sit()@?
  .amet@?
Lorem@?.ipsum@?.dolor()@?.sit()@?.amet@?

Lorem&?
  .ipsum&?
  .dolor()&?
  .sit()&?
  .amet&?
Lorem&?.ipsum&?.dolor()&?.sit()&?.amet&?

私にずっお、 @は肥倧化したキャラクタヌのように感じ、読曞の流れを邪魔したす。 䞀方、 &?は心地よく、私の読曞の邪魔にならず、 &ず?間に玠敵な䞊郚スペヌスがありたす。

個人的には、単玔なawait!マクロを䜿甚する必芁があるず思いたす。 修正埌のマクロが蚀語に組み蟌たれた堎合、マクロは単玔に展開できたすね。

@Laaas私が望む限り、Rustにはただ接尟蟞マクロがないので、それらは新しい構文です。 たた、 foo.await!.barずfoo.await!().barは同じサヌフェス構文ではないこずに泚意しおください。 埌者の堎合、実際の接尟蟞ず組み蟌みマクロがありたすキヌワヌドずしおawaitをあきらめる必芁がありたす。

@jplatte

倚くのプレフィックスキヌワヌドがあり、そのうちのいく぀かはRust 1.0の埌に远加されおいたす䟋 union 。

unionは単項匏挔算子ではないため、この比范には関係ありたせん。 Rustには正確に3぀の安定した単項プレフィックス挔算子 return 、 break 、およびcontinue があり、それらはすべお!入力されたす。

うヌん... @ 、私の以前の提案は少し良く芋えたす

client.get("https://my_api").@send()?.@json()?

let output = @future;

let foo = (@alpha())?
    .<strong i="8">@beta</strong>
    .@some_other_stuff()?
    .@even_more_stuff()
    .stuff_and_stuff();

@Centrilこれが私のポむントです。修正埌のマクロはただないので、単にawait!()たす。 たた、私は.await!() FYIを意味したした。 awaitはキヌワヌドである必芁はないず思いたすが、問題がある堎合は予玄できたす。

unionは単項匏挔算子ではないため、この比范には関係ありたせん。 Rustには正確に3぀の安定した単項プレフィックス挔算子 return 、 break 、およびcontinue があり、それらはすべお!入力されたす。

これは、たずえタむプが異なっおいおも、接頭蟞-キヌワヌドバリアントが単項匏挔算子のグルヌプに適合するこずを意味したす。 接尟蟞-キヌワヌドの倉圢は、既存の構文からのはるかに倧きな盞違であり、私の意芋では、蚀語におけるawaitの重芁性に関連しお倧きすぎたす。

プレフィックスマクロずポストフィックスぞの移行の可胜性に぀いお awaitは、これが機胜するためのキヌワヌドのたたである必芁がありたす。 その堎合、マクロは特別なlangアむテムになり、远加のr#なしで名前ずしおキヌワヌドを䜿甚でき、 r#await!()は同じマクロを呌び出すこずができたすが、おそらくそうすべきではありたせん。 それ以倖は、それを利甚可胜にするための最も実甚的な解決策のようです。

぀たり、 awaitをキヌワヌドずしお保持し、 await!をlang-itemマクロに解決したす。

@HeroicKatoraなぜそれが機胜するためにキヌワヌドのたたである必芁があるのですか

@Laaas移行の可胜性を開いたたたにしおおきたい堎合は、それをキヌワヌドずしお䜿甚する将来の修正埌の構文のために開いたたたにする必芁があるためです。 したがっお、移行のために゚ディションを䞭断する必芁がないように、キヌワヌドの予玄を維持する必芁がありたす。

@Centril

たた、foo.await.barずfoo.await。barは同じサヌフェス構文ではないこずに泚意しおください。 埌者の堎合、実際の接尟蟞ず組み蟌みマクロがありたすキヌワヌドずしおの埅機をあきらめる必芁がありたす。

キヌワヌドawaitを!ず組み合わせお内郚マクロ通垞の方法では定矩できないに解決するこずでこれを解決できたせんか その埌、キヌワヌドのたたですが、それ以倖の堎合はマクロ構文でマクロに解決されたす。

@HeroicKatora x.await!() awaitが予玄キヌワヌドになるのはなぜですか

そうではありたせんが、修正埌を未解決のたたにしおおけば、埌の議論で到達する解決策である必芁はありたせん。 それが唯䞀の合意された最良の可胜性である堎合、最初にこの正確な修正埌の構文を採甚する必芁がありたす。

これは、接尟蟞挔算子ずしおはるかにうたく機胜する䜕かに出くわすもう1぀の機䌚です。 この倧きな䟋はtry!で、最終的には独自のシンボル? 。 ただし、接尟蟞挔算子がより最適であり、すべおに独自の特別な文字を䞎えるこずができないのはこれが最埌ではないず思いたす。 したがっお、少なくずも@始めるべきではないず思いたす。 このようなこずをする方法があればもっずいいでしょう。 そのため、接尟蟞マクロスタむル.await!()をサポヌトしおいたす。

let x = foo().try!();
let y = bar().await!();

しかし、これが意味のある接尟蟞マクロを理解するには、それら自䜓を導入する必芁がありたす。 したがっお、通垞のawait!(foo)マクロ構文から始めるのが最善だず思いたす。 これがそれ自䜓のシンボルを正圓化するのに十分重芁であるず本圓に感じた堎合、埌でこれをfoo.await!()たたはfoo@に拡匵するこずができたす。
このマクロに少しの魔法が必芁になるこずは、stdにずっお目新しいこずではなく、私にずっおは倧きな問題ではありたせん。
@jplatteが蚀ったように

@ Nemo157 await!マクロが魔法になるこずに同意したすが、これは問題ではないず䞻匵したす。 stdは、そのようなマクロがすでに耇数ありたす。たずえば、 compile_error! 、誰もそれらに぀いお䞍満を蚀っおいるのを芋たこずがありたせん。 マクロを䜿甚するのは、それがどのように行われるかではなく、䜕をするかを理解するだけであるのが普通だず思いたす。

ここで説明しおいる繰り返し発生する問題は、チェヌンずその䜿甚方法に関するものです。
匏を連鎖させるのを埅ちたす。 倚分別の解決策があるかもしれたせんか

連鎖のためにawaitを䜿甚せず、awaitforのみを䜿甚する堎合
割り圓お、letをawaitに眮き換えるようなものがありたす
await foo = future

次に、チェヌンの堎合、 await res = fut1 -> fut2やawait res = fut1 >>= fut2ようなある皮の操䜜を想像できたす。

欠萜しおいる唯䞀のケヌスは、結果を埅っお返すこずです、いく぀かのショヌトカット
await res = fut; res 。
これは、単玔なawait futで簡単に実行できたす。

私はこのような別の提案を芋たこずがないず思いたす少なくずも
チェヌンなので、ここにドロップするずいいず思いたす。

@HeroicKatoraリストにfut(await)を远加し、私の意芋に埓っおランク付けしたした。

誰かが私の埗点がずれおいるず感じたら、教えおください

構文的には、 .await!()はクリヌンで、構文に奇劙な点を远加せずに連鎖できるず思いたす。

ただし、「実際の」接尟蟞マクロを取埗した堎合、おそらく.r#await!()がシャドりされる可胜性があるのに察し、 .await!()はシャドりむングできないため、少し奇劙になりたす。

awaitが匏の次の郚分に結合されおいるこずがわかったため、「postfixキヌワヌド」オプション foo() await?.bar() await?ようなスペヌスで区切るにはかなり匷く反察しおいたす。それが動䜜する郚分ではありたせん。 ここでは、空癜以倖のほずんどすべおの蚘号を奜みたす。たた、長いチェヌンの欠点にもかかわらず、これよりもプレフィックス構文を奜みたす。

必須の区切り文字は単䞀のステヌトメントを埅぀ずいう非垞に䞀般的なケヌスにずっお苊痛であり、「有甚な優先順䜍」はたったくないため、「明癜な優先順䜍」 await?砂糖を䜿甚が明らかに最良のプレフィックスオプションだず思いたす盎感的で、したがっお混乱したす。

構文的には、 .await!()はクリヌンで、構文に奇劙な点を远加せずに連鎖できるず思いたす。

ただし、「実際の」接尟蟞マクロを取埗した堎合、おそらく.r#await!()がシャドりされる可胜性があるのに察し、 .await!()はシャドりむングできないため、少し奇劙になりたす。

postfixマクロを取埗し、 .await!()を䜿甚する堎合、キヌワヌドずしおawaitを予玄解陀し、それをpostfixマクロにするこずができたす。 このマクロの実装には、ただ少しの魔法が必芁ですが、今日のcompiler_error!ように実際のマクロになりたす。

@EyeOfPython forward-compatibility怜蚎する倉曎に぀いお詳しく説明しおいただけたすか fut@awaitがfut.await!()より高く、 await { future }がawait!(future)より䜎くなる方法がわかりたせん。 verbosity列も少し奇劙に芋えたす。䞀郚の匏は短いですが、評䟡が䜎く、連鎖ステヌトメントなどが考慮されおいたす。他のすべおはバランスが取れおいるようで、これたでで最もよく凝瞮された広範な評䟡のようです。

この議論を読んだ埌、倚くの人が通垞のawait!()マクロを远加し、埌で埌眮バヌゞョンを理解したいず思っおいるようです。 これは、実際にpostfixバヌゞョンが必芁であるず想定しおいたす。これに぀いおは、このコメントの残りの郚分でも圓おはたりたす。

だから私はここにいるみんなの意芋を調査したいず思いたす今のずころawait!(future)構文に党員が同意する必芁がありたすか 長所は、その構文に構文解析のあいたいさがなく、マクロでもあるため、この倉曎をサポヌトするために蚀語の構文を倉曎しないこずです。 短所は、チェヌンの芋栄えが悪いこずですが、この構文は簡単に埌眮バヌゞョンに自動的に眮き換えるこずができるため、それは問題ではありたせん。

それを解決しお蚀語に実装したら、postfix await構文に぀いおの議論を続け、できればもっず成熟した経隓、アむデア、そしおおそらく他のコンパむラ機胜を䜿甚するこずができたす。

@HeroicKatora awaitを解攟しお通垞の識別子ずしお自然に䜿甚でき、他の接尟蟞挔算子を远加できるので、私はそれを高く評䟡したしたが、 fut.await!()はawait方が良いず思いたすfut.await!()が高い可胜性があるこずも間違いなく有効です。

await { future }ずawait!(future)堎合、埌者はオプションを開いたたたにしお他のほずんどすべおのオプションに倉曎できたすが、前者は実際にはawait futureバリアントのいずれかのみを蚱可したす @withoutboatsのブログ゚ントリに蚘茉されおいるfwd(await { future }) < fwd(await!(future))であるべきだず思いたす。

冗長性に぀いおは、正解です。ケヌスをサブグルヌプに分割した埌、冗長性を再評䟡したせんでした。これは、すべおの䞭で最も客芳的なものであるはずです。

コメントを考慮しお線集したす、ありがずうございたす

await!(future)安定させるこずは、私が想像できる最悪の遞択肢です。

  1. これは、 awaitを予玄解陀する必芁があるこずを意味したす。これは、将来の蚀語蚭蚈がさらに困難になるこずを意味したす。
  2. これは、非掚奚ずなったtry!(result)ず同じルヌトを意図的に取っおいたすRust 2018でr#try!(result)を蚘述する必芁がありたす。

    • await!(future)が䞍適切な構文であるこずがわかっおいる堎合、最終的には非掚奚にするこずを意味したす。これは意図的に技術的負債を生み出しおいたす。

    • さらに、 try!(..)はRustで定矩されおいたすが、 await!(future)は定矩できず、代わりにコンパむラの魔法になりたす。

    • try!(..)廃止は容易ではなく、瀟䌚的に倧きな打撃を䞎えたした。 その詊緎をもう䞀床経隓するこずは魅力的ではないようです。

  3. これは、蚀語の䞭心的で重芁な郚分の1぀にマクロ構文を䜿甚したす。 それは明らかに䞀流ではないようです。
  4. await!(future)はうるさいです; 異なり、 await future次のように蚘述する必芁がありたす!( ... ) 。
  5. Rust API、特に暙準ラむブラリは、メ゜ッド呌び出し構文を䞭心ずしおいたす。 たずえば、 Iteratorを凊理する堎合、メ゜ッドをチェヌンするのが䞀般的です。 await { future }およびawait future同様に、 await!(future)構文はメ゜ッドチェヌンを困難にし、䞀時的なletバむンディングを誘発したす。 これは人間工孊にずっおも、読みやすさに぀いおも私の芋解では悪いこずです。

@Centril同意したいのですが、いく぀かの未解決の質問がありたす。 1.よろしいですか それを「魔法」にするず、キヌワヌドずしおドロップせずにマクロを参照できるようにするこずで、さらに魔法にするこずはできたせんか

私はRustに参加するのが遅すぎお、 2.の瀟䌚的芖点を評䟡できたせんtry!から倉換されおいないため、それが解決策であったこずは明らかです。 それは、゚ディション2018に移行するむンセンティブずしお、 async/awaitを䜿甚するのか、それずも蟛抱匷くこれを繰り返さないのかずいう問題を提起したす。

3.に非垞によく䌌た他の2぀のimho䞭心機胜 vec![]ずformat! / println! 。 前者は安定したボックス構造がないためです。埌者はフォヌマット文字列構造であり、䟝存型の匏がないためです。 これらの比范も郚分的に4.を別の芖点に眮いおいるず思いたす。

私は英語のように読めない構文には反察です。 IE、「awaitx」は英語のようなものを読みたす。 「x!! @」はそうではありたせん。 「x.await」は英語のように興味をそそるように読みたすが、xが長い名前のメンバヌ関数呌び出しや䞀連の連鎖むテレヌタヌメ゜ッドなどの重芁な行である堎合はそうではありたせん。

具䜓的には、「keyword x」をサポヌトしおいたす。ここで、keywordはおそらくawaitです。 私はC ++コルヌチンTSずUnityのcコルヌチンの䞡方を䜿甚しおおり、どちらもそれに非垞によく䌌た構文を䜿甚しおいたす。 そしお、それらを本番コヌドで䜕幎も䜿甚した埌、私の信念は、あなたの歩留たりポむントがどこにあるかを䞀目で知るこずは絶察に重芁であるずいうこずです。 関数のむンデント行をざっず読むず、200行の関数のすべおのco_await / yield returnを、認知的負荷なしで数秒で遞択できたす。

同じこずは、埌で埅機するドット挔算子、たたは他の接尟蟞「シンボルの山」構文には圓おはたりたせん。

awaitは基本的な制埡フロヌ操䜜だず思いたす。 'if 、 while 、 match 、およびreturnず同じレベルの敬意を払う必芁がありたす。 それらのいずれかが接尟蟞挔算子であるず想像しおみおください-Rustコヌドを読むこずは悪倢です。 私のawaitの議論ず同様に、Rust関数のむンデント行をスキミングしお、すべおの制埡フロヌをすぐに遞択できたす。 䟋倖はありたすが、それは䟋倖であり、私たちが努力すべきものではありたせん。

@ejmahlerに同意したす。 開発の反察偎であるコヌドレビュヌを忘れおはなりたせん。 ゜ヌスコヌドを含むファむルは、読み取られおから曞き蟌たれるこずがはるかに倚いため、曞き蟌みよりも読み取りず理解の方が簡単なはずです。 コヌドレビュヌでは、降䌏点を芋぀けるこずが非垞に重芁です。 そしお私は個人的にUseful precedence投祚したす。
私はこれを信じおいたす

...
let response = await client.get("https://my_api").send()?;
let body: MyResponse = await response.into_json()?;

これよりも理解しやすいです

...
let body: MyResponse = client.get("https://my_api").send().await?.into_json().await?;

@HeroicKatora

@Centril同意したいのですが、いく぀かの未解決の質問がありたす。 1.よろしいですか それを「魔法」にするず、キヌワヌドずしおドロップせずにマクロを参照できるようにするこずで、さらに魔法にするこずはできたせんか

技術的には おそらく。 ただし、特別な堎合には匷力な正圓化が必芁であり、この堎合、魔法に魔法をかけるこずは正圓化されおいないようです。

それは、゚ディション2018に移行するむンセンティブずしお、 async/awaitを䜿甚するのか、それずも蟛抱匷くこれを繰り返さないのかずいう問題を提起したす。

新しいモゞュヌルシステム、 async / await 、およびtry { .. }をむンセンティブにする぀もりだず蚀ったかどうかはわかりたせん。 しかし、私たちの意図に関係なく、それは良いこずだず思いたす。 私たちは、人々が最終的に新しい蚀語機胜を䜿甚しお、より優れた慣甚的なラむブラリを䜜成し始めるこずを望んでいたす。

3.に非垞によく䌌た他の2぀のimho䞭心機胜 vec![]ずformat! / println! 。 前者は、安定した箱型構造のアファむクがないため、非垞に

前者は存圚し、 vec![1, 2, 3, ..]ず蚘述されお、配列リテラル匏を暡倣したす䟋 [1, 2, 3, ..] 。

@ejmahler

「x.await」は英語のように興味をそそるように読みたすが、xが長い名前のメンバヌ関数呌び出しや䞀連の連鎖むテレヌタヌメ゜ッドなどの重芁な行である堎合はそうではありたせん。

チェヌンされたむテレヌタメ゜ッドの束の䜕が問題になっおいたすか それは明らかに慣甚的なRustです。
rustfmtツヌルは、メ゜ッドチェヌンをさたざたな行にフォヌマットするため、次のようになりたすここでも、 matchを䜿甚しお構文の匷調衚瀺を衚瀺したす。

let foo = alpha().match?  // or `alpha() match?`, `alpha()#match?`, `alpha().match!()?`
    .beta
    .some_other_stuff().match?
    .even_more_stuff().match
    .stuff_and_stuff();

.awaitを「それから埅぀」ず読んだ堎合、少なくずも私にずっおは完党に読みたす。

そしお、それらを本番コヌドで䜕幎も䜿甚した埌、私の信念は、あなたの歩留たりポむントがどこにあるかを䞀目で知るこずは絶察に重芁であるずいうこずです。

特に䞊蚘のrustfmtフォヌマットでは、postfix awaitがそれをどのように吊定するのかわかりたせん。 さらに、あなたは曞くこずができたす

let foo = alpha().match?;
let bar = foo.beta.some_other_stuff().match?;
let baz = bar..even_more_stuff().match;
let quux = baz.stuff_and_stuff();

あなたがそれを空想するなら。

認知的負荷なしで、ほんの数秒で200行の機胜で。

特定の機胜に぀いおあたり知らない限り、200 LOCはおそらく単䞀責任の原則に違反し、やりすぎであるように思われたす。 解決策は、それをより少なくし、それを分割するこずです。 実際、それが保守性ず読みやすさにずっお最も重芁なこずだず思いたす。

awaitは基本的な制埡フロヌ操䜜だず思いたす。

?です。 実際、 awaitず?はどちらも、「コンテキストから倀を抜出する」ずいう効果的な制埡フロヌ操䜜です。 蚀い換えるず、ロヌカルコンテキストでは、これらの挔算子のタむプがawait : impl Future<Output = T> -> Tおよび? : impl Try<Ok = T> -> Tず想像できたす。

䟋倖はありたすが、それは䟋倖であり、私たちが努力すべきものではありたせん。

そしお、ここでの䟋倖は?ですか

@andreytkachenko

@ejmahlerに同意したす。 開発の反察偎であるコヌドレビュヌを忘れおはなりたせん。 ゜ヌスコヌドを含むファむルは、読み取られおから曞き蟌たれるこずがはるかに倚いため、曞き蟌みよりも読み取りず理解の方が簡単なはずです。

䞍䞀臎は、読みやすさず人間工孊にずっお䜕が最善かずいうこずです。

これよりも理解しやすいです

...
let body: MyResponse = client.get("https://my_api").send().await?.into_json().await?;

これはフォヌマット方法ではありたせん。 rustfmtを実行するず、次のようになりたす。

let body: MyResponse = client
    .get("https://my_api")
    .send()
    .match?
    .into_json()
    .match?;

@ejmahler @andreytkachenkoここで促されるこずです。 これはRust-yではなく、通垞のフォヌマット芏則が修正埌の構文でこれを補いたす。 たた、 awaitは実際には、yieldのコヌドポむントではなく、yieldポむントに配眮されおいないため、プレフィックス構文ではyield-pointがよりあいたいであるず考えおいたす。

あなたはこの道を行く堎合は、むしろしお、それを綎るのための実隓をしたしょうawaitの代わりずしおlet本圓にこれを斜行する@Keruspeのアむデアの粟神むンチそれらはストレッチのように芋えるので、他の構文拡匵なし。

await? response = client.get("https://my_api").send();
await? body: MyResponse = response.into_json();

しかし、これらのどれに぀いおも、文法におけるそれらの構成可胜性の喪倱ず耇雑さを説明するのに十分な利点は芋られたせん。

うヌん...接頭蟞ず接尟蟞の䞡方の圢匏を埅぀こずが望たしいですか それずも接尟蟞の圢だけですか

メ゜ッド呌び出しを連鎖させるこずは、特に話しおいるずきに慣甚的です
むテレヌタずはるかに少ない皋床のオプションですが、それを陀けば、錆は
最初に呜什型蚀語、次に関数型蚀語。

私は接尟蟞が文字通り理解できないず䞻匵しおいるのではありたせん、私はマキンです
最䞊䜍の制埡フロヌ操䜜を隠す認知的負荷の議論、
「リタヌン」ず同じ重芁性を持ち、次の堎合に認知的負荷を増加させたす
行頭の近くに眮くのず比范しお-そしお私は
この議論は、長幎の生産経隓に基づいお行われたす。

11:59マズダク教Farrokhzadで土、2019幎1月19日には[email protected]
曞きたした

@HeroicKatora https://github.com/HeroicKatora

@Centril https://github.com/Centril同意したいのですが、ありたす
いく぀かの未解決の質問。 1に぀いおよろしいですか 私たちがそれを「魔法」にすれば
これがマクロなしでマクロを参照できるようにするこずで、それをさらに魔法にするこずはありたせん
キヌワヌドずしおドロップしたすか

技術的には おそらく。 ただし、
特別な堎合、そしおこの堎合、魔法に魔法をかけるこずはないようです
正圓化されたす。

それは私たちが非同期/埅機する぀もりかどうかずいう問題を提起したす
2018幎版に移行するむンセンティブ、たたはむしろ忍耐匷く、
これを繰り返したす。

新しいモゞュヌルシステム、async /を意図しおいるず蚀ったかどうかはわかりたせん
埅っお、{..}をむンセンティブにしようずしたす。 しかし、私たちの意図に関係なく
圌らはそうです、そしおそれは良いこずだず思いたす。 最終的には人々に
新しい蚀語機胜を䜿甚しお、より良く、より慣甚的な文章を曞き始めたす
ラむブラリ。

3に非垞によく䌌た他の2぀のimho䞭心機胜vec[]ずformat/
println。 前者は安定した箱がないのでずおも
建蚭afaik、

前者は存圚し、配列を暡倣するためにvec[1、2、3、..]ず曞かれおいたす。
リテラル匏、䟋[1、2、3、..]。

@ejmahler https://github.com/ejmahler

「x.await」は英語のように食欲をそそるように読みたすが、xが
長い名前のメンバヌ関数呌び出しや束などの重芁な行
連鎖むテレヌタメ゜ッドなどの

チェヌンされたむテレヌタメ゜ッドの束の䜕が問題になっおいたすか それは明らかに
慣甚的なさび。
rustfmtツヌルは、メ゜ッドチェヌンをさたざたな行にフォヌマットするため、
getここでもmatchを䜿甚しお構文の匷調衚瀺を衚瀺したす

foo = alpha。match //たたはalpha() match? 、 alpha()#match? 、 alpha().match!()?
。ベヌタ
.some_other_stuff。match
.even_more_stuff。match
.stuff_and_stuff;

.awaitを「thenawait」ず読むず、少なくずも私にずっおは完党に読みたす。

そしお、生産コヌドでそれらを䜿甚しお数幎埌、私の信念は知っおいるずいうこずです䞀目であなたのむヌルドポむントがどこにあるかは絶察に重芁です。

特にrustfmtでは、postfixがどのようにそれを吊定するのかわかりたせん
䞊蚘のフォヌマット。 さらに、あなたは曞くこずができたす

let foo = alpha。match ; let bar = foo.beta.some_other_stuff。match ; let baz = bar..even_more_stuff。match; let quux = baz.stuff_and_stuff;

あなたがそれを空想するなら。

認知的負荷なしで、ほんの数秒で200行の機胜で。

特定の機胜に぀いおあたり知らなくおも、私には思えたす
その200LOCは、おそらく単䞀責任の原則に違反しおおり、
過床に。 解決策は、それをより少なくし、それを分割するこずです。 実際、私は
それが保守性ず読みやすさにずっお最も重芁なこずだず思いたす。

埅機は基本的な制埡フロヌ操䜜だず思いたす。

そうですか 実際、埅っお どちらも効果的な制埡フロヌ操䜜です
それは「文脈から䟡倀を匕き出す」ず蚀っおいたす。 蚀い換えれば、地元で
コンテキストでは、次のタむプの挔算子がawaitimplであるず想像できたす。
未来-> Tず impl Try-> T。

䟋倖はありたすが、それは䟋倖であり、私たちがすべきこずではありたせん。
のために努力。

そしおここでの䟋倖は 

@andreytkachenko https://github.com/andreytkachenko

@ejmahlerhttps  //github.com/ejmahlerに同意したす。 すべきではない
開発の反察偎を忘れおください-コヌドレビュヌ。 ゜ヌスコヌド付きのファむルは
読んだり曞いたりするこずがはるかに倚いので、もっず簡単にできるはずです
読んで理解しおから曞く。

䞍䞀臎は、読みやすさず
人間工孊。

これよりも理解しやすいです

...本文MyResponse = client.get "https// my_api"。send。await.into_json。await;

これはフォヌマット方法ではありたせん。 慣甚的なrustfmtフォヌマット
は

本䜓MyResponse =クラむアント
.get "https// my_api"
.send
。䞀臎
.into_json
。䞀臎;

—
あなたが蚀及されたのであなたはこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/rust-lang/rust/issues/57640#issuecomment-455810497 、
たたはスレッドをミュヌトしたす
https://github.com/notifications/unsubscribe-auth/ABGmeocFJpPKaypvQHo9LpAniGOUFrmzks5vE3kXgaJpZM4aBlba
。

@ejmahler私たちはreに同意したせん。 "隠蔜"; 同じ議論がなされた。

?挔算子は非垞に短く、過去に返品を「隠す」ず批刀されおきたした。 ほずんどの堎合、コヌドは曞き蟌たれるのではなく、読み取られたす。 名前を?!に倉曎するず、2倍の長さになり、芋萜ずしにくくなりたす。

それにもかかわらず、私たちは最終的に?を安定させ、それ以来、予蚀は実珟しなかったず思いたす。
私にずっお、接尟蟞awaitは、自然な読み順に埓いたす少なくずも巊から右の蚀語を話す人にずっお。 特に、デヌタフロヌの順序に埓いたす。

構文の匷調衚瀺は蚀うたでもありたせん。埅機に関連するものはすべお明るい色で匷調衚瀺できるため、䞀目で芋぀けるこずができたす。 したがっお、実際のawait単語の代わりに蚘号があったずしおも、構文が匷調衚瀺されたコヌドで非垞に読みやすく、芋぀けやすくなりたす。 そうは蚀っおも、私はただawait単語をgrepの理由で䜿甚するこずを奜みたす-蚘号の代わりにawait単語だけを䜿甚するず、埅っおいるものすべおのコヌドをgrepする方が簡単です@やのように、その意味は文法に䟝存したす。

これはすべおロケット科孊ではありたせん

let body: MyResponse = client.get("https://my_api").send()...?.into_json()...?;

接尟蟞...は非垞に読みやすく、䞀目で芋逃しにくく、将来の結果が利甚可胜になるのを埅぀間、コヌドの䞀皮の末尟ずしお自然に読み取られるため、非垞に盎感的です。 誰もが以前に楕円を芋たこずがあるので、優先順䜍/マクロシェナニガンは必芁なく、芋慣れないシゞルからの䜙分なラむンノむズもありたせん。

@solsonに謝眪

@ ben0x539぀たり、 future()....startような結果のメンバヌにアクセスできるずいうこずですか たたは、 range().....ような範囲の結果を埅ちたすか そしお、珟圚の省略蚘号..は、右偎の二項挔算子たたは二項挔算子である必芁があり、これは䞀目で非垞に近いので、 no precedence/macro shenanigans necessary and正確に意味したす。

はい  オペレヌタヌが存圚したす。 私はすでにあったこずを認めたした
䟋倖。 しかし、それは䟋倖です。 制埡フロヌの倧郚分は
Rustプログラムは、プレフィックスキヌワヌドを介しお行われたす。

13:51ベンゞャミン君の土、2019幎1月19日には[email protected]
曞きたした

これはすべおロケット科孊ではありたせん

let bodyMyResponse = client.get "https// my_api"。send...。into_json...;

接尟蟞...は非垞に読みやすく、䞀目で芋逃しがたいです。
あなたはそれをコヌドのようなものずしお自然に読むので盎感的です
将来の結果が利甚可胜になるのを埅぀間。 番号
優先順䜍/マクロシェナニガンが必芁であり、からの䜙分なラむンノむズはありたせん
誰もが以前に楕円を芋たこずがあるので、なじみのないシゞル。

—
あなたが蚀及されたのであなたはこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/rust-lang/rust/issues/57640#issuecomment-455818177 、
たたはスレッドをミュヌトしたす
https://github.com/notifications/unsubscribe-auth/ABGmen354fhk7snYsANTfp5oOuDb4OLYks5vE5NSgaJpZM4aBlba
。

@HeroicKatora少し人工的に芋えたすが、確かにそうです。 これは、提案されおいる他の接尟蟞゜リュヌションず同様に、接尟蟞操䜜であるため、 await x?盎感に反する優先順䜍の必芁性を回避し、マクロではないこずを意味したした。

@ejmahler

はい  オペレヌタヌが存圚したす。 私はすでに䟋倖があったこずを認めたした。 しかし、それは䟋倖です。

keyword exprに適合する2぀の匏圢匏、぀たりreturn exprずbreak exprたす。 前者は埌者よりも䞀般的です。 continue 'label圢匏は、匏ではありたすが、 keyword expr圢匏ではないため、実際にはカりントされたせん。 これで、2぀の接頭蟞キヌワヌド単項匏フォヌムず1぀の埌眮単項匏フォヌムができたした。 ?ずawaitがawaitずreturnよりも䌌おいるこずを考慮する前に、私はreturn/break exprずはほずんど呌びたせん。 ?が䟋倖ずなるルヌル。

Rustプログラムの制埡フロヌの倧郚分は、プレフィックスキヌワヌドを介しお行われたす。

前述のように、 break exprはそれほど䞀般的ではありたせん break;がより䞀般的で、 return;がより䞀般的であり、単項匏ではありたせん。 残っおいるのは初期のreturn expr;あり、これがmatch 、 ? 、ネストされたif letよりもはるかに䞀般的であるこずは私にはたったくわかりたせん。 else s、およびforルヌプ。 try { .. }安定したら、 ?がさらに䜿甚されるず思いたす。

@ ben0x539準備ができたら、可倉個匕数ゞェネリック甚に...を予玄する必芁があるず思いたす

私はここでpostfix構文で革新するずいうアむデアが本圓に奜きです。 フロヌの方がはるかに理にかなっおおり、プレフィックスtry!からポストフィックス?移行したずきに、コヌドがどれだけ改善されたかを芚えおいたす。 Rustコミュニティで、コヌドがどれだけ改善されたかを䜓隓した人はたくさんいるず思いたす。

.awaitのアむデアが気に入らない堎合は、実際の接尟蟞挔算子を芋぀けるためにある皋床の創造性を発揮できるず確信しおいたす。 䞀䟋ずしお、 ++たたは@を䜿甚しお埅機するこずが考えられたす。

:(私はもう埅ちたくないだけです。

誰もがマクロ構文に慣れおいたす。他の意芋で始たるこのスレッドのほずんどの人は、最終的にマクロ構文を奜むようです。

確かにそれは「魔法のマクロ」になるでしょうが、ナヌザヌはマクロ展開がどのように芋えるかを気にするこずはめったになく、そうする人にずっおは、ドキュメントでニュアンスを説明するのは簡単です。

通垞のマクロ構文は、アップルパむのようなもので、誰もが2番目に奜きなオプションですが、その結果、家族が奜きなオプションです[0]。 重芁なのは、tryのように 埌でい぀でも倉曎できたす。 しかし、最も重芁なこずは、私たち党員が同意するのが早ければ早いほど、実際にそれを䜿い始めお生産的になるこずができるのです

[0]最初の1分間に参照 https://www.ted.com/talks/kenneth_cukier_big_data_is_better_data/transcript?language=en

match、if、if let、while、while、forは、すべお広範な制埡フロヌです。
プレフィックスを䜿甚したす。 䌑憩ず続行のふりをするこずが唯䞀の制埡フロヌです
キヌワヌドはむラむラするほど誀解を招くものです。

15:37 Yazad Daruvalaで土、2019幎1月19日には[email protected]
曞きたした

:(私はもう埅ちたくないだけです。

誰もがマクロ構文に慣れおいたす。このスレッドのほずんどの人は
他の意芋から始めお、マクロ構文を支持するこずになったようです。

確かにそれは「魔法のマクロ」になるでしょうが、ナヌザヌはマクロが䜕であるかを気にするこずはめったにありたせん
拡匵は次のように芋えたす。そうする人にずっおは、説明するのは簡単です。
ドキュメントのニュアンス。

通垞のマクロ構文はアップルパむのようなもので、みんなの2番目です
お気に入りのオプションですが、結果ずしお家族のお気に入りのオプション[0]。
重芁なのは、tryのように 埌でい぀でも倉曎できたす。 しかし、ほずんどの
重芁なのは、私たち党員が同意するのが早ければ早いほど、私たち党員が早く始めるこずができるずいうこずです。
実際に䜿甚しお生産性を高めたしょう

[0]最初の1分間に参照
https://www.ted.com/talks/kenneth_cukier_big_data_is_better_data/transcript?language=en

—
あなたが蚀及されたのであなたはこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/rust-lang/rust/issues/57640#issuecomment-455824275 、
たたはスレッドをミュヌトしたす
https://github.com/notifications/unsubscribe-auth/ABGmesz5_LfDKdcKn6zMO5uuSJs9lFiYks5vE6wygaJpZM4aBlba
。

@mitsuhiko同意したす チェヌンにより、Postfixはより玠朎に感じたす。 私が提案したfut@await構文は、他の提案ほど倚くの欠点がないように芋えるもう1぀の興味深いオプションだず思いたす。 それがあたりにも遠すぎお、もっず珟実的なバヌゞョンが望たしいかどうかはわかりたせんが。

@ejmahler

match、if、if let、while、while let、およびforはすべお、プレフィックスを䜿甚する広範な制埡フロヌです。 ブレヌクずコンティニュヌのふりをするこずが、むラむラするほど誀解を招く唯䞀の制埡フロヌキヌワヌドです。

誀解を招くこずはたったくありたせん。 これらの構成に関連する文法は倧たかに次のずおりです。

Expr = kind:ExprKind;
ExprKind =
  | If:{ "if" cond:Cond then:Block { "else" else_expr:ElseExpr }? };
  | Match:{ "match" expr:Expr "{" arms:MatchArm* "}" }
  | While:{ { label:LIFETIME ":" }? "while" cond:Cond body:Block }
  | For:{ { label:LIFETIME ":" }? "for" pat:Pat "in" expr:Expr body:Block }
  ;

Cond =
  | Bool:Expr
  | Let:{ "let" pat:Pat "=" expr:Expr }
  ;

ElseExpr =
  | Block:Block
  | If:If
  ;

MatchArm = pats:Pat+ % "|" { "if" guard:Expr }? "=>" body:Expr ","?;

ここで、フォヌムはif/while expr block 、 for pat in expr block 、およびmatch expr { pat0 => expr0, .., patn => exprn }です。 これらすべおの圢匏で、埌に続くものの前にキヌワヌドがありたす。 これが「プレフィックスを䜿甚する」ずいう意味だず思いたす。 ただし、これらはすべおブロック圢匏であり、単項接頭挔算子ではありたせん。 したがっお、 await exprずの比范は、䞀貫性やルヌルがないため、誀解を招く恐れがありたす。 ブロックフォヌムずの䞀貫性を保぀堎合は、 await blockではなくawait expr await blockず比范しおください。

@mitsuhiko同意したす チェヌンにより、Postfixはより玠朎に感じたす。

さびは二元論的です。 呜什型アプロヌチず機胜的アプロヌチの䞡方をサポヌトしたす。 堎合によっおは、それぞれがより適しおいる可胜性があるため、問題ないず思いたす。

知りたせん。 䞡方があれば玠晎らしいず思いたす

await foo.bar();
foo.bar().await;

しばらくScalaを䜿っおいたので、私もそのように機胜するこずがたくさん奜きでした。 特にmatchずifは、Rustの接尟蟞の䜍眮にあるず䟿利です。

foo.bar().await.match {
   Bar1(x, y) => {x==y},
   Bar2(y) => {y==7},
}.if {
   bazinga();
}

これたでのたずめ

オプションマトリックス

オプションの芁玄マトリックス @を印章ずしお䜿甚したすが、ほずんど䜕でもかたいたせん

| 名前| Future<T> | Future<Result<T, E>> | Result<Future<T>, E> |
| --- | --- | --- | --- |
| プレフィックス| -| -| -|
| キヌワヌドマクロ| await!(fut) | await!(fut)? | await!(fut?) |
| キヌワヌド機胜| await(fut) | await(fut)? | await(fut?) |
| 有甚な優先順䜍| await fut | await fut? | await (fut?) |
| 明らかな優先順䜍| await fut | await? fut | await fut? |
| POSTFIX | -| -| -|
| キヌワヌド付きFn | fut(await) | fut(await)? | fut?(await) |
| キヌワヌドフィヌルド| fut.await | fut.await? | fut?.await |
| キヌワヌドメ゜ッド| fut.await() | fut.await()? | fut?.await() |
| 接尟蟞キヌワヌドマクロ| fut.await!() | fut.await!()? | fut?.await!() |
| スペヌスキヌワヌド| fut await | fut await? | fut? await |
| シゞルキヌワヌド| fut@await | fut@await? | fut?@await |
| シゞル| fut@ | fut@? | fut?@ |

「SigilKeyword」のsigilは#になるこずはできたせん。その堎合、 rずいう未来ではそれを行うこずができたせん。 ...は、私の最初の心配のように、印章がトヌクン化を倉曎する必芁がないためです。

より珟実の䜿甚PM私の耇数持぀他の_real_のナヌスケヌスawait urloに、私はそれらを远加したす

| 名前| reqwest Client |> Client::get |> RequestBuilder::send |> await |> ? |> Response::json | > ? |
| --- | --- |
| プレフィックス| -|
| キヌワヌドマクロ| await!(client.get("url").send())?.json()? |
| キヌワヌド機胜| await(client.get("url").send())?.json()? |
| 有甚な優先順䜍| (await client.get("url").send()?).json()? |
| 明らかな優先順䜍| (await? client.get("url").send()).json()? |
| POSTFIX | -|
| キヌワヌド付きFn | client.get("url").send()(await)?.json()? |
| キヌワヌドフィヌルド| client.get("url").send().await?.json()? |
| キヌワヌドメ゜ッド| client.get("url").send().await()?.json()? |
| 接尟蟞キヌワヌドマクロ| client.get("url").send().await!()?.json()? |
| スペヌスキヌワヌド| client.get("url").send() await?.json()? |
| シゞルキヌワヌド| client.get("url").send()@await?.json()? |
| シゞル| client.get("url").send()@?.json()? |

線集メモ Response::jsonがFutureも返すこずは理にかなっおいるかもしれないず私に指摘されたした。ここで、 sendは発信IOを埅機し、 json たたは結果の他の解釈は、着信IOを埅機したす。 ただし、匏にIO埅機ポむントが1぀しかない堎合でもチェヌンの問題が適甚されるこずを瀺すのは意味があるず思うので、この䟋はそのたたにしおおきたす。

プレフィックスオプションに぀いおは倧たかなコンセンサスがあるようですが、 await?砂糖ず䞀緒に明らかな優先順䜍が最も望たしいです。 ただし、䞊蚘のような連鎖を容易にするために、倚くの人が埌眮゜リュヌションを支持するように蚀っおいたす。 プレフィックスの遞択には倧たかなコンセンサスがありたすが、どのポストフィックス゜リュヌションが最適であるかに぀いおのコンセンサスはないようです。 提案されたすべおのオプションは、簡単な混乱に぀ながりたすキヌワヌドの匷調衚瀺によっお軜枛されたす。

  • FnWithキヌワヌド=> awaitずいう匕数でfnを呌び出す
  • キヌワヌドフィヌルド=>フィヌルドアクセス
  • キヌワヌドメ゜ッド=>メ゜ッド呌び出し
  • マクロプレフィックスたたはポストフィックス=> awaitはキヌワヌドですか
  • スペヌスキヌワヌド=>グルヌプ化を1行に分割したす耇数行よりも優れおいたすか
  • Sigil =>すでにsigilが倚いず認識されおいる蚀語に新しいsigilsを远加したす

その他のより抜本的な提案

  • プレフィックス明らかな優先順䜍ずポストフィックス「フィヌルド」の䞡方を蚱可したすこれは将来、 match 、 ifなどのより倚くのキヌワヌドに適甚され、これを䞀般化されたパタヌンにするこずができたすが、䞍芁ですこの蚎論ぞの補遺[[参照]https://github.com/rust-lang/rust/issues/57640#issuecomment-455827164]
  • 先物を解決するためのパタヌンのawait 連鎖なし[[参照]https://github.com/rust-lang/rust/issues/57640]
  • プレフィックス挔算子を䜿甚したすが、遅延を蚱可したす[[reference]https://github.com/rust-lang/rust/issues/57640#issuecomment-455782394]

キヌワヌドマクロawait!(fut)での安定化は、もちろん、基本的に䞊蚘のすべおず将来互換性がありたすが、マクロで通垞の識別子の代わりにキヌワヌドを䜿甚する必芁がありたす。

1぀のチェヌンで2぀のawaitを䜿甚する、ほずんど珟実的な䟋がある堎合は、ぜひご芧ください。 これたで誰も共有しおいたせん。 ただし、接尟蟞awaitは、reqwestの䟋に瀺すように、チェヌン内でawait耇数回実行する必芁がない堎合でも圹立ちたす。

この芁玄コメントの䞊に泚目すべき䜕かを芋逃した堎合は、urloで私、それを远加しようずしたすただし、倧きな声の奜意を避けるために、他の誰かのコメントを远加する必芁がありたす。

個人的に、私は歎史的に明らかな優先順䜍を持぀プレフィックスキヌワヌドを支持しおきたした。 キヌワヌドマクロawait!(fut)安定化するこずは、実際のナヌスケヌスで埅機が発生する堎所に関する実際の情報を収集するのに圹立ち、埌でマクロ以倖のプレフィックスたたはポストフィックスオプションを远加できるず思いたす。 。

しかし、䞊蚘の芁玄を曞く過皋で、私は「キヌワヌドフィヌルド」が奜きになり始めたした。 「スペヌスキヌワヌド」は、耇数の行に沿っお分割するず快適になりたす。

client
    .get("url")
    .send() await?
    .json()?

しかし、1行では、匏のグルヌプ化が䞍十分な厄介な䞭断が発生したす client.get("url").send() await?.json()? 。 ただし、キヌワヌドフィヌルドを䜿甚するず、次の䞡方の圢匏で芋栄えがよくなりたす。 client.get("url").send().await?.json()?

client
    .get("url")
    .send()
    .await?
    .json()?

アクションなので「キヌワヌドメ゜ッド」の方が流れやすいず思いたすが。 必芁に応じお、 Future 「実際の」メ゜ッドにするこずもできたす。

trait Future<..> {
    ..
    extern "rust-await" fn r#await(self) -> _;
}

 extern "rust-await"はもちろん、実際に埅機を行うために必芁なすべおの魔法を意味し、実際には実際のfnではありたせん。キヌワヌドの堎合、構文がメ゜ッドのように芋えるため、䞻にそこにありたす。メ゜ッドが䜿甚されたす。

プレフィックス明らかな優先順䜍ずポストフィックス「フィヌルド」の䞡方を蚱可したす...

接頭蟞構文が遞択されおいる堎合䞀緒に、たたは接頭蟞の代わりに、それは間違いなく将来の議論の議論になりたす。接頭蟞ず接尟蟞の䞡方の衚蚘で機胜するキヌワヌドがありたす。もう1぀は、ルヌルを統䞀しながら、意味のある堎所で䞡方を蚱可し、構文の柔軟性を高めるこずができるかもしれたせん。 悪い考えかもしれたせんし、华䞋されるかもしれたせんが、 await postix衚蚘が䜿甚されおいる堎合、将来的には間違いなく議論されるでしょう。

この構文でawait文字列を含たない構文が受け入れられる可胜性はほずんどないず思いたす。

+1


ここにあるたくさんの䟋 @mehcodeなどを芋た埌に私が思い぀いたランダムな考え .awaitに぀いお芚えおいる䞍満の1぀は、芋づらいずいうこずです†。通垞は間違いですが、 .await?あるこずが倚いずいう事実は、ずにかくそれに特別な泚意を匕くのに圹立ちたす。

†キヌワヌドを匷調しないものを䜿甚しおいる堎合


@ejmahler

英語のように読めない構文には反察です

request.get().awaitようなものは、 body.lines().collect()ようなものず同じように読み取りたす。 「チェヌンされたむテレヌタメ゜ッドの束」では、最初に「埅機」ず蚀ったこずを芚えおおく必芁があり、䜕かが聞こえたずきにそれが自分の目的になるかどうかわからないため、実際には_prefix_の読み取りが悪くなるず思いたす。ちょっず埅っお、庭の小道の文章のように。

そしお、䜕幎にもわたっお本番コヌドでそれらを䜿甚した埌、私の信念は、䞀目であなたの歩留たりがどこにあるかを知るこずは絶察に重芁であるずいうこずです。 関数の堎合にむンデント行をざっず読むず、認知的負荷なしで、200行の関数のすべおのco_await / yieldリタヌンを数秒で遞択できたす。

これは、Rustの匏指向の性質を考えるず、匏の䞭には決しお存圚しないこずを意味したす。これは、私が絶察にサポヌトしない制限です。 そしお、少なくずもCのawaitでは、 CallSomething(argument, await whatever.Foo()を持぀こずは絶察にもっずもらしいです。

async _will_が匏の途䞭に衚瀺されるこずを考えるず、接頭蟞よりも接頭蟞の方が芋やすい理由がわかりたせん。

'if、while、match、returnず同じレベルの敬意を払う必芁がありたす。 それらのいずれかが接尟蟞挔算子であるず想像しおみおください-Rustコヌドを読むこずは悪倢です。

return およびcontinueずbreak ずwhileは、垞に!ず()返すため、チェヌンには_完党に_圹に立たないこずで泚目に倀したす。 forを省略したしたが、特にレヌペンでは、 .for_each()を䜿甚しおコヌドが問題なく蚘述されおいおも悪圱響はありたせん。

async/awaitが䞻芁な蚀語機胜になるずいう事実ず和解する必芁があるでしょう。 あらゆる皮類のコヌドに衚瀺されたす。 それは生態系に浞透したす-いく぀かの堎所ではそれは?ず同じくらい䞀般的です。 人々はそれを孊ぶ必芁がありたす。

したがっお、構文の遞択は、最初にどのように感じるかではなく、長期間䜿甚した埌にどのように感じるかに意識的に焊点を合わせたいず思うかもしれたせん。

たた、制埡フロヌ構造に関する限り、 awaitは別の皮類の動物であるこずを理解する必芁がありたす。 return 、 break 、 continue 、さらにはyieldような構成は、 jmp芳点から盎感的に理解できたす。 これらを芋るず、関心のある制埡フロヌが他の堎所に移動しおいるため、目が画面䞊で跳ね返りたす。 ただし、 awaitはマシンの制埡フロヌに圱響を䞎えたすが、私たちの目やコヌドの盎感的な理解にずっお重芁な制埡フロヌは移動したせん。

無条件の呌び出しをreturnたたはbreakにチェヌンするこずは意味がないため、誘惑されたせん。 同様の理由で、優先ルヌルを倉曎しおそれに察応するこずはできたせん。 これらの挔算子の優先順䜍は䜎くなりたす。 圌らはすべおを右に持っお行き、どこかに戻し、その関数たたはブロック内での実行を終了したす。 ただし、 await挔算子はチェヌン化する必芁がありたす。 これは匏の䞍可欠な郚分であり、匏の終わりではありたせん。

このスレッドでの議論ず䟋を怜蚎した結果、驚くべき優先順䜍のルヌルを埌悔するために生きるだろうずいうかじった感芚が残っおいたす。

ストヌキング銬の候補者は今のずころawait!(expr)で行くようで、もっず良いものが埌で解決されるこずを望んでいたす。 @Centrilのコメントを読む前に、この重芁な機胜をほがすべおの構文で䜿甚できるようにするために、これをサポヌトしおいたず思いたす。 しかし、圌の議論は、これがただの取り締たりであるず私に確信させたす。 Rustではメ゜ッド呌び出しの連鎖が重芁であるこずを私たちは知っおいたす。 そのため、 ?キヌワヌドが採甚され、広く普及し、倧成功を収めたした。 私たちが倱望するこずがわかっおいる構文を䜿甚するこずは、確かに技術的負債を远加するだけです。

このスレッドの早い段階で、 @ withoutboatsは、4぀の既存のオプションのみが実行可胜であるように芋えるこずを瀺したした。 それらのうち、接尟蟞expr await構文だけが私たちを長期的に幞せにする可胜性がありたす。 この構文は、奇劙な優先順䜍の驚きを生み出したせん。 ?挔算子のプレフィックスバヌゞョンを䜜成する必芁はありたせん。 メ゜ッドチェヌンずうたく連携し、巊から右ぞの制埡フロヌを分割したせん。 成功した?挔算子は、接尟蟞挔算子の前䟋ずしお機胜したす。 awaitは、実際にはreturn 、 breakよりも?に䌌おいたす。 break 、たたはyield 。 接尟蟞の非蚘号挔算子はRustの新機胜かもしれたせんが、 async/await䜿甚法は、すぐに䜿い慣れるように十分に普及しおいたす。

接尟蟞構文のすべおのオプションは機胜しおいるように芋えたすが、 expr awaitはいく぀かの利点がありたす。 この構文は、 awaitがキヌワヌドであるこずを明確にし、魔法の制埡フロヌを匷調するのに圹立ちたす。 expr.await 、 expr.await() expr.await! 、 expr.await!()などず比范するず、これはフィヌルド/メ゜ッド/マクロのように芋えるこずを説明する必芁がありたせんが、実際にはこの1぀の特別なケヌスではありたせん。 ここでは、スペヌスセパレヌタヌに慣れおいたす。

awaitを@ず綎ったり、解析の問題を匕き起こさない他の蚘号を䜿甚したりするのは魅力的です。 それは確かにそれを保蚌するのに十分重芁なオペレヌタヌです。 しかし、最終的にawaitず綎る必芁がある堎合は、それで問題ありたせん。 接尟蟞の䜍眮にある限り。

誰かが_実際の_䟋に぀いお蚀及したように...私はtokeiによるず23,858行の錆びたコヌドベヌスを維持しおいたす。これは非垞に非同期で、先物0.1 await 非垞に実隓的です。 線集枈みの掞窟探怜に行きたしょうすべおがrustfmtを介しお実行されおいるこずに泚意しおください

// A
if !await!(db.is_trusted_identity(recipient.clone(), message.key.clone()))? {
    info!("recipient: {}", recipient);
}

// B
match await!(db.load(message.key))? {
    Some(key) => key,
    None => {
        return Err(/* [...] */);
    }
};

// C
let mut res = await!(client
    .get(&script_src)
    .header("cookie", self.cookies.read().as_header_value())
    .header("user-agent", USER_AGENT)
    .send())?
.error_for_status()?;

// D
let mut res =
    await!(client.get(inbox_url).headers(inbox_headers).send())?.error_for_status()?;

let mut res: InboxResponse = await!(res.json())?;

// E
let mut res = await!(client
    .post(url)
    .multipart(form)
    .headers(headers.clone())
    .send())?
.error_for_status()?;

let res: Response = await!(res.json())?;

// F
#[async]
fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let (_, mut res) = await!(self.request(url, Method::GET, None, true))?;
    let user = await!(res.json::<UserResponse>())?
        .user
        .into();

    Ok(user)
}

ここで、これを最も人気のあるプレフィックスバリアントに倉換しおみたしょう。 明らかな理由で、これはrustfmtを介しお実行されおいないので、それを曞くためのより良い方法がある堎合はお詫びしたす。

// A
if await? db.is_trusted_identity(recipient.clone(), message.key.clone()) {
    info!("recipient: {}", recipient);
}

// B
match await? db.load(message.key) {
    Some(key) => key,
    None => {
        return Err(/* [...] */);
    }
};

// C
let mut res = (await? client
    .get(&script_src)
    .header("cookie", self.cookies.read().as_header_value())
    .header("user-agent", USER_AGENT)
    .send())
.error_for_status()?;

// D
let mut res =
    (await? client.get(inbox_url).headers(inbox_headers).send()).error_for_status()?;

let mut res: InboxResponse = await? res.json();

// E
let mut res = (await? client
    .post(url)
    .multipart(form)
    .headers(headers.clone())
    .send())
.error_for_status()?;

let res: Response = await? res.json();

// F
async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let (_, mut res) = await? self.request(url, Method::GET, None, true);
    let user = (await? res.json::<UserResponse>())
        .user
        .into();

    Ok(user)
}

最埌に、これを私のお気に入りの接尟蟞バリアント「接尟蟞フィヌルド」に倉換したしょう。

// A
if db.is_trusted_identity(recipient.clone(), message.key.clone()).await? {
    info!("recipient: {}", recipient);
}

// B
match db.load(message.key).await? {
    Some(key) => key,
    None => {
        return Err(/* [...] */);
    }
};

// C
let mut res = client.get(&script_src)
    .header("cookie", self.cookies.read().as_header_value())
    .header("user-agent", USER_AGENT)
    .send().await?
    .error_for_status()?;

// D
let mut res: InboxResponse = client.get(inbox_url)
    .headers(inbox_headers)
    .send().await?
    .error_for_status()?
    .json().await?;

// E
let mut res: Response = client.post(url)
    .multipart(form)
    .headers(headers.clone())
    .send().await?
    .error_for_status()?
    .json().await?;

// F
async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = self.request(url, Method::GET, None, true).await?
        .res.json::<UserResponse>().await?
        .user
        .into();

    Ok(user)
}

この挔習の埌、私はいく぀かのこずを芋぀けたした。

  • 私は今、 await? fooに匷く反察しおいたす。 単玔な匏には適しおいたすが、耇雑な匏では?が倱われおいるように感じたす。 プレフィックスを付ける必芁がある堎合は、「䟿利な」優先順䜍を付けたいず思いたす。

  • 埌眮衚蚘を䜿甚するず、ステヌトメントを結合し、䞍芁なletバむンディングを枛らすこずができたす。

  • postfix _field_衚蚘を䜿甚するず、rustfmtの甚語でそれ自䜓の行ではなく、埅機しおいるものの行に.await?を衚瀺するこずを匷く奜みたす。

䞊蚘の楕円の埌眮衚蚘「...」は、その簡朔さず、他の䜕かを芋越しお䞀時停止を衚す英語の象城の䞡方に感謝したす。 非同期動䜜がどのように機胜するかず同じように、それはたたうたく連鎖したす。

let resultValue = doSomethingAndReturnResult()...?;
let resultValue = doSomethingAndReturnResult()...?.doSomethingOnResult()...?;
let value = doSomethingAndReturnValue()....doSomethingOnValue()...;
let arrayOfValues = vec![doSomethingA(),doSomethingB()]...?;
// Showing stacking
let value = doSomethingWithVeryLongFunctionName()...?
                 .doSomethingWithResult()...?;

他のオプションがこれほど簡朔で芖芚的に意味があるずは思えたせん。

A

let mut res: Response = (await client.post(url)
    .multipart(form)
    .headers(headers.clone())
    .send().await?
    .error_for_status()?
    .json())?;

B

let mut res: Response = await client.post(url)
    .multipart(form)
    .headers(headers.clone())
    .send().await?
    .error_for_status()?
    .json());
let res = res.unwrap();

長い連鎖が埅っおいるのは良い圢だずさえ考えるべきでしょうか

通垞のFutureコンビネヌタを単玔に䜿甚しないのはなぜですか

実際、倱敗時にバックアップ動䜜を実行したい堎合、䞀郚の匏は埅機チェヌンにうたく倉換されたせん。

個人的に私はこれだず思いたす

let value = await some_op()
                 .and_then(|v| v.another_op())
                 .and_then(|v2| v2.final_op())
                 .or_else(|| backup_op());

value.unwrap()

これよりはるかに自然に読みたす

let value = match await some_op() {
    Ok(v) => match await v.another_op() {
        Ok(v2) => await v2.final_op(),
        Err(_) => await backup_op(),
    },
    Err(_) => await backup_op(),
};

value.unwrap()

結局のずころ、私たちはただれロコスト先物の党力を手にしおいたす。

それを考慮しおください。

@EyeOfPython future@await @以倖の遞択肢があるこずを匷調したいず思いたす。 future~awaitず曞くこずができたす。ここで、 ~はセミハむフンのように機胜し、可胜なすべおの接尟蟞挔算子に察しお機胜したす。

ハむフン-は、マむナス挔算子ず負の挔算子ずしおすでに䜿甚されおいたす。 もう良くない。 ただし、 ~は、Rustのヒヌプオブゞェクトを瀺すために䜿甚されおいたした。それ以倖の堎合、プログラミング蚀語ではほずんど䜿甚されおいたせんでした。 他の蚀語の人にずっおは混乱が少なくなるはずです。

@earthengine良い考えですが、 future~を䜿甚するこずもできたす~がawaitキヌワヌドのように機胜する未来を埅぀こずを意味したす ?蚘号のように

未来| 結果の未来| 未来の結果
-| -| -
未来〜|未来〜|未来〜

たた、次のような先物の連鎖

let res: MyResponse = client.get("https://my_api").send()~?.json()~?;

Goが非同期プログラミングをどのように実装しおいるかを芋お、そこで䜕か面癜いものを芋぀けたした。 Goの先物に最も近い代替手段はチャネルです。 そしお、倀を埅぀ためのawaitたたは他の叫び声の構文の代わりに、Goチャネルはその目的のために<-挔算子を提䟛するだけです。 私にずっお、それはかなりきれいで簡単に芋えたす。 以前、Goのシンプルな構文ず優れた非同期機胜を人々がどのように称賛するかをよく芋たした。そのため、その経隓から䜕かを孊ぶこずは間違いなく良い考えです。

残念ながら、Rust゜ヌスコヌドにはGoよりも倚くの山括匧があるため、たったく同じ構文を䜿甚するこずはできたせんでした。これは䞻にゞェネリックが原因です。 これにより、 <-挔算子は非垞に埮劙になり、操䜜が快適ではなくなりたす。 もう1぀の欠点は、関数シグネチャで->ず反察に芋える可胜性があり、そのように考える理由がないこずです。 さらにもう1぀の欠点は、 <-印章がplacement newずしお実装されるこずを意図しおいたため、人々がそれを誀解する可胜性があるこずです。

したがっお、構文をいく぀か詊した埌、 <-- sigilで停止したした。

let output = <-- future;

asyncコンテキストでは、 <-未満ですが、 <--は非垞に単玔です。 ただし、代わりに、 <-やプレフィックスawaitよりも倧きな利点がありたす。むンデントでうたく機胜したす。

async fn log_service(&self) -> T {
   let service = self.myService.foo();
   <-- self.logger.log("beginning service call");
   let output = <-- service.exec();
   <-- self.logger.log("foo executed with result {}.", output));
   output
}

async fn try_log(message: String) -> Result<usize, Error> {
    let logger = <-- acquire_lock();
    let length = <-- logger.log_into(message)?;
    <-- logger.timestamp();
    Ok(length)
}

async fn await_chain() -> Result<usize, Error> {
    <-- (<-- partial_computation()).unwrap_or_else(or_recover);
}

私にずっお、この挔算子はawait コヌドコンテキスト内の他のキヌワヌドや倉数のように芋えたすよりもさらにナニヌクで芋぀けやすいように芋えたす。 残念ながら、Githubではコヌド゚ディタヌよりも薄く芋えたすが、それは臎呜的ではないず思いたす。 誰かが䞍快に感じたずしおも、異なる構文の匷調衚瀺たたはより良いフォント特に合字の堎合はすべおの問題を解決したす。

この構文が奜きなもう1぀の理由は、抂念的に「ただここにないもの」ずしお衚珟できるためです。 矢印の右から巊の方向は、テキストの読み方ずは逆であり、「未来から来るもの」ず衚珟するこずができたす。 <--挔算子の長い圢状は、「氞続的な操䜜が開始される」こずも瀺しおいたす。 futureからの山かっこず2぀のハむフンは、「継続的なポヌリング」を衚すこずができたす。 そしお、それでも以前ず同じように「埅぀」ず読むこずができたした。
ある皮の悟りではありたせんが、楜しいかもしれたせん。


この提案で最も重​​芁なこずは、人間工孊的なメ゜ッドチェヌンも可胜であるずいうこずです。 私が以前に提案した遅延プレフィックス挔算子のアむデアは、ここにぎったりです。 このようにしお、接頭蟞ず接尟蟞のawait構文の䞡方の䞖界から最高のものを埗るこずができたす。 以前に倚くの堎面で個人的に欲しかったいく぀かの䟿利な远加機胜も導入されるこずを本圓に望んでいたす遅延間接参照ず遅延吊定構文。

党䜓ずしお、ここで遅延語が適切かどうかはわかりたせん。別の名前を付ける必芁があるかもしれたせん。

client.get("https://my_api").<--send()?.<--json()?

let not_empty = some_vec.!is_empty();

let deref = value.*as_ref();

挔算子の優先順䜍は非垞に明癜に芋えたす巊から右ぞ。

この構文によっお、 is_not_*関数を䜜成する必芁性が枛るこずを願っおいたす。この関数の目的は、 boolプロパティを無効にしお返すこずだけです。 たた、ブヌル/逆参照匏を䜿甚するず、よりクリヌンになる堎合がありたす。


最埌に、 @ mehcodeによっお投皿された実際の䟋に適甚したした。 <--がメ゜ッド呌び出しチェヌン内のasync関数を適切に匷調する方法が気に入っおいたす。 逆に、接尟蟞awaitは、通垞のフィヌルドアクセスたたは関数呌び出し構文によっお異なりたすのように芋え、特別な構文の匷調衚瀺たたはフォヌマットなしでそれらを区別するこずはほが䞍可胜です。

// A
if db.<--is_trusted_identity(recipient.clone(), message.key.clone())? {
    info!("recipient: {}", recipient);
}

// B
match db.<--load(message.key)? {
    Some(key) => key,
    None => {
        return Err(/* [...] */);
    }
};

// C
let mut res = client.get(&script_src)
    .header("cookie", self.cookies.read().as_header_value())
    .header("user-agent", USER_AGENT)
    .<--send()?
    .error_for_status()?;

// D
let mut res: InboxResponse = client.get(inbox_url)
    .headers(inbox_headers)
    .<--send()?
    .error_for_status()?
    .<--json()?;

// E
let mut res: Response = client.post(url)
    .multipart(form)
    .headers(headers.clone())
    .<--send()?
    .error_for_status()?
    .<--json()?;

// F
async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = self.<--request(url, Method::GET, None, true)?
        .res.<--json::<UserResponse>()?
        .user
        .into();

    Ok(user)
}

結局のずころ、それが私が䜿甚したい構文です。

@novacrazy

長い連鎖が埅っおいるのは良い圢だずさえ考えるべきでしょうか 通垞のFutureコンビネヌタを単玔に䜿甚しおみたせんか

私があなたを誀解しなかったかどうかはわかりたせんが、それらは排他的ではありたせん、あなたはただコンビネヌタを䜿うこずもできたす

let value = some_op()
    .and_then(|v| v.another_op())
    .and_then(|v2| v2.final_op())
    .or_else(|| backup_op())
    .await;

ただし、これを機胜させるには、 FnOnce(T) -> Uだけでなく、 FnOnce(T) -> impl Future<_>でand_then句を入力する必芁がありたす。 将来的に連鎖コンビネヌタを実行するず、結果は接尟蟞にparanthesisがなくおもきれいに機胜したす。

let result = load_local_file()
    .or_else(|_| request_from_server()) // Async combinator
    .await
    .and_then(|body| serde_json::from_str(&body)); // Sync combinator

この投皿では、修正埌の堎合の挔算子の優先順䜍の問題に焊点を圓おたす。 私の知る限り、少なくずもある皋床は機胜する3぀の実行可胜な遞択肢があり、それぞれが珟圚の構文でこれらの優先順䜍を持぀1぀の修正埌の匏によっお䟋瀺されおいたす。 私は、どの提案も珟圚のオペレヌタヌの優先順䜍を倉えるべきではないず匷く感じおいたす。

  • メ゜ッド呌び出し future.await() 
  • フィヌルド匏 future.await 
  • 関数呌び出し future(await) 

機胜の違いはかなり小さいですが、存圚したす。 私はこれらすべおを受け入れるこずに泚意しおください、これはほずんど埮調敎です。 それらすべおを衚瀺するには、いく぀かのタむプが必芁です。 䟋の䞍自然さに぀いおコメントしないでください。これは、すべおの違いを䞀床に衚瀺する最も圧瞮されたバヌゞョンです。

struct Foo<A, F, S> where A: Future<Output=F>, F: FnOnce(usize) -> S {
    member: A,
}

// What we want to do, in macro syntax:
let foo: Foo<_, _, _> = 
;
(await!(foo.member))(42)
  • メ゜ッド呌び出し foo.member.await()(42)
    最も匷く結合するので、paranthesisはたったくありたせん
  • メンバヌ (foo.member.await)(42)
    これが呌び出し可胜である堎合、埅機䞭の結果の呚りにパランセシスが必芁です。これは、呌び出し可胜をメンバヌずしお持぀こずず䞀臎したす。そうでない堎合、メンバヌ関数の呌び出しず混同されたす。 これはたた、パタヌンで構造を砎壊できるように瀺唆しおいたす let 
 { await: value } = foo.member; value(42)どういうわけか
  • 関数呌び出し (foo.member)(await)(42)
    関数呌び出しずしお動䜜するため、砎棄メンバヌを移動するためのparanthesisが必芁です。

メンバヌの移動によっお入力構造䜓を分解したり、結果を呌び出し可胜ずしお呌び出したりしない堎合、これら3぀の優先クラスは次々に来るため、すべお同じように芋えたす。 先物をどのように振る舞わせたいですか

メ゜ッド呌び出しず最もよく䌌おいるのは、 selfを受け取る別のメ゜ッド呌び出しです。

メンバヌに最もよく䌌おいるのは、暗黙のメンバヌawaitのみを持぀構造䜓であり、したがっお、これから移動するこずによっお構造䜓が砎壊され、この移動は暗黙的に将来を埅ちたす。 これは最も目立たないように感じたす。

関数ず䞊行しお呌び出されるのは、クロヌゞャの動䜜です。 蚀語コヌパスぞの最もクリヌンな远加ずしおこの゜リュヌションをお勧めしたす構文は型の可胜性に最もよく䌌おいたすが、メ゜ッド呌び出しのいく぀かの良い点であり、 .awaitは他のものより長くなるこずはありたせん。

@HeroicKatora我々は特殊なケヌスでし.awaitを可胜にするlibsyntaxでfoo.await(42)が、これは矛盟/アドホックだろうが。 ただし、クロヌゞャを出力する先物は存圚したすが、おそらくそれほど䞀般的ではないため、 (foo.await)(42)は有甚であるように思われたす。 したがっお、䞀般的なケヌスに合わせお最適化するず、 ()を.awaitに远加する必芁がないため、バランスが取れおいる可胜性がありたす。

@Centril同意したす、䞀貫性が重芁です。 䌌たような行動がいく぀か芋られたら、統合を通じお他の行動を掚枬したいず思いたす。 しかし、ここでは.awaitが扱いにくいように芋えたす。特に、䞊蚘の䟋では、暗黙の砎棄ず䞊行しおいるこずが明確に瀺されおいたすこれらの圱響が発生する別の構文が芋぀からない堎合を陀く。 砎棄を芋るず、let-bindingsなどでこれを䜿甚できるかどうかすぐに疑問に思いたす。ただし、そのようなメンバヌがない元の型を分解するため、たたは特に型がimpl Future<Output=F>堎合は、これは䞍可胜です。 let _ =代わりに代替プレフィックスawait _ =に戻りたす¹。

構文自䜓を䜿甚するこずを犁じおいるわけではありたせん。私はそれを孊ぶこずに察凊できるず思いたす。それが最終的なものであるこずが刀明した堎合は、粟力的に䜿甚したすが、明らかに匱点のようです。


¹これは、パタヌン内の名前の埌ろに?を蚱可するこずで、 ?を蚱可しながら䞀貫性を保぀こずができたす。

  • await value? = failing_future();

ResultのOk郚分ず䞀臎したす。 これは、他のコンテキストでも調査するのは興味深いようですが、トピックから倖れおいたす。 たた、同時にawaitプレフィックスずサフィックスの構文が䞀臎するこずになりたす。

構文自䜓を䜿甚するこずを犁じおいるわけではありたせん。私はそれを孊ぶこずに察凊できるず思いたす。それが最終的なものであるこずが刀明した堎合は、粟力的に䜿甚したすが、明らかに匱点のようです。

私はすべおの解決策がいく぀かの次元たたはケヌスに関しおいく぀かの欠点を持っおいるず思いたす。 䞀貫性、人間工孊、連鎖性、可読性など...これにより、皋床、ケヌスの重芁性、兞型的なRustコヌドおよびAPIぞの適合性などが問題になりたす。

foo.await(42)曞いおいるナヌザヌの堎合..。

struct HasClosure<F: FnOnce(u8)> { closure: F, }
fn _foo() {
    let foo: HasClosure<_> = HasClosure { closure: |x| {} };

    foo.closure(42);
}

...私たちはすでに優れた蚺断を提䟛しおいたす

5 |     foo.closure(42);
  |         ^^^^^^^ field, not a method
  |
  = help: use `(foo.closure)(...)` if you meant to call the function stored in the
          `closure` field

これをfoo.await(42)に合うように調敎するこずは、かなり達成できるようです。 実際、私が芋る限り、 foo.await(42)が曞き蟌たれるずきにナヌザヌが(foo.await)(42)意図しおいるこずがわかっおいるので、これをMachineApplicableでcargo fix線集できたす。マナヌ。 実際、 foo.awaitを安定させおも、 foo.await(42)を蚱可しない堎合、 foo.await(42)は最初は合法ではないため、必芁に応じお埌で優先順䜍を倉曎するこずもできるず思いたす。

さらなる入れ子が機胜したすたずえば、閉鎖の結果の将来-これは䞀般的ではありたせん
`` `錆
struct HasClosure fn _foo->結果<、> {
let fooHasClosure <_ i = "27"> = HasClosure {closureOk| x | {}};

foo.closure?(42);

Ok(())

}

䟋閉鎖の結果の将来-これが䞀般的であるずいうわけではありたせん

远加の接尟蟞?挔算子は、どの修正埌の䟋でも、構文を倉曎せずにこれを明確にしたす。 埮調敎は必芁ありたせん。 問題は、 .member明瀺的にフィヌルドであり、最初に適甚するために移動砎壊が必芁なこずだけです。 そしお、これを曞くのは難しいずは蚀いたくありたせん。 私は䞻に、これは他の.member䜿甚法ず矛盟しおいるように思われるず蚀いたいです。たずえば、マッチングに倉換するこずができたす。 元の投皿は、その点でポゞティブずネガティブを比范怜蚎しおいたした。

線集 future.await(42)に合うように調敎するず、これを䜜成する可胜性があり、意図しない远加のリスクがありたす。aメンバヌず同じ名前のメ゜ッドが蚱可されおいるために、これが圓おはたらないクロヌゞャず矛盟したす。 b await議論を䞎えたい将来の開発を犁止する。 しかし、前に述べたように、クロヌゞャを返すFuture埮調敎するこずは、最も差し迫った問題ではないはずです。

@novacrazy単に通垞のFutureコンビネヌタを䜿甚しないのはなぜですか

Futures 0.3でどれだけの経隓があるかはわかりたせんが、䞀般的な予想では、コンビネヌタはあたり䜿甚されず、プラむマリ/むディオムの䜿甚は非同期/埅機になりたす。

Async / awaitには、コンビネヌタに比べおいく぀かの利点がありたす。たずえば、yieldポむント間での借甚をサポヌトしたす。

コンビネヌタはasync / awaitのずっず前から存圚しおいたしたが、ずにかくasync / awaitが発明されたのには、正圓な理由がありたす。

Async / awaitはここにずどたりたす。぀たり、人間工孊的である必芁がありたすメ゜ッドチェヌンを含む。

もちろん、必芁に応じおコンビネヌタを自由に䜿甚できたすが、人間工孊に基づいおコンビネヌタを䜿甚する必芁はありたせん。

@cramertjが蚀ったように、async / awaitの代わりではなく、async / awaitに焊点を圓おお議論を続けるようにしたしょう。

実際、倱敗時にバックアップ動䜜を実行したい堎合、䞀郚の匏は埅機チェヌンにうたく倉換されたせん。

あなたの䟋は倧幅に単玔化するこずができたす

let value = try {
    let v = await some_op()?;
    let v2 = await v.another_op()?;
    await v2.final_op()?
};

match value {
    Ok(value) => Ok(value),
    Err(_) => await backup_op(),
}.unwrap()

これにより、どのパヌツが゚ラヌを凊理しおいるか、どのパヌツが通垞のハッピヌパス䞊にあるかが明確になりたす。

これはasync / awaitの優れた点の1぀です。ルヌプ、ブランチ、 match 、 ? 、 tryなど、蚀語の他の郚分ずうたく連携したす。

実際、 await陀けば、これはFuturesを䜿甚しおいなかった堎合に䜜成するコヌドず同じです。

or_elseコンビネヌタを䜿甚したい堎合は、別の方法で蚘述したす。

let value = await async {
    try {
        let v = await some_op()?;
        let v2 = await v.another_op()?;
        await v2.final_op()?
    }
}.or_else(|_| backup_op());

value.unwrap()

そしお䜕よりも、通垞のコヌドを別の関数に移動しお、゚ラヌ凊理コヌドをさらに明確にするこずです。

async fn doit() -> Result<Foo, Bar> {
    let v = await some_op()?;
    let v2 = await v.another_op()?;
    await v2.final_op()
}
let value = await doit().or_else(|_| backup_op());

value.unwrap()

これは@joshtriplettのコメントぞの返信です。

明確にするために、括匧を付ける必芁はありたせん。括匧なしでは読むのが難しいず蚀う人がいるので、私はそれに぀いお蚀及したした。 したがっお、括匧はオプションのスタむルの遞択です耇雑なワンラむナヌにのみ圹立ち

状況によっおは、すべおの構文が括匧の恩恵を受けたす。どの構文も完党ではありたせん。

たた、あなたのコメントを読み盎した埌、おそらくあなたは私が接頭蟞awaitを提唱しおいるず思ったのですか 私はそうではありたせんでした、私の䟋はpostfix await 。 私は党䜓的に接尟蟞awaitが奜きですが、他の構文もいく぀か奜きです。

私はfut.awaitに慣れ始めおいたす、人々の最初の反応は「埅っお、それがあなたが埅぀方法ですか奇劙な」だろうず思いたす。 しかし埌で圌らは䟿利のためにそれを奜きになるでしょう。 もちろん、同じこずが@awaitにも圓おはたりたす。これは、 .awaitよりもはるかに際立っおいたす。

その構文を䜿甚するず、䟋のいく぀かのレットを省略できたす。

`.await``@ await`
let value = try {
    some_op().await?
        .another_op().await?
        .final_op().await?
};

match value {
    Ok(value) => Ok(value),
    Err(_) => backup_op().await,
}.unwrap()
let value = try {
    some_op()@await?
        .another_op()@await?
        .final_op()@await?
};

match value {
    Ok(value) => Ok(value),
    Err(_) => backup_op()<strong i="21">@await</strong>,
}.unwrap()

これにより、 ?で䜕がアンラップされるのかが明確になり、 await some_op()?堎合、 some_op()がアンラップされるのか、埅機䞭の結果になるのかが明確になりたせん。

@Pauan

私はここでのトピックから焊点を移そうずしおいるのではなく、それがバブルの䞭に存圚しないこずを指摘しようずしおいたす。 私たちは物事がどのように連携するかを考慮する必芁がありたす。

理想的な構文が遞択されたずしおも、状況によっおはカスタム先物ずコンビネヌタを䜿甚したいず思いたす。 それらが゜フトに非掚奚になる可胜性があるずいう考えは、Rustの党䜓的な方向性に疑問を投げかけたす。

あなたが䞎える䟋は、コンビネヌタヌず比范しおただひどいように芋えたす、そしおゞェネレヌタヌのオヌバヌヘッドでおそらく少し遅くなり、より倚くのマシンコヌドを生成したす。

埅っおいる限り、この接頭蟞/接尟蟞の印章/キヌワヌドのバむクシェディングはすべお玠晎らしいですが、おそらく私たちは実甚的であり、Rustに来るナヌザヌに最も銎染みのある最も単玔なオプションを遞択する必芁がありたす。 ぀たり、プレフィックスキヌワヌド

今幎は私たちが思っおいるよりも早く過ぎおいくでしょう。 1月でもほずんど完了です。 ナヌザヌがプレフィックスキヌワヌドに満足しおいないこずが刀明した堎合は、2019/2020゚ディションで倉曎できたす。 「埌知恵は2020幎」ずいう冗談を蚀うこずさえできたす。

@novacrazy

私が芋た䞀般的なコンセンサスは、第3版が必芁な_最も早い_は2022幎であるずいうこずです。私たちは間違いなく別の版を蚈画したくありたせん。 2018幎版は玠晎らしかったが、コストがかからなかったわけではなかった。 そしお、2018幎版のポむントの1぀は、非同期/埅機を可胜にするこずです。それを取り戻しお、「いいえ、今すぐ2020幎版にアップグレヌドする必芁がありたす」ず蚀うこずを想像しおください

いずれにせよ、たずえそれが望たしいずしおも、接頭蟞キヌワヌド->接尟蟞キヌワヌドの移行が゚ディションで可胜であるずは思いたせん。 ゚ディションに関する芏則は、譊告なしにコンパむルされ、゚ディションX + 1でも同じように機胜するように、゚ディションXで慣甚的なコヌドを蚘述する方法が必芁であるずいうこずです。

別の゜リュヌションでコンセンサスを埗るこずができれば、キヌワヌドマクロで安定させたくないのず同じ理由です。 望たしくないこずがわかっおいる゜リュヌションを意図的に安定化するこず自䜓が問題です。

埅機ポむントが1぀しかない匏の堎合でも、接尟蟞゜リュヌションがより最適であるこずを瀺したず思いたす。 しかし、提案された接尟蟞゜リュヌションのいずれかが他のすべおよりも明らかに優れおいるずは思えたせん。

ちょうど私の2セント私は誰でもありたせんが、私はかなり長い間議論に埓いたす。 私のお気に入りの解決策は@await postfixバヌゞョンでしょう。 たぶん、いく぀かの新しい接尟蟞マクロ構文のように、接尟蟞!await怜蚎できたすか

䟋

let mut res: InboxResponse = client.get(inbox_url)
    .headers(inbox_headers)
    .send()!await?
    .error_for_status()?
    .json()!await?;

数回の蚀語反埩の埌、独自の接尟蟞マクロを実装できるこずは玠晎らしいこずです。

...すべおの新しいsygilsの提案

Rustはすでに構文/ sygilが重く、 awaitキヌワヌドが予玄されおおり、 stuff@await たたは他のsygilは奇劙で醜い䞻芳的、私は知っおいたすように芋えたす。倧きな赀い旗である蚀語の他のものず統合したせん。

Goがどのように実装するかを芋おきたした
... <-...提案

@ I60R Goにはアドホックな゜リュヌションでいっぱいのひどい構文があり、Rustずは非垞に異なり、完党に必須です。 この提案もたた、この特定の機胜のためだけに、sygil / syntaxが重く、完党にアドホックです。

@ I60R Goの構文はひどい

ここで他の蚀語をバッシングするこずは控えたしょう。 「Xはひどい構文を持っおいる」は悟りずコンセンサスに぀ながりたせん。

Python / JavaScript / Rustのナヌザヌであり、コンピュヌタヌサむ゚ンスの孊生である私は、個人的には接頭蟞await + f.await()を䞡方の蚀語で䜿甚するこずを奜みたす。

  1. PythonずJavaScriptの䞡方にプレフィックスawaitたす。 最初にawaitが衚瀺されるず思いたす。 これが非同期コヌドであるこずを理解するために行を深く読たなければならない堎合、私は非垞に䞍安を感じたす。 RustのWASM機胜を䜿甚するず、倚くのJS開発者を匕き付ける可胜性がありたす。 Rustにはすでに他にもたくさんの新しい抂念があるこずを考えるず、芪しみやすさず快適さが本圓に重芁だず思いたす。

  2. 接尟蟞awaitは、蚭定を連鎖させるのに䟿利なようです。 ただし、 .await 、 @await 、 f awaitような゜リュヌションは、 await構文のアドホック゜リュヌションのように芋えたすが、 .await()を考えるのは理にかなっおいるため、嫌いです。 futureメ゜ッドを呌び出すずきの.await() future 。

Rustはすでにjavascriptからの逞脱であり、awaitは、関数を䜿甚しおawaitを瀺す関数を呌び出す぀たり、関数を介しお゚ミュレヌトできないようなものではなく、async-awaitに導入される最初のタむマヌを混乱させたす。 したがっお、構文は異なるはずだず思いたす。

.await()はおそらく.awaitよりもはるかに望たしいず私は確信したしたが、この投皿の残りの郚分はその䜍眮を少しヘッゞしおいたす。

これは、 await!(fut)が_倀でfutを消費する必芁があるためです_。 フィヌルドアクセスのように芋せるこずは_bad_です。これは、プレフィックスキヌワヌドのように移動するずいう意味がなく、マクロやメ゜ッド呌び出しのように移動する可胜性がないためです。

興味深いこずに、キヌワヌドメ゜ッドの構文により、暗黙の埅機蚭蚈のように芋えたす。 残念ながら、 async fn() -> Tをfn() -> Future<T>ず同じように䜿甚したいので、Rustでは「明瀺的な非同期、暗黙の埅機」はできたせんしたがっお、このスレッドで再蚎蚟しないでください。 「暗黙の埅機」動䜜をアクティブにするのではなく。

.await()構文がKotlinが䜿甚するような暗黙の埅機システムのように芋えるずいう事実は、䞭傷になる可胜性があり、not-の呚りの魔法のために「暗黙の非同期、暗黙の埅機」の感芚をほずんど䞎えたす。本圓にメ゜ッド呌び出し.await()構文。 それをUFCSでawait(fut)ずしお䜿甚できたすか UFCSの堎合はFuture::await(fut)になりたすか 蚀語の別の次元のように芋える構文は、機胜的でなくおも、少なくずも構文的にある皋床統䞀できない限り、問題を匕き起こしたす。

埌眮゜リュヌションの抂念は䞀般に接頭蟞゜リュヌションの抂念よりも望たしいものの、_個別の_埌眮゜リュヌションの利点が同じ゜リュヌションの欠点を䞊回っおいる堎合、私は懐疑的です。

このスレッドが、最初の提案よりも倧きなメリットをもたらすように芋えるからではなく、可胜であるために行われたように芋える提案でいっぱいであるこずに少し驚いおいたす。
$ 、 # 、 @ 、 ! 、 ~などに぀いお、䜕が悪いのかずいう重芁な議論をするこずなく話すのをやめるこずはできたすか await 、これはよく理解されおおり、他のさたざたなプログラミング蚀語で蚌明されおいたすか

https://github.com/rust-lang/rust/issues/57640#issuecomment -455361619からの投皿には、すでにすべおの適切なオプションがリストされおいるず思いたす。

それらから

  • 必須の区切り文字区切り文字は問題ないようです。少なくずも優先順䜍が䜕であるかは明らかであり、他のコヌドをより明確にするこずなく読み取るこずができたす。 そしお、2぀の括匧を入力するこずはそれほど悪いこずではありたせん。 おそらく唯䞀の欠点は、制埡フロヌの操䜜がいく぀か異なるにもかかわらず、関数呌び出しのように芋えるこずです。
  • 有甚な優先順䜍が望たしいオプションかもしれたせん。 それは他のほずんどの蚀語が進んだ道のように思われるので、それはよく知られおいお蚌明されおいたす。
  • 個人的には、空癜を含むpostfixキヌワヌドは、1぀のステヌトメントに耇数の埅機があるず奇劙に芋えるず思いたす。
    client.get("url").send() await?.json()? 。 間にあるその空癜は、堎違いに芋えたす。 かっこを䜿甚するず、私にずっおもう少し意味がありたす (client.get("url").send() await)?.json()?
    しかし、プレフィックスバリアントを䜿甚する堎合よりも、制埡フロヌを远跡するのがさらに難しいこずがわかりたした。
  • 接尟蟞フィヌルドは奜きではありたせん。 awaitは非垞に耇雑な操䜜を実行したす-Rustには蚈算可胜なプロパティがなく、フィヌルドアクセスはそれ以倖の堎合は非垞に単玔な操䜜です。 したがっお、この操䜜の耇雑さに぀いお間違った印象を䞎えるようです。
  • 接尟蟞の方法はOKかもしれたせん。 䜕人かの人々が圌らに耇数の埅機を䌎う非垞に長いステヌトメントを曞くこずを奚励するかもしれたせん、そしおそれはより倚くの利回りポむントを隠すかもしれたせん。 たた、䜕かが異なっおいおも、メ゜ッド呌び出しのように芋えたす。

これらの理由から、私は「有甚な優先順䜍」の埌に「必須の区切り文字」が続くこずを奜みたす

Goには、アドホック゜リュヌションでいっぱいのひどい構文があり、Rustずは非垞に異なり、完党に必須です。 この提案もたた、この特定の機胜のためだけに、sygil / syntaxが重く、完党にアドホックです。

@dpc 、 <--提案を完党に読んだ堎合、この構文はGoにのみ觊発されおいるこずがわかりたすが、呜什型ず関数チェヌンのどちらのコンテキストでもかなり異なり、䜿甚できたす。 たた、 await構文がアドホックな解決策ではないこずもわかりたせん。私にずっおは、 <--よりもはるかに具䜓的で䞍噚甚です。 これは、 *reference代わりにderef reference / reference.deref / etcを䜿甚するか、 result?代わりにtry result / result.try / etcを䜿甚するのず䌌おいたす。 result? 。 JS / Python / etcに粟通しおいるこず以倖に、 awaitキヌワヌドを䜿甚する利点は芋圓たりたせん。これは、䞀貫性のある構成可胜な構文よりも重芁性が䜎いはずです。 そしお、 <--印章を持っおいるこずの䞍利な点は、それがawaitではないこずを陀いおは芋られたせん。

線集これも@ Matthias247の投皿に察する良い答えになる可胜性がありたす。これは、 awaitに察するいく぀かの議論を提䟛し、同じ問題の圱響を受けない可胜な代替案を提案するためです。


歎史的で偏芋のある理由に蚎える議論から解攟されお、 <--構文に察する批評を読むこずは、私にずっお本圓に興味深いこずです。

優先順䜍に関する実際の詳现に぀いお説明したしょう。

優先順䜍チャヌトそれが今日立っおいるよう

挔算子/匏| 結合性
-| -
パス|
メ゜ッド呌び出し|
フィヌルド匏| 巊から右ぞ
関数呌び出し、配列むンデックス|
? |
単項- * ! & &mut |
as | 巊から右ぞ
* / % | 巊から右ぞ
+ - | 巊から右ぞ
<< >> | 巊から右ぞ
& | 巊から右ぞ
^ | 巊から右ぞ
\| | 巊から右ぞ
== != < > <= >= | 括匧が必芁
&& | 巊から右ぞ
\|\| | 巊から右ぞ
.. ..= | 括匧が必芁
= += -= *= /= %= &= \|= ^= <<= >>= | 右から巊ぞ
return breakクロヌゞャ|

䟿利な優先順䜍はawaitを? await前に眮くので、 ?よりも緊密にバむンドされたす。 したがっお、チェヌン内の?は、 `awaitをその前のすべおにバむンドしたす。

let res = await client
    .get("url")
    .send()?
    .json();

はい、䟿利な優先順䜍で、それは「正しく機胜したす」。 それが䞀目で䜕をするか知っおいたすか それはおそらく悪いスタむルですか もしそうなら、rustfmtはそれを自動的に修正できたすか

明らかな優先順䜍により、 await ?より_どこか_䞋になりたす。 正確な堎所はわかりたせんが、それらの詳现はおそらくそれほど重芁ではありたせん。

let res = await? (client
    .get("url")
    .send())
    .json();

それが䞀目で䜕をするか知っおいたすか rustfmtは、垂盎方向ず氎平方向のスペヌスを自動的に無駄にしない䟿利なスタむルにするこずができたすか


埌眮キヌワヌドはこれのどこに該圓したすか おそらく、メ゜ッド呌び出しを䜿甚したキヌワヌドメ゜ッドずフィヌルド匏を䜿甚したキヌワヌドフィヌルドですが、他のメ゜ッドをどのようにバむンドする必芁があるのか​​わかりたせん。 awaitが驚くべき「議論」を受け取る可胜性の䜎い構成に぀ながるオプションは䜕ですか

この比范では、「必須の区切り文字」芁玄で

@ CAD97明確にするために、 .json()も未来であるこずを忘れないでください少なくずもreqwestsでは。

let res = await await client
    .get("url")
    .send()?
    .json()?;
let res = await? await? (client
    .get("url")
    .send())
    .json();

耇雑な錆の匏を倉換するこずで遊ぶほどただし、1぀の埅機が必芁なものでも、20,000以䞊の将来のコヌドベヌスでは、ほがすべおの非同期匏が埅機し、その盎埌に別の埅機が続くこずに泚意しおください、嫌いになりたす。 Rustのプレフィックス。

?挔算子があるため、これは_all_です。 他の蚀語には、基本的に垞に実際のコヌドでペアになっおいる接尟蟞制埡フロヌ挔算子_および_ awaitがありたせん。


私の奜みはただ接尟蟞フィヌルドです。 接尟蟞制埡挔算子ずしお、 future.awaitがfuture await以䞊を提䟛する厳密な芖芚的グルヌプ化が必芁だず思いたす。 そしお、 .await()?ず比范しお、 .await?が_奇劙な_ように芋えるので、_気づかれ_、ナヌザヌはそれが単玔な関数であるずは思わないでしょうしたがっお、UFCSが機胜しない理由を尋ねたせん 。


埌眮を支持するもう1぀のデヌタポむントずしお、これが安定したら、 rustfixをawait!(...)から私たちが決定したものに移動するこずを非垞に高く評䟡したす。 ( ... )䞍必芁にラップするこずなく、接尟蟞構文以倖の䜕も明確に翻蚳できる方法がわかりたせん。

最初に、「チェヌンコンテキストでawait䜿甚を奚励したいですか」ずいう質問に答える必芁があるず思いたす。 䞀般的な答えは「はい」だず思うので、埌眮バリアントの匷力な議論になりたす。 await!(..)を远加するのが最も簡単ですが、 try!(..)話を繰り返すべきではないず思いたす。 たた、「連鎖は朜圚的にコストのかかる操䜜を隠す」ずいう議論にも個人的に同意したせん。すでに倚くの連鎖方法があり、非垞に重い可胜性があるため、連鎖は怠惰を䌎いたせん。

プレフィックスawaitキヌワヌドは他の蚀語を䜿甚するナヌザヌにずっお最も銎染み深いものですが、それに基づいお決定する必芁はないず思いたす。代わりに、䜿いやすさ、利䟿性、読みやすさなど、より長期的なものに集䞭する必芁がありたす。 。 @withoutboatsは「芪しみやすさの予算」に぀いお

今、私たちはおそらく同じこずをする2぀の方法を望たないので、接尟蟞ず接頭蟞の䞡方のバリアントを導入するべきではありたせん。 したがっお、オプションを接尟蟞のバリアントに絞り蟌んだずしたしょう。

たず、 fut awaitから始めたしょう。このバリアントは、人間がコヌドを解析する方法を深刻に混乱させ、コヌドを読み取る際に垞に混乱を招くため、非垞に嫌いです。 コヌドは䞻に読み取り甚であるこずを忘れないでください

次のfut.await 、 fut.await() 、 fut.await!() 。 最も䞀貫性があり、混乱の少ないバリアントは、接尟蟞マクロのものになるず思いたす。 いく぀かの文字を節玄するためだけに、新しい「キヌワヌド関数」たたは「キヌワヌドメ゜ッド」゚ンティティを導入する䟡倀はないず思いたす。

最埌に、印章ベヌスのバリアント fut@awaitおよびfut@ 。 fut@awaitバリ゚ヌションが奜きではありたせん。印章を玹介するず、なぜawait郚分に煩わされるのでしょうか。 将来の拡匵fut@something蚈画はありたすか そうでなければ、それは単に冗長に感じたす。 だから私はfut@バリアントが奜きです。それは優先順䜍の問題を解決し、コヌドは理解しやすく、曞きやすく、読みやすくなりたす。 可芖性の問題は、コヌドの匷調衚瀺によっお解決できたす。 この機胜を「@forawait」ず説明するのは難しいこずではありたせん。 もちろん、最倧の欠点は、非垞に限られた「印章予算」からこの機胜の料金を支払うこずですが、機胜の重芁性ず非同期コヌドベヌスで䜿甚される頻床を考慮するず、長期的には䟡倀があるず思いたす。 そしおもちろん、 ?で特定の類䌌点を描くこずができたす。 ただし、Rust批評家からのPerlゞョヌクに備える必芁がありたす

結論私の意芋では、「印章予算」に負担をかける準備ができおいる堎合はfut@を䜿甚し、そうでない堎合はfut.await!()たす。

Rustはニッチが異なり、すでに倚くの点で異なっお芋えるため、芪しみやすさに぀いお話すずき、JS / Python / Cの芪しみやすさに぀いおあたり気にする必芁はないず思いたす。 これらの蚀語に類䌌した構文を提䟛するこずは、短期的で䜎報酬の目暙です。 Rustが完党に異なる動䜜をする堎合、䜿い慣れたキヌワヌドを䜿甚するためだけにRustを遞択するこずはありたせん。

しかし、Rustは同様のニッチであり、哲孊によっおさえ、他の蚀語よりもGoに近いため、Goに粟通しおいるこずが重芁です。 そしお、偏芋のある憎しみのすべおにもかかわらず、䞡方の最倧のポむントの1぀は、機胜を盲目的にコピヌするのではなく、本圓に理由のある゜リュヌションを実装するこずです。

IMO、この意味で<--構文はここで最も匷力です

それでも、Rust匏はいく぀かの連鎖メ゜ッドになる可胜性があるこずを忘れないでください。 ほずんどの蚀語はそうしない傟向がありたす。

C開発チヌムの経隓を思い出させたい

C構文に察する䞻な考慮事項は、挔算子の優先順䜍がfooを埅぀こずです。

これは私がコメントできるような気がしたす。 'await'で優先順䜍をよく考え、必芁なフォヌムを蚭定する前に倚くのフォヌムを詊したした。 私たちが芋぀けた䞭心的なこずの1぀は、この機胜を䜿甚したいず思っおいた私たちず顧客内郚および倖郚にずっお、非同期呌び出しを超えお䜕かを「チェヌン」したいず思うこずはめったにありたせんでした。

expr内で「await」を䜿甚しお「続行」したいずいう傟向はたれでした。 await expr.Mのようなものが時々芋られたすが、それらはexpr.Mを埅぀人の数よりも䞀般的ではなく望たしくないようです。

そしお

これが、「await」に「暗黙の」圢匏を䜿甚しなかった理由でもありたす。 実際には、それは人々が非垞に明確に考えたいず思っおいたものであり、圌らがそれに泚意を払うこずができるようにコヌドの䞭心に眮きたいず思っおいたした。 興味深いこずに、数幎埌もこの傟向は続いおいたす。 ぀たり、䜕幎も埌に、䜕かが過床に冗長であるこずを埌悔するこずがありたす。 いく぀かの機胜は早い段階でそのように優れおいたすが、人々がそれに慣れたら、䜕かより簡朔なものに適しおいたす。 'await'の堎合はそうではあり

専甚のキヌワヌド単語ではなく、印章に察する良い点です。

https://github.com/rust-lang/rust/issues/50547#issuecomment -388939886

あなたは本圓に䜕癟䞇ものナヌザヌを持぀人に耳を傟けるべきです。

したがっお、䜕もチェヌンしたくない、いく぀かのawaitが必芁なだけで、私の経隓は同じです。 async/awaitコヌドを6幎以䞊䜜成しおいお、そのような機胜は必芁ありたせんでした。 接尟蟞の構文は本圓に異質に芋え、決しお起こらない可胜性が高い状況を解決するず考えられおいたす。 Async呌び出しは本圓に倧胆なものなので、1行で耇数の埅機が重すぎたす。

expr内で「await」を䜿甚しお「続行」したいずいう傟向はたれでした。 await expr.Mのようなものが時々芋られたすが、それらはexpr.Mを埅぀人の数よりも䞀般的ではなく望たしくないようです。

それは事埌分析のようです。 おそらく、続行しない理由の1぀は、プレフィックス構文で続行するのが非垞に厄介なためです挔算子?読み取り可胜なたたであるため、ステヌトメントでtry!耇数回実行したくない堎合ず比范しお ? 。 䞊蚘は䞻に私が知る限り優先順䜍ではなく、優先順䜍を考慮しおいたす。 たた、CはRustではなく、トレむトメンバヌは結果のメ゜ッドを呌び出したいずいう欲求をかなり倉える可胜性があるこずを思い出しおください。

@ I60R 、

  1. 芪しみやすさが重芁だず思いたす。 Rustは比范的新しい蚀語であり、人々は他の蚀語から移行するでしょう。Rustが芋慣れおいる堎合は、Rustを遞択する決定を䞋すのが簡単になりたす。
  2. 私はメ゜ッドのチェヌン化をあたり楜しんでいたせん-長いチェヌンをデバッグするのははるかに難しく、チェヌン化はコヌドの可読性を耇雑にするだけであり、远加のオプションずしおのみ蚱可される可胜性がありたすマクロ.await!() 。 プレフィックス圢匏では、開発者は次のように、チェヌンではなくメ゜ッドにコヌドを抜出する必芁がありたす。
let resp = await client.get("http://api")?;
let body: MyResponse = await resp.into_json()?;

このようなものに

let body: MyResponse = await client.get_json("http://api")?;

それは事埌分析のようです。 おそらく、それらが継続しない理由の1぀は、プレフィックス構文でそうするこずが非垞に厄介だからです。 䞊蚘は、䜍眮ではなく、優先順䜍のみを考慮しおいたす。 たた、CはRustではなく、トレむトメンバヌは結果のメ゜ッドを呌び出したいずいう欲求をかなり倉える可胜性があるこずを思い出しおください。

いいえ、プレフィックス/ポストフィックス/暗黙の圢匏の䞡方がある堎合の内郚Cチヌムの実隓に関するものです。 そしお、私は接尟蟞フォヌムのプロを芋るこずができないずいう単なる習慣ではない私の経隓に぀いお話しおいる。

@mehcodeあなたの䟋は私をやる気にさせたせん。 reqwestは、最初の芁求/応答サむクルずそれに続く応答ボディストリヌムの凊理を別々の䞊行プロセスにするこずを意識的に決定するため、 埅機する必芁がありたす。

reqwestは、次のAPIを完党に公開する可胜性がありたす。

let res = await client
    .get("url")
    .json()
    .send();

たたは

let res = await client
    .get("url")
    .send()
    .json();

埌者はand_then超える単糖です。

reqwestずhyperの最良のAPI決定はこれらを別々に保぀こずであるため、ここでの接尟蟞の䟋の倚くがこのチェヌンを䟋ずしお䜿甚しおいるのは厄介です。

ここでのほずんどの接尟蟞埅機の䟋は、コンビネヌタおよび必芁に応じお砂糖を䜿甚しお曞き盎すか、同様の操䜜を続けお耇数回埅機する必芁があるず正盎に信じおいたす。

@andreytkachenko

プレフィックス圢匏では、開発者は次のように、チェヌンではなくメ゜ッドにコヌドを抜出する必芁がありたす。

それは良いこずですか、悪いこずですか N個のメ゜ッドがあり、それぞれがM個のフォロヌアップをもたらす可胜性がある堎合、開発者はN * Mメ゜ッドを提䟛するこずになっおいたすか 個人的には、少し長くおも、構成可胜な゜リュヌションが奜きです。

このようなものに

let body: MyResponse = await client.get_json("http://api")?;
let body: MyResponse = client.get("http://api").await?.into_json().await?;

@Pzixel

Cでは、Rustの堎合ほど倚くの連鎖/関数型コヌドを取埗できるずは思いたせん。 それずも私は間違っおいたすか これにより、C開発者/ナヌザヌの経隓は興味深いものになりたすが、必ずしもRustに適甚できるずは限りたせん。 OcamlやHaskellず察比できたらいいのにず思いたす。

それが意芋の盞違の根本的な原因だず思いたす。私たちの䞭には呜什型のスタむルを楜しんでいる人もいれば、機胜的なスタむルを楜しんでいる人もいたす。 以䞊です。 Rustは䞡方をサポヌトしおおり、議論の䞡偎は、非同期が通垞のコヌドの蚘述方法にうたく適合するこずを望んでいたす。

@dpc

Cでは、Rustの堎合ほど倚くの連鎖/関数型コヌドを取埗できるずは思いたせん。 それずも私は間違っおいたすか これにより、C開発者/ナヌザヌの経隓は興味深いものになりたすが、必ずしもRustに適甚できるずは限りたせん。 OcamlやHaskellず察比できたらいいのにず思いたす。

LINQず機胜スタむルはCでかなり人気がありたす。

@dpc 、
読みやすさに぀いおは、コヌドが明瀺的であるず同じくらい優れおいたす。私の経隓では、メ゜ッド/関数の名前が自己蚘述的である堎合は、フォロヌアップを行う必芁はありたせん。

オヌバヌヘッドに぀いおの堎合-Rustコンパむラはそれらをむンラむン化するのがかなり賢いですずにかく私たちは垞に#[inline]持っおいたす。

@dpc

let body: MyResponse = client.get("http://api").await?.into_json().await?;

私の感じでは、これは基本的にfutures APIの問題を繰り返したす。チェヌンは簡単になりたすが、そのチェヌンのタむプは浞透しおデバッグするのがはるかに難しくなりたす。

同じ議論がにも圓おはたりたせんか でもオペレヌタヌ これにより、より倚くの連鎖が可胜になり、デバッグが困難になりたす。 しかし、なぜ私たちは遞んだのですか やり過ぎ それなら そしお、なぜRustはビルダヌパタヌンのAPIを奜むのですか そのため、Rustは、APIでのチェヌンを支持する倚くの遞択をすでに行っおいたす。 はい、それはデバッグを難しくするかもしれたせんが、それは糞くずレベルで起こるべきではありたせん-倚分倧きすぎるチェヌンのためのクリッピヌのための新しい糞くず ここでの埅機の違いに぀いおは、ただ十分な動機付けが必芁です。

それは良いこずですか、悪いこずですか N個のメ゜ッドがあり、それぞれがM個のフォロヌアップをもたらす可胜性がある堎合、開発者はN * Mメ゜ッドを提䟛するこずになっおいたすか 個人的には、少し長くおも、構成可胜な゜リュヌションが奜きです。

NずMは必ずしも倧きいわけではなく、すべおが関心のある/抜出に圹立぀ずは限りたせん。

@andreytkachenko 、

  1. 私は同意したせん、芪しみやすさはここで過倧評䟡されおいたす。 他の蚀語から移行するずき、最初の人々はasync-awaitスタむルのプログラミングを行う胜力を求めたすが、たったく同じ構文ではありたせん。 実装方法が異なるが、それによっおプログラミング゚クスペリ゚ンスが向䞊する堎合は、さらに別の利点になりたす。

  2. 長いチェヌンをデバッグできないこずは、コヌドスタむルではなくデバッガヌの制限です。 読みやすさに぀いおは状況次第だず思いたすが、ここでは呜什型を匷制するこずは䞍必芁に制限されおいたす。 async関数呌び出しがただ関数呌び出しである堎合、チェヌンをサポヌトしないのは驚くべきこずです。 ずにかく、 <--は、远加オプションずしお関数チェヌンで䜿甚できるプレフィックス挔算子です。

@skade同意したした。

埅機の長いチェヌンを持぀すべおの䟋は、コヌドの臭いです。 これらのゞェネレヌタヌスパゲッティステヌトマシンを内郚で䜜成するのではなく、コンビネヌタヌたたは曎新されたAPIを䜿甚しおはるかに゚レガントに解決できたす。 極端な省略構文は、珟圚の将来よりもさらに難しいデバッグのレシピです。

私はただプレフィックスキヌワヌドawaitずマクロawait!(...) / .await!()の䞡方のファンでasyncず#[async]ゞェネレヌタヌ関数ず組み合わせおいたす、ここに私のコメント

すべおがうたくいけば、プレフィックスずサフィックスの䞡方を凊理するためにawait!に察しお単䞀のマクロを䜜成でき、 awaitキヌワヌドはasync関数内のキヌワヌドになりたす。

@skade 、
私にずっお、 futureコンビネヌタを䜿甚するこずの倧きな欠点は、コンビネヌタがasync関数呌び出しを非衚瀺にし、通垞の関数ず区別できないこずです。 ビルダヌスタむルのチェヌン内で䜿甚される可胜性が非垞に高いため、すべおのサスペンド可胜なポむントを確認したいず思いたす。

@ I60Rの長い呌び出しチェヌンのデバッグは、デバッガヌの問題ではありたせん。これらのチェヌンの蚘述に関する問題は、型掚論を正しく行うこずだからです。 これらのメ゜ッドの倚くがゞェネリックパラメヌタヌを受け取り、クロヌゞャヌにバむンドされる可胜性のあるゞェネリックパラメヌタヌを配垃するこずを考えるず、深刻な問題です。

すべおのサスペンションポむントを衚瀺するこずがこの機胜の目的であるかどうかはわかりたせん。 これは実装者が決定する必芁がありたす。 そしお、それはawait構文の提案されたすべおのバヌゞョンで完党に可胜です。

@novacrazyの良い点、あなたがそれを蚀ったので、以前のjavascripterずしお、私はawaitチェヌンを決しお䜿甚したせん、私は垞にその埌ブロックを䜿甚したした

私はそれが次のように芋えるず思いたす

let result = (await doSomethingAsync()
          .then(|result| {
                     match result {
                          Ok(v) => doSomethingAsyncWithFirstResponse(v)
                          Err(e) => Future.Resolve(Err(e))
                      }
            }).then(|result| {
                  Ok(result.unwrap())
            })).unwrap();

それが可胜かどうかさえわかりたせんが、Rustの先物を調べる必芁がありたす

@richardanayaこれは完党に可胜です異なる構文。

Box implのように

impl<T> Box<T> {
    #[inline]
    pub fn new(x: T) -> Box<T> {
        box x
    }
    ...
}

次のように、新しいキヌワヌドawaitを入力しおAwaitを特性化できたす。

impl<T> Await for T {
    #[inline]
    pub fn await(self) -> T {
        await self
    }
    ...
}

たた、メ゜ッドおよびキヌワヌドずしおawaitを䜿甚したす。

let result = await foo();
first().await()?.second().await()?;

@richardanaya同意したした。 私は䜕幎も前に私のwebdevのものにasync / awaitを採甚した最初の開発者の䞀人でした、そしお本圓の力はasync / awaitを既存のPromises / Futuresず組み合わせるこずから来たした。 たた、あなたの䟋でさえ、おそらく次のように単玔化するこずができたす。

let result = await doSomethingAsync()
                  .and_then(doSomethingAsyncWithFirstResponse);

let value = result.unwrap();

先物たたは先物の結果たたは結果の先物をネストしおいる堎合、 .flatten()コンビネヌタはそれをさらに倧幅に単玔化できたす。 手動ですべおを開梱しお埅぀のは悪い圢です。

@XXこれは冗長で無効です。 awaitはasync関数にのみ存圚し、ずにかくFuture / IntoFutureを実装する型でのみ機胜するため、新しい関数は必芁ありたせん。特性。

@ novacrazy 、 @ richardanaya

これらのゞェネレヌタスパゲッティステヌトマシンを内郚で䜜成するのではなく、コンビネヌタたたは曎新されたAPIを䜿甚しおはるかに゚レガントに解決できたす。 極端な省略構文は、珟圚の将来よりもさらに難しいデバッグのレシピです。

@novacrazyの良い点、あなたがそれを蚀ったので、以前のjavascripterずしお、私はawaitチェヌンを決しお䜿甚したせん、私は垞にその埌ブロックを䜿甚したした

コンビネヌタは、Rusts async / awaitでたったく異なるプロパティずパワヌを持っおいたす。たずえば、yieldポむント間での借甚に関しおです。 非同期ブロックず同じ機胜を持぀コンビネヌタを安党に䜜成するこずはできたせん。 コンビネヌタの議論は圹に立たないので、このスレッドから陀倖したしょう。

@ I60R

私にずっお、将来コンビネヌタを䜿甚するこずの倧きな欠点は、それらが非同期関数呌び出しを非衚瀺にし、それらを通垞の関数ず区別するこずが䞍可胜になるこずです。 ビルダヌスタむルのチェヌン内で䜿甚される可胜性が非垞に高いため、すべおのサスペンド可胜なポむントを確認したいず思いたす。

サスペンドポむントを非衚瀺にするこずはできたせん。 コンビネヌタが蚱可する唯䞀のこずは、他の先物を䜜成するこずです。 ある時点で、それらを埅たなければなりたせん。

Cには、プレフィックスawaitを䜿甚するほずんどのコヌドが、既存のポストフィックス?挔算子ず結合するずいう問題がないこずに泚意しおください。 特に、優先順䜍に関する質問、および2぀の類䌌した「デコレヌタ」を持぀こずの䞀般的な厄介さは、匏の反察偎に衚瀺されたす。

@ Matthias247デヌタを借甚する必芁がある堎合は、確かに、耇数のawaitステヌトメントを自由に䜿甚しおください。 ただし、倚くの堎合、単にデヌタを移動する必芁があり、コンビネヌタはそのために完党に有効であり、より効率的なコヌドにコンパむルされる可胜性がありたす。 完党に最適化されるこずもありたす。

繰り返したすが、本圓の力は物事を組み合わせるこずにありたす。 これほど耇雑なこずをする正しい方法はありたせん。 そのため、この構文のバむクシェディングは、他の蚀語からの新しいナヌザヌを助けたり、保守可胜でパフォヌマンスが高くしたりするのに圹立たない堎合は、たさにそのように考えおいたす。 80の確率で、構文が䜕であれ、単玔な先物を䜿甚しお最も安定したパフォヌマンスの高いAPIを提䟛するために、 async / await觊れるこずすらできないず思いたす。

その点で、プレフィックスキヌワヌドawaitおよび/たたは混合マクロawait!(...) / .await!()は、最も読みやすく、䜿い慣れた、デバッグしやすいオプションです。

@andreytkachenko

私はあなたの投皿を芋お、実際、私が「芪しみやすさ」に぀いお考えた今、完党に同意したす。芪しみやすさには2぀のタむプがあるず思いたす。

  1. await構文を、倚くのawaitを䜿甚する同様の蚀語のように芋せたす。 Javascriptはここではかなり倧きく、コミュニティずしおのWASM機胜に非垞に関連しおいたす。

  2. 2番目のタむプの芪しみやすさは、同期コヌドのみを扱う開発者にコヌドを芪しみやすく芋せるこずです。 awaitの最倧の特城は、非同期コヌドをLOOK同期にするこずだず思いたす。 これは実際、javascriptが実際に間違っおいるこずの1぀です。これは、䞻に同期開発者にずっおたったく異質に芋えるチェヌンよりも長く正芏化されおいるこずです。

javascript asyncの時代から私が提䟛したいこずの1぀は、振り返っおみるず開発者ずしお私にずっおはるかに䟿利だったのは、promise / futureをグルヌプ化する機胜でした。 Promise.allp1、p2なので、䜜業を簡単に麻痺させるこずができたす。 thenチェヌンは、垞にJavascriptの過去の玄束の反響でしたが、私が考えるず、かなり叀颚で䞍必芁です。

私は倚分この埅぀ずいう考えを提䟛したいず思いたす。 「非同期コヌドず同期コヌドの違いを最小限に抑えるようにしおください」

@novacrazy非同期関数は、impl Futureタむプを返したすよね Futureトレむトにawaitメ゜ッドを远加できない理由は䜕ですか このように

pub fn await(self) -> Self::Output {
    await self
}
...

@XX私が理解しおいるように、Rustのasync関数は、ゞェネレヌタヌを䜿甚しおステヌトマシンに倉換されたす。 この蚘事は良い説明です。 したがっお、 awaitが機胜するにasync関数が必芁です。これにより、コンパむラヌは䞡方を正しく倉換できたす。 awaitは、 async郚分がないず機胜したせん。

Futureはwaitメ゜ッドがありたす。これはあなたが提案したものず䌌おいたすが、珟圚のスレッドをブロックしたす。

@skade 、

しかし、コヌドスタむルが型掚論にどのように圱響する可胜性がありたすか 連鎖型および呜什型で蚘述された同じコヌドに違いは芋られたせん。 タむプは完党に同じである必芁がありたす。 デバッガヌがそれらを理解できない堎合、それはコヌドではなくデバッガヌで間違いなく問題です。

@ skade 、 @ Matthias247 、

コンビネヌタを䜿甚するず、機胜チェヌンの先頭に1぀の䞭断点がマヌクされたす。 他のすべおは内郚で暗黙的になりたす。 これは、暗黙のmut堎合ずたったく同じ問題です。これは、個人的にはRustの最倧の混乱点の1぀でした。 䞀郚のAPIは先物を返したすが、他のAPIは先物の結果を返したす-私はそれを望んでいたせん。 サスペンションポむントは、可胜であれば明瀺的である必芁があり、適切に構成可胜な構文は、

@ I60R letバむンディングは、型掚論ぞのゞャンクションポむントであり、゚ラヌ報告に圹立ちたす。

@novacrazy

したがっお、awaitで動䜜するには非同期関数が必芁です

これは戻り倀の型で衚珟できたすか 䟋えば、戻り倀の型があるこずをimpl Future + Asyncの代わりに、 impl Future 。

@skadeメ゜ッド呌び出し構文の.はたったく同じ目的を果たすずい぀も思っおいたした

@dpc

Cでは、Rustの堎合ほど倚くの連鎖/関数型コヌドを取埗できるずは思いたせん。 それずも私は間違っおいたすか これにより、C開発者/ナヌザヌの経隓は興味深いものになりたすが、必ずしもRustに適甚できるずは限りたせん。 OcamlやHaskellず察比できたらいいのにず思いたす。

あなたは錆ず同じくらい倚くを埗る。 LINQコヌドを芋るず、それが衚瀺されたす。

兞型的な非同期コヌドは次のようになりたす。

async Task<List<IGroping<int, PageMetadata>>> GetPageMetadata(string url, DbSet<Page> pages)
{
    using(var client = new HttpClient())
    using(var r = await client.GetAsync(new Uri(url)))
    {
        var content = await r.Content.ReadAsStringAsync();
                return await pages
                   .Where(x => x.Content == content)
                   .Select(x => x.Metadata)
                   .GroupBy(x => x.Id)
                   .ToListAsync();
    }
}

たたは、より䞀般的な

let a = await!(service_a);
let b = await!(some_method_on(a, some, other, params));
let c = await!(combine(somehow, a, b));

呌び出しを連鎖させるのではなく、倉数に割り圓おおから、なんらかの方法で䜿甚したす。 あなたがborrowcheckerを扱うずき、それは特に真実です。


私はあなたが䞀぀の状況で先物を連鎖させるこずができるこずに同意するこずができたす。 通話䞭に発生する可胜性のある゚ラヌを凊理する堎合。 䟋 let a = await!(service_a)? 。 これは、postfixの代替が優れおいる唯䞀の状況です。 私はそれがここで利益を埗るのを芋るこずができたした、しかし私はそれがすべおの短所を䞊回るずは思いたせん。

別の理由 impl Add for MyFuture { ... }ずlet a = await a + b;どうですか

postfixawaitキヌワヌドのコンテキストで

let x = (0..10)
    .map(some_computation)
    .collect() : Result<Vec<_>, _>
    .unwrap()
    .map(other_computation) : Vec<usize>
    .into() : Rc<[_]>;

接尟蟞awaitキヌワヌドず非垞によく䌌おいたす。

let foo = alpha() await?
    .beta await
    .some_other_stuff() await?
    .even_more_stuff() await
    .stuff_and_stuff();

正しくフォヌマットされおいない堎合も同じ欠点がありたす。

foo.iter().map(|x| x.bar()).collect(): Vec<_>.as_ref()
client.get("https://my_api").send() await.unwrap().json() await.unwrap()

Type Ascription RFCのピルを飲み蟌む堎合は、䞀貫性を保぀ためにfut awaitを飲み蟌む必芁があるず思いたす。

ずころで、これが有効な構文であるこずをご存知でしたか

fn main() {
    println
    !("Hello, World!");
}

それでも、実際のコヌドではこれが発生するこずはありたせんでした。

少し䜙談させおください。 @BenoitZugmeyerによっお提案されおいるexpr!macroたたはexpr@macro 、あるいはexpr.macro!()ずしおも実行できたす。 最初のオプションが望たしいず思いたす。 それらが良いアむデアかどうかはわかりたせんが、接尟蟞を埅っおいる間にアドホックな解決策ではなく䞀般的な抂念を抜出したい堎合は、少なくずも接尟蟞マクロを朜圚的な解決策ずしお考える必芁がありたす。

awaitを接尟蟞マクロにしたずしおも、それは魔法のマクロ compile_error! であるこずに泚意しおください。 ただし、 @ jplatteやその他の䌁業は、それが問題ではないこずをすでに確立しおいたす。

そのルヌトに行く堎合、私は最初にpostfixマクロがどのように機胜するかを正確に確立し、次にawaitのみを魔法のpostfixマクロずしお蚱可し、埌で独自に定矩されたpostfixマクロを蚱可したす。

字句解析

字句解析/構文解析に関しおは、これは問題になる可胜性がありたす。 expr!macroず、コンパむラはexpr!ずいうマクロがあり、その埌に無効な文字macroがあるず考えるかもしれたせん。 ただし、 expr!macroは、先読みでlexできるはずであり、 expr埌に!が続き、その盎埌にidentifierがあるず、䜕かが接尟蟞マクロになりたす。 expr!macro圢匏を取るこずができるず仮定したす。

埌眮マクロは圹に立ちたすか

頭のおっぺんに、埌眮マクロのこれらの他のナヌスケヌスを思い぀いた。 ただし、すべおをカスタムマクロで実装できるずは限らないため、このリストが非垞に圹立぀かどうかはわかりたせん。

  • stream!await_all ストリヌムを埅機するため
  • option!or_continue  optionがNoneの堎合、ルヌプを続行したす
  • monad!bind 名前にバむンドせずに=<<を実行する堎合

stream!await_all

これにより、先物だけでなくストリヌムも埅぀こずができたす。

event_stream("ws://some.stock.exchange/usd2eur")
    .and_then(|exchange_response| {
        let exchange_rate = exchange_response.json()?;
        stream::once(UpdateTickerAction::new(exchange_rate.value))
    })

 async -stream-esqueブロック内ず同等になりたす

let exchange_rate = event_stream("ws://some.stock.exchange/usd2eur")
    !await_all
    .json()?;

UpdateTickerAction::new(exchange_rate.value)

option!or_continue

これにより、オプションのラップを解陀し、それがNone堎合は、ルヌプを続行できたす。

loop {
    let event = match engine.event() {
        Some(event) => event,
        None => continue,
    }
    let button = match event.button() {
        Some(button) => button,
        None => continue,
    }
    handle_button_pressed(button);
}

ず同等になりたす

loop {
    handle_button_pressed(
        engine.event()!or_continue
            .button()!or_continue
    );
}

monad!bind

これにより、かなり玠朎な぀たり衚珟䞭心の方法でモナドを取埗できたす。 Rustにはただモナドのようなものはなく、Rustに远加されおも売られおいたせん。 それでも、それらを远加する堎合は、この構文が圹立぀可胜性がありたす。

ここから以䞋を取りたした。

nameDo :: IO ()
nameDo = do putStr "What is your first name? "
            first <- getLine
            putStr "And your last name? "
            last <- getLine
            let full = first ++ " " ++ last
            putStrLn ("Pleased to meet you, " ++ full ++ "!")

次のようになりたす。

do {
    putStr("What is your first name? ")!bind;
    let first = getLine()!bind;
    putStr("And your last name? ")!bind;
    let last = getLine()!bind;
    let full = first + " " + &last
    putStrLn("Pleased to meet you, " + &full + "!")!bind;
}

たたは、 letが少ない、よりむンラむン化

do {
    putStr("What is your first name? ")!bind;
    let first = getLine()!bind;
    putStr("And your last name? ")!bind;
    putStrLn(
        "Pleased to meet you, " + &first + " " + &getLine()!bind + "!"
    )!bind;
}

評䟡

私はこれに぀いお非垞に分かれおいたす。 私の脳の数孊者の郚分は、 await䞀般化された解決策を芋぀けたいず思っおおり、接尟蟞マクロはそれらを達成する方法かもしれたせん。 私の脳の実甚的な郚分は次のように考えおいたす。マクロシステムがただ誰も理解しおいない蚀語をわざわざ䜜るのはなぜですか。

ただし、 ?ずawaitから、非垞に䟿利な接尟蟞挔算子の2぀の䟋がありたす。 将来远加したいもの、おそらく私が蚀及したものに䌌たものを芋぀けたらどうしたすか それらを䞀般化すれば、自然にRustに远加できたす。 そうでない堎合は、毎回さらに別の構文を考え出す必芁がありたす。これにより、接尟蟞マクロよりも蚀語が肥倧化する可胜性がありたす。

皆さんはどう思いたすか

@EyeOfPython

私は非垞によく䌌たアむデアを思い぀きたした。Rustの接尟蟞マクロは時間の問題です。
ndarrayスラむスを扱うずきは、毎回それに぀いお考えおいたす。

let view = array.slice(s![.., ..]);

しかし、はるかに良いでしょう

let view = array.slice![.., ..];
// or like you suggested
let view = array!slice[.., ..];
// or like in PHP
let view = array->slice![.., ..];

たた、 _withたたは_else接尟蟞が付いたもののように、倚くのコンビネヌタがなくなる可胜性がありたす。

opt!unwrap_or(Error::new("Error!"))?; //equal to .unwrap_or_else(||Error::new("Error!"));

@EyeOfPython @andreytkachenko postfixマクロは珟圚Rustの機胜ではなく、

これはRFCの議論ではなく、実装する必芁のある受け入れられたRFCの議論です。

そのため、ここでそれらに぀いお説明したり、非同期構文を提案したりするこずは珟実的ではないず思いたす。 それはさらに機胜を倧幅に遅らせるでしょう。

このすでに倧芏暡な議論を抑制するために、ここでそれらを議論するこずは圹に立たないず思いたす。それらは議論された問題の倖にあるず芋なすこずができたす。

ちょっず考えおみおください。このスレッドは特にawaitを察象ずしおいたすが、今埌はyield匏に぀いおもたったく同じ議論が行われるず思いたすが、これも同様に連鎖する可胜性がありたす。 䞀般化できる構文を芋たいのですが、芋た目は同じです。

ここでマクロを䜿甚しない理由

  1. マクロはドメむン固有のもののために提䟛されおおり、プログラムの制埡フロヌを倉曎したり、コア蚀語機胜を゚ミュレヌトしたりする方法でマクロを䜿甚するのはやり過ぎです
  2. 接尟蟞マクロはすぐに悪甚されお、カスタム挔算子やその他の゚゜セリック蚀語機胜を実装し、コヌドの誀りを匕き起こしたす
  3. 圌らは適切な蚀語機胜の開発を思いずどたらせるでしょう

    • stream.await_allはコンビネヌタの完璧なナヌスケヌスです

    • option.or_continueず_elseコンビネヌタの眮き換えは、null合䜓挔算子の完璧なナヌスケヌスです

    • monad.bindはif-letチェヌンの完璧なナヌスケヌスです

    • ndarray slicingは、 constゞェネリックの完璧なナヌスケヌスです

  4. 圌らはすでに実装されおいる?挔算子に疑問を投げかけたす

@collinanderson

同様に連鎖する可胜性がありたす

なぜ地球䞊でそれらが連鎖する可胜性があるず思いたすか 䞊蚘のprintln䟋のように、実際のコヌドでは発生したせん。

@Pzixel最終的にGenerator::resumeが倀をずる可胜性が高いため、 yield exprは非()タむプになりたす。

@vlaff awaitがTypeAscriptionず䞀臎しおいる必芁があるずいう議論がはっきりずわかりたせん。 それらは非垞に異なるものです。

たた、タむプアクリプションは繰り返し詊行される機胜の1぀であり、これが成功するずいう保蚌はありたせん。 私はこれに反察したくありたせんが、TAは将来のRFCであり、これはすでに提案されおいる構文で受け入れられおいる機胜に぀いおの議論です。

倚くのコメントを読んで、なぜ埅぀のかに぀いおさらに芁玄を远加するために...は非垞に理想的なパスに芋えたす

  1. マクロはなじみがあるので、既存のコヌドに最もなじみがあるように芋えたす
  2. awaitを䜿甚する既存の䜜業がありたす... https://github.com/alexcrichton/futures-awaitし、コヌドの曞き換えを枛らすのに圹立぀可胜性がありたす
  3. 接尟蟞マクロはテヌブルにないので、蚀語の䞀郚になるこずは決しおなく、「埅っおください」 非暙準のコンテキストでは、RFCによる可胜性すらありそうにありたせん
  4. それは、コミュニティに、完党に暙準から倖れおいない䜕かを提䟛しながら、広く普及した安定した䜿甚の埌の長期的な方向性を怜蚎するためのより倚くの時間を䞎えたす䟋try
  5. 埅機ず歩留たりを満たすこずができる公匏の道を芋぀けるたで、次の歩留たりの同様のパタヌンずしお䜿甚できたす
  6. 連鎖は期埅したほど䟡倀がない可胜性があり、耇数の行で耇数の埅機を行うこずで、おそらく明確さがさらに向䞊したす。
  7. IDE構文ハむラむタヌを倉曎する必芁はありたせん
  8. 他の蚀語の人々は、他のマクロの䜿甚法を芋た埌、await...マクロによっお捚おられるこずはおそらくないでしょう認知的過負荷が少ない
  9. 安定化に向けお前進するための、おそらくすべおのパスの䞭で最も最小限の劎力パスです

埅぀ ここではマクロはすでにありたす。問題はチェヌンに぀いおです。

考えれば考えるほど、接尟蟞がよく芋えたす。 䟋えば

let a = foo await;
let b = bar await?;
let c = baz? await;
let d = booz? await?;
let e = kik? + kek? await? + kuk? await?;
// a + b is `impl Add for MyFuture {}` which alises to `a.select(b)`

任意のレベルのネストを蚱可し、読み取り可胜です。 ?および将来のオペレヌタヌずシヌムレスに連携したす。 新芏参入者にずっおは少し異質に芋えたすが、文法䞊の利益がそれを䞊回る可胜性がありたす。

䞻な理由は、 awaitは関数呌び出しではなく、個別のキヌワヌドである必芁があるためです。 重芁すぎるため、独自のハむラむトずテキスト内の配眮を蚭定する必芁がありたす。

@ Pzixel 、 @ HeroicKatora 、 @ skade

たずえば、Pythonのyieldずyield from匏をyieldの結果ずなる倀を提䟛できたす。 これは@valffの意味であり、型の垰属ずは䜕の関係もありたせん。 したがっお、 yieldも!たたは()以倖のタむプになりたす。

コルヌチンのポむントから、 yieldずawait䞡方がコルヌチンを䞀時停止し、最終的に倀を返すこずができたす。 それらは同じコむンの䞡面にすぎないので。

そしお、別の構文の可胜性、_square-brackets-with-keyword_を捚おお、これを郚分的に匷調したす構文の匷調衚瀺にyieldを䜿甚

let body: MyResponse = client.get("http://api").send()[yield]?.into_json()[yield]?

「接尟蟞キヌワヌド」は私にずっお最も理にかなっおいたす。 future-expressionずawait区切る空癜以倖の文字を䜿甚した接尟蟞も私には意味がありたすが、「。」には意味がありたせん。 これはメ゜ッド甚であり、 awaitはメ゜ッドではないためです。 ただし、プレフィックスキヌワヌドずしおawaitが必芁な堎合は、たくさんのものをチェヌンしたい人のためにawait selfを呌び出すだけのトレむトたたはメ゜ッドの@XX提案が奜きですおそらくメ゜ッドにawaitずいう名前を付けるこずはできたせんwaitだけで十分だず思いたす。 個人的には、長いチェヌンは読みにくく、プレフィックスたたはポストフィックスが機胜するため、チェヌンごずではなく、行ごずに埅機するこずになりたす。

[線集] waitすでに存圚し、未来を阻んでいるこずを忘れたので、その考えをかき集めおください。

@roland私は特にこれを参照しおおり、タむプの垰属に぀いお説明しおいたす //github.com/rust-lang/rust/issues/57640#issuecomment -456023146

@rolandsteinerだからあなたは曞く

let body: MyResponse = client.get("http://api").send() await?.into_json() await?;

私がそれを次のように曞くずき

let response = client.get("http://api").send() await?;
let body: MyResponse = response.into_json() await?;

@skadeああ、あなたは私が思っおいたのずは違うコメントを意味したした、ごめんなさい。 stuck_out_tongue

@Pzixel最終的にGenerator::resumeが倀をずる可胜性が高いため、 yield exprは非()タむプになりたす。

したがっお、 yieldも!たたは()以倖のタむプになりたす。

@ valff 、 @ rolandsteiner yieldが再開倀を返す可胜性は䜎いず思いたす。これは、ゞェネレヌタヌの構文や特性を操䜜するのが面倒になるこずなく、静的に型指定された蚀語に適合させるのは困難です。 履歎曞匕数を持぀元のプロトタむプでは、キヌワヌドgen argを䜿甚しおこの匕数を参照しおいたした。このようなものは、IMOでうたく機胜する可胜性がはるかに高くなりたす。 その芳点から、 yieldは()返すので、 awaitの議論にあたり圱響を䞎えないはずです。

asyncはプレフィックス挔算子であるため、 awaitはプレフィックス挔算子である必芁があるず思いたす yieldもプレフィックスになるず思いたす。 たたは、通垞の方法ずしお䜿甚し、接尟蟞の䜍眮で䜿甚したす。

ただし、ここですべおのバむクシェディングを実行しおいるわけではありたせん。Rustの他の誰も持っおいない接尟蟞キヌワヌドを怜蚎するのはなぜですか それは蚀語をずおも奇劙にするでしょう。

たた、先物を連鎖させるず、なぜそれが面癜いのかがわかりたす。 しかし、連鎖が埅っおいたすか それはどういう意味ですか 新しい未来を返す未来 Rustに䞀玚垂民ずしおそのむディオムを持たせたいのは本圓に䞀般的なむディオムですか 私たちが本圓にそれを気にするなら、私は私たちがすべきだず思いたす

  1. メ゜ッドを遞択したす぀たり、 foo.await() 。 それは奇劙な接尟蟞キヌワヌドを導入せず、私たちは皆それが䜕を意味するかを知っおいたす。 それず連鎖するこずもできたす。
  2. キヌワヌド/ロロペレヌタヌが本圓に必芁な堎合は、埌でその質問を解決できたす。

たた、個人的な意芋を述べるために、接尟蟞のキヌワヌド䜍眮にあるawaitは嫌いです。

プレフィックスawaitは、他の蚀語で䜿甚されおいる理由がありたす。これは自然蚀語ず䞀臎したす。 あなたは「あなたの到着を埅぀」ずは蚀わない。 JavaScriptを曞いたのですが、少し偏芋があるかもしれたせん。

たた、 awaitチェヌンは過倧評䟡されおいるず思いたす。 将来のコンビネヌタに察するasync/awaitの䟡倀は、 if 、 matchなどの暙準蚀語構造を利甚しお非同期コヌドを順番に蚘述できるこずです。 あなたはずにかくあなたの埅機を分割したいず思うでしょう。

async/await魔法の構文を䜜りすぎないでください。これは、蚀語のごく䞀郚にすぎたせん。 提案されたメ゜ッド構文぀たり、 foo.await() は、IMOが通垞のメ゜ッド呌び出しに察しお盎亀しすぎおおり、魔法のように倖れおいたす。 proc-macro機械が蚭眮されおいるので、その背埌に隠しおみたせんか

関数の定矩でasyncではなくawaitキヌワヌドを䜿甚するの

await fn foo(future: impl Future<Output = i32>) -> i32 {
    future
}

このawait fnは、 asyncコンテキストでのみ呌び出すこずができたす。

async {
    let n = foo(bar());
}

そしお、 let n = (await foo(bar()));脱糖したす。
次に、 awaitキヌワヌドに加えお、トレむトFutureは、接尟蟞の䜍眮でawaitロゞックを䜿甚するためのawaitメ゜ッドを実装できたす。

async {
    let n = bar().awaited();
}

たた、誰かが私に発電機ずの関係を説明できたすか async / awaitが、ゞェネレヌタヌが安定化されおいおも実装される前に実装されおいるこずに驚いおいたす。

@phaazonゞェネレヌタヌがasync / await内郚実装の詳现ずしおRustに远加されたした。 それらを安定させる珟圚の蚈画はありたせん、そしおそれらが可胜になる前にそれらはただ非実隓的なRFCを必芁ずしたす。 個人的には安定させたいのですが、少なくずも1、2幎は離れおいるようです。おそらく、 async / awaitが安定しお、安定するたでRFCされないでしょう。それに関するいく぀かの経隓。

@XX関数定矩でawaitを䜿甚するず、 asyncのセマンティクスを砎っおいるず思いたす。 基準を守りたしょうね。

@phaazonこれがasyncセマンティクスをどのように壊すかをより詳现に指定できたすか

ほずんどの蚀語はasyncを䜿甚しお非同期になるものを導入し、 awaitがそれを埅ちたす。 したがっお、 await代わりにasyncは、私にはちょっず奇劙です。

@phaazonいいえ、代わりではありたせんが、それに加えお。 完党な䟋

async fn bar() -> i32 {
    5 // will be "converted" to impl Future<Output = i32>
}

await fn foo(future: impl Future<Output = i32>) -> i32 {
    future // will be "converted" to i32 in async context
}

async {
    let a = await bar(); // correct, a == 5
    let b = foo(bar()); // correct, b == 5
}

let c = foo(bar()); // error, can't call desugaring statement `await foo(bar())`

それが有効である堎合、チェヌンで䜿甚するためのawait-methodを実装するこずが可胜になりたす。

async {
    let n = first().awaited()?.second().awaited()?;
    // let n = (await (await first())?.second())?;
}

私の意芋では、postfixがあたりにも魔法のように「感じ」、蚀語に慣れおいないのを埅っおいるかどうかは問題ではありたせん。 メ゜ッド構文.await()たたは.await!()を採甚する堎合、 Futureは.await()たたは.await!()メ゜ッドがあるこずを説明するだけです。意味のある堎合にそれらを埅぀ために䜿甚するこずもできたす。 䞀床も芋たこずがなくおも、5分かけお考えれば理解するのはそれほど難しいこずではありたせん。

さらに、prefixキヌワヌドを䜿甚するず、次のようなクレヌトを䜜成できなくなりたす珟圚、詳现を凊理するむンフラストラクチャがないため、䞍完党な擬䌌コヌド。

trait AwaitChainable {
    fn await(self) -> impl Future;
}

impl<T: Future> AwaitChainable for T {
    fn await(self) -> impl Future {
        await self
    }
}

そうすれば、必芁に応じおpostfixを埅぀こずができたす。 ぀たり、それがどういうわけか䞍可胜であり、コンパむラによっお魔法のように接尟蟞埅機を実装する必芁がある堎合でも、䞊蚘の䟋のようなものを䜿甚しお、それが䞻にどのように機胜するかを説明できたす。 孊ぶのは難しいこずではないでしょう。

@ivandardi私も同じこずを考えたした。 しかし、この定矩

fn await(self) -> impl Future {
    await self
}

関数がasync contextでのみ呌び出すこずができるずは蚀っおいたせん。

@XXええ、私が蚀ったように、壊れた擬䌌コヌドを無芖したすPIには珟圚、正しい構文ず特性をそこに曞き蟌む方法を調べるためのむンフラストラクチャがありたせん:(非同期でのみ呌び出し可胜にするものを曞いたず想像しおくださいコンテキスト。

@ XX 、 @ ivandardi定矩にawaitはasyncコンテキストでのみ機胜したす。 したがっお、これは違法です。

fn await(self) -> impl Future {
    await self
}

それは違いない

async fn await(self) -> impl Future {
    await self
}

これは、次のようなasyncコンテキストでのみ呌び出すこずができたす。

await future.await()

どのような皮類が目的党䜓を打ち負かしたす。

これを機胜させる唯䞀の方法は、 async完党に倉曎するこずです。これはテヌブルから倖れおいたす。

@ivandardi私のバヌゞョンのこの進化

fn await(self) -> T { // How to indicate using in async-context only?
    await self
}

`` `錆
await fn awaitself-> T {//非同期がすでに取埗されおいるため
自分を埅぀
}

```rust
await fn await(self) -> T {
    self // remove excess await
}

@CryZe @XXなぜあなたは私をブヌむングしおいるのですか 私は正しい。

@XX䜕をしようずしおいるこずは、非同期の意味を倉曎しお、完党に埅぀こずですたずえば、䜜成await文脈をから䜕ずか違うasyncコンテキスト。 蚀語開発者からのサポヌトはあたり埗られないず思いたす

@EyeOfPythonこの定矩は期埅どおりに機胜したせん

async fn await(self) -> impl Future {
    await self
}

より可胜性が高い

#[call_only_in_async_context_with_derived_await_prefix]
fn await(self) -> impl Future {
    self
}

これが架空の疑䌌構文であるこずを無芖したため、私は反察祚を投じおいたす。 基本的に圌らのポむントは、Rustが蚀語が理解できるDrop and Copyのような特別な特性を远加できるずいうこずです。これにより、型に察しお.awaitを呌び出す機胜が远加され、awaitキヌワヌドず同じように型ず察話したす。 たた、賛成祚/反察祚によっお芖芚化されるような䞻芳的な感情に基づくものではなく、客芳的な解決策を芋぀けるこずが重芁であるため、投祚はずにかくRFCには無関係であるず芋なされたす。

このコヌドが䜕をすべきかわかりたせん。 しかし、それはasyncawaitが珟圚どのように機胜するかずは䜕の関係もありたせん。 気になる堎合は、このスレッドから陀倖し、専甚のRFCを䜜成しおください。

@CryZeそのタむプが利甚可胜です。 それは未来ず呌ばれおいたす。 そしお、async / awaitは、非同期コヌドの倉換のみを察象ずしたメカニズムであるこずがずっず前に合意されたした。 これは、䞀般的なバむンド衚蚘を意味するものではありたせん。

@ivandariあなたの接尟蟞が埅぀のではなく、新しい未来を創造したす。 それは本質的に恒等関数です。 通垞の関数ではないため、暗黙的に埅぀こずはできたせん。

@ Matthias247圌らが提案しようずしおいたのは、メ゜ッド呌び出しの構文を持぀接尟蟞を埅機させる方法でした。 そうすれば、Rustは、で行ったように、、@、...などの任意の新しい蚘号を導入する必芁がありたせん。 挔算子、そしおそれでもかなり自然に芋えたす

let result = some_operation().await()?.some_method().await()?;

したがっお、コンパむラが通垞のawaitキヌワヌドこの堎合はたったく必芁ありたせんず同じように認識し、非同期を倉換する、Future特性の特別な皮類のメ゜ッドを䜕らかの方法で埅機するずいうアむデアになりたす。そこからゞェネレヌタヌにコヌドしたす。 そうすれば、 await some_future()?で巊右ではなく、巊から右ぞの適切な論理制埡フロヌが埗られ、奇劙な新しいシンボルを導入する必芁はありたせん。

぀たり、tl; drメ゜ッド呌び出しのように芋えたすが、実際には接尟蟞が埅っおいたす

埌眮構文を考慮しお明瀺的に蚀及されおいないこずは、゚ラヌずオプションのコンビネヌタの普及です。 これらは、錆が埅っおいるすべおの蚀語ず最も異なる堎所です-自動トレヌスバックの代わりに、 .map_err()?たす。

特に次のようなもの

let result = await reqwest::get(..).send();
let response = result.map_err(|e| add_context(e))?;
let parser = await response.json();
let parsed = parser.map_err(|e| add_context(e))?;

読みにくいどの接尟蟞構文が考慮されるかは気にしない

let parsed = reqwest::get(..)
    .send() await
    .map_err(add_context)?
    .json() await
    .map_err(add_context)?;

このデフォルトのフォヌマットには、倚倉数アプロヌチよりも倚くの行がありたす。 耇数の埅機がない匏は、postfix-awaitを䜿甚しお垂盎方向のスペヌスを少なくする必芁があるようです。

私は今非同期コヌドを曞いおいたせん、それで私は無知から話しおいる、積み重ねお申し蚳ありたせん-これが実際に問題でないなら、それは玠晎らしいです。 ゚ラヌ凊理を異なる方法で行う他の蚀語に䌌せるために、適切な゚ラヌ凊理を人間工孊的でなくしたくありたせん。

はい、それが私の蚀いたいこずです。 状況に応じお、プレフィックスずポストフィックスのどちらを䜿甚するかを遞択できるので、䞡方の長所がありたす。

@XXそれをナヌザヌコヌドで衚珟できない堎合は、コンパむラを䜿甚しおその機胜を実装する必芁がありたす。 しかし、接尟蟞がどのように機胜するかを理解するずいう点では、衚面的な理解であっおも、以前に投皿した説明は匕き続き機胜したす。

@ CryZe 、 @ XX 、

䞀芋スムヌズに芋えたすが、Rustの哲孊ずは完党に䞀臎したせん。 でもsortむテレヌタの方法は返したせんself配分を明瀺的にするためにず䌑憩メ゜ッドの呌び出しチェヌンを。 ただし、通垞の関数呌び出しず区別が぀かない完党に暗黙的な方法で、圱響が少ないものが実装されるこずを期埅したす。 IMOの可胜性はありたせん。

はい、それが私の蚀いたいこずです。 状況に応じお、プレフィックスずポストフィックスのどちらを䜿甚するかを遞択できるので、䞡方の長所がありたす。

なぜそれが目暙でなければならないのですか Rustは、他のすべおの制埡フロヌたずえば、 break 、 continue 、 ifなどでこれをサポヌトしおいたせん。「これは可胜性がありたす。特定の意芋では芋栄えがしたす。

䞀般に、 awaitは非垞に特別であり、通垞のメ゜ッド呌び出しではないこずを皆さんに思い出させたいず思いたす。

  • スタックが巻き戻されお再確立される可胜性があるため、ステップオヌバヌ埅機時にデバッガヌが奇劙な動䜜をする堎合がありたす。 私が芚えおいる限り、CずJavascriptで非同期デバッグを機胜させるには長い時間がかかりたした。 そしお、それらはデバッガヌに取り組むチヌムに支払いをしたした
  • 埅機ポむントを通過しないロヌカルオブゞェクトは、実際のOSスタックに栌玍できたす。 生成されたfutureに移動する必芁がないものは、最終的に必芁なヒヌプメモリFutureが存圚する堎所に違いをもたらしたす。
  • 埅機ポむントをたたがる借入は、生成された先物が!Unpinである必芁がある理由であり、既存のコンビネヌタずメカニズムのいく぀かに倚くの䞍䟿を匕き起こしたす。 asyncメ゜ッドからUnpin先物を生成する可胜性がありたすが、将来は埅機を超えお借甚したせん。 ただし、 awaitが衚瀺されない堎合、それは発生したせん。
  • async / awaitの珟圚の状態ではカバヌされおいない、他の予期しない借甚チェッカヌの問題がある可胜性がありたす。

@Pzixel @lnicola

Cの䟋は完党に必須であり、Rustでよく芋られる機胜的なスタむルのロングチェヌンのようなものではありたせん。 そのLINQ構文は単なるDSLであり、私が少しグヌグルで調べたfoo().bar().x().wih_boo(x).camboom().space_flight();ようなものではなく、Cコヌド䟋は、ほずんどの䞀般的なプログラミング蚀語ず同様に、100必須に芋えたす。 だからこそ、ラングXがしたこずをただ理解するこずはできたせん。なぜなら、それはたったく同じではないからです。

IMOプレフィックス衚蚘は、呜什型のコヌディングに完党に適合したす。 しかし、Rustは䞡方のスタむルをサポヌトしおいたす。

@skade

機胜的なスタむルの問題に぀いおのあなたのそしお他のコメントのいく぀かに同意したせん。 簡朔にするために、どちらか䞀方を匷く奜む人がいるこずに同意したしょう。

@ Matthias247いいえ、芋た目以倖に特別な理由がありたす。 Rustが連鎖を促進するからです。 そしお、「ああ、他の制埡フロヌメカニズムには接尟蟞の構文がないのに、なぜ特別なものを埅぀必芁があるのですか」ず蚀うかもしれたせん。 たあ、それは間違った評䟡です。 接尟蟞の制埡フロヌがありたす。 それらは、私たちが呌び出すメ゜ッドの内郚にありたす。 Option::unwrap_orは、接尟蟞の䞀臎ステヌトメントを実行するようなものです。 Iterator::filterは、埌眮ifステヌトメントを実行するようなものです。 制埡フロヌが連鎖構文自䜓の䞀郚ではないずいう理由だけで、接尟蟞の制埡フロヌがただないずいう意味ではありたせん。 その芳点では、接尟蟞awaitを远加するこずは、実際には私たちが持っおいるものず䞀臎したす。 この堎合、 Iterator動䜜に䌌たものを䜿甚するこずもでき、生の接尟蟞を埅機させる代わりに、 Future::await_orような埅機コンビネヌタを䜿甚するこずもできたす。 いずれにせよ、接尟蟞を埅぀こずは芋た目だけの問題ではなく、機胜性ず生掻の質の問題です。 そうでなければ、ただtry!()マクロを䜿甚しおいるでしょう

@dpc

Cの䟋は完党に必須であり、Rustでよく芋られる機胜的なスタむルのロングチェヌンのようなものではありたせん。 そのLINQ構文は単なるDSLであり、foo。bar。x。wih_boox.camboom。space_flight;のようなものではありたせん。 私は少しグヌグルで調べたしたが、Cのコヌド䟋は、ほずんどの䞀般的なプログラミング蚀語ず同じように、100必須に芋えたす。 だからこそ、ラングXがしたこずをただ理解するこずはできたせん。なぜなら、それはたったく同じではないからです。

それは真実ではありたせんが pollyなどのフレヌムワヌクを確認できたす、それに぀いおは議論したせん。 䞡方の蚀語で同じ数の連鎖コヌドが衚瀺されたす。 しかし、実際にはすべおが異なるものがありたす。 そしおそれはTry特性ず呌ばれたす。 Cにはそれに䌌たものがないため、 awaitポむントを超えお䜕もするこずは想定されおいたせん。 䟋倖が発生した堎合、それは自動的にラップされ、発信者のために発生したす。

?挔算子を手動で䜿甚する必芁があるRustの堎合はそうではありたせん。

awaitポむントを超えるものが必芁な堎合は、「結合」挔算子await?䜜成するか、蚀語ルヌルを拡匵するなどする必芁がありたす。たたは、接尟蟞を埅぀だけで、物事がより自然になりたす少し異質な構文ですが、誰が気にしたすか

ですから、私は珟圚、より実行可胜な解決策ずしお接尟蟞が埅っおいるず考えおいたす。 私が持っおいる唯䞀の提案は、 await()やawait!()ではなく、専甚のスペヌス区切りのキヌワヌドであるべきです。

通垞の.awaitメ゜ッドを正圓化する正圓な理由を思い぀いたず思いたす。 あなたがそれに぀いお考えるならば、それは他のブロックの方法ず䜕ら倉わりはありたせん。 .awaitメ゜ッドを呌び出すず、おそらくグリヌンスレッドの実行が停止し、ある時点で実行䞭のランタむムがスレッドの実行を再開したす。 したがっお、Mutexチャネルたたはstdチャネルのいずれを䜿甚しおいる堎合でも、すべおの目的ず目的で次のようになりたす。

let result = my_channel().recv()?.iter().map(...).collect();

たたはそのような未来

let result = my_future().await()?.iter().map(...).collect();

違いはありたせん。 それらは䞡方ずもそれぞれのrecv/ awaitで実行をブロックし、䞡方ずも同じ方法でチェヌンしたす。 唯䞀の違いは、awaitがOSのヘビヌりェむトスレッドではない別の゚グれキュヌタで実行されおいる可胜性があるこずですただし、シングルスレッドの゚グれキュヌタの堎合は非垞によくありたす。 したがっお、倧量のチェヌンを思いずどたらせるこずは、たったく同じように䞡方に圱響を及がし、おそらく実際の糞くずの出ない糞くずに぀ながるはずです。

ただし、ここでの私のポむントは、このコヌドを曞いおいる人の芳点からは、.recvず.awaitに倧きな違いはなく、どちらも実行をブロックし、結果が利甚可胜になるず戻るメ゜ッドであるずいうこずです。 。 したがっお、すべおの意図ず目的のために、それはほずんど通垞の方法であり、本栌的なキヌワヌドを必芁ずしたせん。 Mutexずstdのチャネルのrecvたたはlockキヌワヌドもありたせん。

ただし、rustcは明らかにコヌド党䜓をゞェネレヌタヌに倉換したいず考えおいたす。 しかし、それは蚀語の芳点から実際に意味的に必芁ですか 実際のOSスレッドをブロックするこずでawaitを実装するrustcの代替コンパむラを䜜成できるず確信しおいたす非同期fnを入力するず、スレッドが生成され、埅機するずそのスレッドがブロックされたす。 これは非垞に単玔で遅い実装ですが、意味的にはたったく同じように動䜜したす。 したがっお、実際のrustcが埅機をゞェネレヌタヌに倉えるずいう事実は意味的に必芁ではありたせん。 したがっお、実際には、.awaitメ゜ッドの呌び出しをゞェネレヌタヌに倉換するrustcは、rustcの実装の詳现を最適化するものず芋なすこずができるず䞻匵したす。 そうすれば、.awaitが完党なメ゜ッドの䞀皮であり、完党なキヌワヌドではないこずを正圓化できたすが、それでもrustcですべおをゞェネレヌタヌに倉換するこずができたす。

@CryZeは.recv()ずは異なり、プログラム内の他の堎所からawaitを安党に䞭断でき、 await暪のコヌドは実行されたせん。 これは倧きな違いであり、それがawait暗黙的に実行しおはならない最も䟡倀のある理由です。

@ I60Rそれはキヌワヌドずしお埅぀よりも明癜です。 必芁に応じお、IDEでも同じ方法で匷調衚瀺できたす。 キヌワヌドを接尟蟞の䜍眮に移動するだけです。ここでは、実際には芋逃しにくいず思いたす実行が停止する䜍眮にあるため。

クレむゞヌなアむデア暗黙の埅機。 別のスレッドに移動したした。これは、ポストフィックスずプレフィックスの議論ですでに忙しすぎおいるためです。

@CryZe

通垞の.awaitメ゜ッドを正圓化する正圓な理由を思い぀いたず思いたす。 あなたがそれに぀いお考えるならば、それは他のブロックの方法ず䜕ら倉わりはありたせん。

https://github.com/rust-lang/rust/issues/57640#issuecomment-456147515をもう䞀床お読み

@ Matthias247これらは非垞に良い点です、私はそれらを逃したようです。

関数、メンバヌ、たたはその他の暗黙の埅機を䜜成するこずに関するこのすべおの話は、基本的に無効です。 それは行動ではなく、倉革です。

コンパむラヌは、高レベルで、キヌワヌドたたはマクロを介しお、埅機匏を特別なゞェネレヌタヌyield匏に倉換し、その堎で借甚やその他のものを凊理したす。

これは明瀺的である

キヌワヌドずしおできるだけ芋栄えがするか、明らかにマクロを䜿甚しおコヌドを生成する必芁がありたす。

魔法の方法、特性、メンバヌなどは、特に新しいナヌザヌにずっおは、誀解や誀解が非垞に簡単です。

プレフィックスキヌワヌドawaitたたはプレフィックスマクロawaitは、これを行うための最も受け入れられる方法のように思われたす。これは、他の倚くの蚀語がそのように行うのず同じように理にかなっおいたす。 私たちはそれを良くするために特別である必芁はありたせん。

@novacrazy

魔法の方法、特性、メンバヌなどは、特に新しいナヌザヌにずっおは、誀解や誀解が非垞に簡単です。

それを拡匵できたすか より具䜓的には、可胜であれば.await!()バリアントに぀いお。

私の意芋では、 foo.await!()を持っおいるこずは、特に適切な構文の匷調衚瀺を䜿甚しお読むのは難しくありたせん。これは無芖しおはなりたせん。

それの意味を誀解しおいたすか 䜕が本質的に次のずおりですタむプmystakesを無芖しおください

trait Future {
    fn await!(self) -> Self::Item {
        await self
    }
}

別名await this_fooずthis_foo.await!()はたったく同じです。 それに぀いお誀解しやすいものは䜕ですか

そしお、新しいナヌザヌのトピックに぀いお新しいナヌザヌは䜕に プログラミング䞀般、たたは蚀語ずしおのRustの新芏ナヌザヌですが、プログラミング蚀語のバックグラりンドがありたすか 前者の堎合、圌らが非同期プログラミングに手を出すずは思えないからです。 埌者の堎合、混乱するこずなく、䞊蚘で説明したように埌眮埅機のセマンティクスを説明する方が簡単です。

あるいは、プレフィックスawaitのみが远加された堎合、私が知っおいるこずは、フォヌムのRustコヌドを入力ずしお受け取るプログラムの䜜成を停止するこずはありたせん。

foo.bar().baz().quux().await!().melo().await!()

そしおそれをに倉換したす

await (await foo.bar().baz().quux()).melo()

@ivandardi

.await!()は堎合によっおは䟿利で、おそらく次のようにawait!(...)ず䞀緒に機胜したす。

macro_rules! await {
    // prefix
    ($fut:expr) => {...}

    // postfix
    ($self:Self) => { await!($self) }
}

ただし、接尟蟞メ゜ッドのマクロは珟圚存圚せず、存圚しない可胜性がありたす。

それが将来の可胜性であるず考える堎合は、今のずころマクロawait!(...)を䜿甚し、それが実装されたずきに将来的に接尟蟞を远加するだけです。

䞡方のマクロを䜿甚するのが理想的ですが、将来的に接尟蟞マクロを実装する予定がない堎合は、プレフィックスキヌワヌドawaitがおそらく最善の策です。

@novacrazy私はそれに同意するこずができ、それは私の最初の提案です。 今のずころawait!()を远加し、接尟蟞フォヌムを理解する必芁がありたす。 埌眮マクロの可胜性に぀いおも話し合う可胜性がありたす。たた、蚀語で埌眮マクロを完党にサポヌトする前に、埌眮.await!()をその蚀語にアドホックに远加できるかどうかに぀いおも話し合いたす。 ?ずTry特性で起こったこずのように、最初に特別なケヌスずしお远加され、その埌、より䞀般的なケヌスに拡匵されおいたす。 決定するずきに泚意する必芁がある唯䞀のこずは、䞀般的な接尟蟞マクロ構文がどのように芋えるかです。これは、別の議論に倀するかもしれたせん。

プレフィックスキヌワヌドawaitたたはプレフィックスマクロawaitは、これを行うための最も受け入れられる方法のように思われたす。これは、他の倚くの蚀語がそのように行うのず同じように理にかなっおいたす。

それは明らかに_実行可胜_ですが、私はそれに぀いお2぀の議論しか芚えおおらず、説埗力があるずは思いたせん。

  • それが他の蚀語のやり方です

    • それはうれしいですが、我々はすでに実行しおいない-unless-のように違うこずをやっおいるpollの代わりに実行されおいるアップツヌ・初段の線await 、錆が根本的に異なっおいるので、蚀語

  • 行の先頭にawaitれるのが奜きな人

    • しかし、垞にそこにあるずは限らないので、それだけが芋える堎所であれば問題が発生したす

    • それは芋るためだけの簡単なようだawait s内のfoo(aFuture.await, bFuture.await) 、圌らは接頭蟞であるかのように

    • さびた状態では、制埡フロヌを芋るず、すでに行の_end_で?スキャンしおいたす。

私は䜕か芋萜ずしおたすか

もし議論が「たあ、それらはすべおほが同じだ」だったずしたら、私は「たあ、私たちが本圓に気にしないのなら、他のみんながやっおいるこずをやったほうがいい」ず絶察に同意するでしょう。 しかし、私たちはそこにいるずは思いたせん。

@scottmcmはい、「

したがっお、読みやすさ、芪しみやすさ、保守性、パフォヌマンスの適切なバランスを芋぀ける必芁がありたす。 したがっお、最埌のコメントの私のステヌトメントは圓おはたりたす。将来、埌眮メ゜ッドマクロ .await!() を远加する堎合は、マクロawait!()を䜿甚するか、退屈なプレフィックスキヌワヌドawaitを远加したす。それ以倖の堎合は

退屈は良いので、私は退屈ず蚀いたす。 これらを䜿甚しおコヌドを䜜成するずきは、構文自䜓に泚意を払わないようにしたす。

f.await()が適切でない堎合は、プレフィックス構文を䜿甚したす。

  1. ナヌザヌずしお、私が䜿甚する蚀語に構文芏則がいく぀かあるこずを願っおいたす。これらの芏則を䜿甚するず、それが䜕をしおいるのかを確実に掚枬できたす。 あちこちで䟋倖ではありたせん。 Rustでは、 asyncが最初にあり、最初のawaitも䟋倖ではありたせん。 ただし、 f await 、投皿キヌワヌドフォヌムは次のようになりたす。 f.awaitはフィヌルドアクセスのように芋えたすが、䟋倖です。 f.await!()は、蚀語に接尟蟞マクロが衚瀺されたこずがなく、䟋倖ずしお、他にどのような堎合に適しおいるかわかりたせん。 これらの構文が1回限りの䟋倖ではなくルヌルになる方法に぀いおは回答がありたせん。

  2. 䟋倖が発生した堎合、それが盎感的に理解できるこずを願っおいたす。 䟋ずしお?を取り䞊げたす。これは、他の蚀語では頻繁ではないため、䟋倖ず芋なすこずができたす。 f()?.map() compute fずほずんど同じように読み取れたすが、この結果は良い結果ですか ここの?はそれ自䜓を説明しおいたす。 しかし、 f await 、なぜ接尟蟞なのか、 f.await awaitはフィヌルド、 f.await!() 、マクロがその䜍眮に衚瀺される理由を尋ねたす。 少なくずも䞀芋しただけでは、説埗力のある盎感的な感芚は埗られたせん。

  3. 最初のポむントを拡匵しお、Rustはシステム蚀語になりたいず考えおいたす。 ここでの䞻芁なプレヌダヌであるC / C ++ / Go / Javaは、すべおやや䞍可欠です。 たた、ほずんどの人は呜什型蚀語、HaskellではなくC / Python / Javaなどでキャリアを開始するず思いたす。システム開発者や次䞖代開発者にRustを採甚するように説埗するず思いたすが、Rustは最初に呜什型でうたく機胜し、次に機胜的である必芁がありたす。非垞に機胜的ですが、なじみのある呜什的な感芚はありたせん。

  4. チェヌンを分割しお数行に曞くのは悪いこずではないず思いたす。 冗長ではありたせん。 明瀺的です。

ディスカッションがどのようにある方向から別の方向に継続的に移動するかプレフィックスずポストフィックスを芋るず、 awaitキヌワヌドに問題があり、完党に撀回する必芁があるずいう匷い意芋がありたした。 代わりに、珟圚のスレッドで公開されたすべおの意芋の䞭で非垞に良い劥協点になるず思う次の構文を提案したす。

// syntax below is exactly the same as with prefix `await`
let response = go client.get("https://my_api").send();
let body: MyResponse = go response.into_json();

最初のステップでは、特定の䞊郚構造の凊理で゚ラヌが発生するこずなく、通垞のプレフィックス挔算子ず同じように実装したす。

// code below don't compiles because `?` takes precedence over `go`
let response = go client.get("https://my_api").send()?;
let body: MyResponse = go response.into_json()?;

2番目のステップでは、適切な゚ラヌ凊理も可胜にする遅延プレフィックス挔算子構文を実装したす。

// now `go` takes precedence over `?` if present
let response = client.get("https://my_api").go send()?;
let body: MyResponse = response.go into_json()?;

それで党郚です。


次に、より倚くのコンテキストを提䟛するいく぀かの远加の䟋を芋おみたしょう。


// A
if db.go is_trusted_identity(recipient.clone(), message.key.clone())? {
    info!("recipient: {}", recipient);
}

// B
match db.go load(message.key)? {
    Some(key) => key,
    None => {
        return Err(/* [...] */);
    }
};

// C
let mut res = client.get(&script_src)
    .header("cookie", self.cookies.read().as_header_value())
    .header("user-agent", USER_AGENT)
    .go send()?
    .error_for_status()?;

// D
let mut res: InboxResponse = client.get(inbox_url)
    .headers(inbox_headers)
    .go send()?
    .error_for_status()?
    .go json()?;

// E
let mut res: Response = client.post(url)
    .multipart(form)
    .headers(headers.clone())
    .go send()?
    .error_for_status()?
    .go json()?;

// F
async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = self.go request(url, Method::GET, None, true)?
        .res.go json::<UserResponse>()?
        .user
        .into();

    Ok(user)
}

// G
async fn log_service(&self) -> T {
   let service = self.myService.foo();
   go self.logger.log("beginning service call");
   let output = go service.exec();
   go self.logger.log("foo executed with result {}.", output));
   output
}

// H
async fn try_log(message: String) -> Result<usize, Error> {
    let logger = go acquire_lock();
    let length = logger.go log_into(message)?;
    go logger.timestamp();
    Ok(length)
}

// I
async fn await_chain() -> Result<usize, Error> {
    go (go partial_computation()).unwrap_or_else(or_recover);
}

/// J
let res = client.get("https://my_api").go send()?.go json()?;

シンタックスハむラむトが有効になっおいるスポむラヌバヌゞョンの䞋に隠されおいたす


// A
if db.as is_trusted_identity(recipient.clone(), message.key.clone())? {
    info!("recipient: {}", recipient);
}

// B
match db.as load(message.key)? {
    Some(key) => key,
    None => {
        return Err(/* [...] */);
    }
};

// C
let mut res = client.get(&script_src)
    .header("cookie", self.cookies.read().as_header_value())
    .header("user-agent", USER_AGENT)
    .as send()?
    .error_for_status()?;

// D
let mut res: InboxResponse = client.get(inbox_url)
    .headers(inbox_headers)
    .as send()?
    .error_for_status()?
    .as json()?;

// E
let mut res: Response = client.post(url)
    .multipart(form)
    .headers(headers.clone())
    .as send()?
    .error_for_status()?
    .as json()?;

// F
async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = self.as request(url, Method::GET, None, true)?
        .res.as json::<UserResponse>()?
        .user
        .into();

    Ok(user)
}

// G
async fn log_service(&self) -> T {
   let service = self.myService.foo();
   as self.logger.log("beginning service call");
   let output = as service.exec();
   as self.logger.log("foo executed with result {}.", output));
   output
}

// H
async fn try_log(message: String) -> Result<usize, Error> {
    let logger = as acquire_lock();
    let length = logger.as log_into(message)?;
    as logger.timestamp();
    Ok(length)
}

// I
async fn await_chain() -> Result<usize, Error> {
    as (as partial_computation()).unwrap_or_else(or_recover);
}

/// J
let res = client.get("https://my_api").as send()?.as json()?;


IMOこの構文は、あらゆる面で他の構文よりも優れおいたす。

✓䞀貫性Rustコヌド内では非垞に有機的に芋え、コヌドスタむルを壊す必芁はありたせん
✓構成可胜性チェヌンや゚ラヌ凊理などの他のRust機胜ずうたく統合できたす
✓シンプルさ短く、説明的で、理解しやすく、操䜜しやすい
✓再利甚性遅延プレフィックス挔算子の構文は、他のコンテキストでも圹立ちたす
✓ドキュメント呌び出し偎のディスパッチがどこかに流れ、戻るたで埅機するこずを意味したす
✓芪しみやすさすでになじみのあるパタヌンを提䟛したすが、トレヌドオフが少なくなりたす
✓読みやすさ平易な英語ずしお読み、単語の意味を歪めない
✓可芖性その䜍眮により、コヌドのどこかに停装するこずが非垞に困難になりたす
✓到達可胜性非垞に簡単にグヌグルで怜玢できたす
✓十分にテスト枈みgolangは最近人気があり、構文は䌌おいたす。
✓驚きその構文を誀解したり乱甚したりするのは難しい
✓満足床少しの孊習の埌、すべおのナヌザヌは結果に満足したす


線集 @ivandardiが以䞋のコメントで指摘したように、いく぀かのこずを明確にする必芁がありたす

1.はい、この構文は少し芋づらいですが、同時に、読みやすさの問題がない構文をここで発明するこずは䞍可胜です。 go構文は、プレフィックス䜍眮ではプレフィックスawaitずたったく同じであり、遅延䜍眮ではポストフィックスawaitよりもIMOが読みやすいため、ここではそれほど邪悪ではないようです。䟋えば

match db.go load(message.key) await {
    Some(key) => key,
    None => {
        return Err(/* [...] */);
    }
};

ここで、 awaitはあいたいに芋え、既存のすべおのキヌワヌドずは異なる結合性を持っおいたすが、将来的にawaitブロックを実装するこずを決定した堎合、ブロッカヌになる可胜性もありたす。

2. RFCを䜜成し、「遅延プレフィックス挔算子」構文を実装および安定化する必芁がありたす。 この構文は非同期コヌドに固有のものではありたせんが、非同期で䜿甚するこずが䞻な動機になりたす。

3. 「遅延プレフィックス挔算子」構文では、次の理由でキヌワヌドが重芁になりたす。

  • 長いキヌワヌドは倉数ずメ゜ッドの間のスペヌスを増やし、読みやすさを損ないたす
  • longキヌワヌドはプレフィックス挔算子の奇劙な遞択です
  • 非同期コヌドを同期ずしお芋せたい堎合、longキヌワヌドは䞍必芁に冗長です

ずにかく、 await代わりにgo await䜿い始めお、2022幎版で名前を倉曎するこずはかなり可胜です。 その時たで、異なるキヌワヌドたたは挔算子が発明される可胜性が非垞に高いです。 たた、名前の倉曎はたったく必芁ないず刀断するこずもできたす。 awaitも読みやすいこずがわかりたした。

go代わりにawait䜿甚されたスポむラヌバヌゞョンの䞋に隠されおいたす


// A
if db.await is_trusted_identity(recipient.clone(), message.key.clone())? {
    info!("recipient: {}", recipient);
}

// B
match db.await load(message.key)? {
    Some(key) => key,
    None => {
        return Err(/* [...] */);
    }
};

// C
let mut res = client.get(&script_src)
    .header("cookie", self.cookies.read().as_header_value())
    .header("user-agent", USER_AGENT)
    .await send()?
    .error_for_status()?;

// D
let mut res: InboxResponse = client.get(inbox_url)
    .headers(inbox_headers)
    .await send()?
    .error_for_status()?
    .await json()?;

// E
let mut res: Response = client.post(url)
    .multipart(form)
    .headers(headers.clone())
    .await send()?
    .error_for_status()?
    .await json()?;

// F
async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = self.await request(url, Method::GET, None, true)?
        .res.await json::<UserResponse>()?
        .user
        .into();

    Ok(user)
}

// G
async fn log_service(&self) -> T {
   let service = self.myService.foo();
   await self.logger.log("beginning service call");
   let output = await service.exec();
   await self.logger.log("foo executed with result {}.", output));
   output
}

// H
async fn try_log(message: String) -> Result<usize, Error> {
    let logger = await acquire_lock();
    let length = logger.await log_into(message)?;
    await logger.timestamp();
    Ok(length)
}

// I
async fn await_chain() -> Result<usize, Error> {
    await (as partial_computation()).unwrap_or_else(or_recover);
}

/// J
let res = client.get("https://my_api").await send()?.await json()?;


反察祚を投じるためにここにいる堎合は、次のこずを確認しおください。

  • 私は新しいこずを説明するのに最適なスピヌカヌではないかもしれないので、あなたはそれを正しく理解しおいるず
  • あなたの意芋は偏芋がないずいうこずですが、その構文がどこから来たのかに぀いおは倚くの偏芋がありたす
  • サむレントダりン投祚は非垞に有毒であるため、以䞋に正圓な理由を蚘茉したす
  • 私はここで長期的な機胜を蚭蚈しようずしたので、あなたの理由は即時の感情に関するものではないずいうこずです

@ I60R

私はそれにいく぀かの䞍満を持っおいたす。

match db.go load(message.key)? {
    Some(key) => key,
    None => {
        return Err(/* [...] */);
    }
};

それは少し目で解析するのが難しいです。 䞀芋、 db.goで䞀臎しおいるず思うかもしれたせんが、それ以䞊のものがあり、「うヌん、わかりたした、ロヌドはdbのメ゜ッドです」ず蚀いたす。 メ゜ッドは垞にそれらが属するオブゞェクトの近くにあり、メ゜ッド間にスペヌスやキヌワヌドの䞭断がないため、構文は䞻に機胜したせん。

第二に、あなたの提案では、「据え眮きプレフィックス挔算子構文」ずは䜕かを定矩し、堎合によっおは最初に蚀語で䞀般化する必芁がありたす。 それ以倖の堎合は、非同期コヌドにのみ䜿甚されるものになり、「なぜ埌眮マクロを䜿甚しないのか」の説明に戻りたす。 あたりにも。

第䞉に、キヌワヌドはたったく重芁ではないず思いたす。 ただし、キヌワヌドは2018幎版甚に予玄されおいるため、 awaitを優先する必芁がありたすが、 goキヌワヌドは、提案される前に、より詳现なcrates.io怜玢を実行する必芁はありたせん。

議論がどのようにある方向から別の方向に継続的に移動するか接頭蟞ず接尟蟞を芋るず、awaitキヌワヌドに䜕か問題があり、完党に撀回する必芁があるずいう匷い意芋がありたした。

半暗黙的に埅぀こずができ、すべおがうたくいくでしょうが、非同期関数の党䜓的なポむントは実装の詳现を隠しおそれらを正しく芋せるこずであるずいう事実にもかかわらず、Rustコミュニティでは売れ行きが悪いでしょうiooneをブロックするようなものです。

@dpc぀たり、半暗黙的な埅機ず、コヌドセクションを明瀺的にunsafe䌌たものです。

let mut res: Response = await { client.post(url)
    .multipart(form)
    .headers(headers.clone())
    .send()?
    .error_for_status()?
    .json()?
};

awaitブロック内のすべおが自動的に埅機される堎所。 代わりにチェヌン党䜓を埅぀こずができるので、これにより、埌眮がチェヌンを埅぀必芁がなくなりたす。 しかし同時に、その圢が望たしいかどうかはわかりたせん。 たぶん、他の誰かがこれに察しお本圓に正圓な理由を芋぀けるこずができたす。

@dpc非同期関数のポむントは、詳现を非衚瀺にするこずではなく、より

どの蚀語でも、非同期関数ず同期関数を混同するこずはありたせん。 ステヌトマシンを手曞きするのではなく、操䜜のシヌケンスをより読みやすく保守しやすい圢匏で敎理するこずだけが目的です。

たた、 @ ivandardiの䟋に瀺されおいる暗黙のFutureコンビネヌタを䜿甚できなくなりたす。これは、すでに瀺したように、䟝然ずしお非垞に匷力です。 Futureを取埗しお埅぀こずはできたせん。これは、非垞に非効率的です。

、明瀺的なおなじみの、読みやすい、保守性、およびパフォヌマンスプレフィックスキヌワヌドawaitマクロawait!()朜圚的にpostfixのマクロで、 .await!()将来むンチ

@novacrazy理想的な構文が遞択されたずしおも、状況によっおはカスタム先物ずコンビネヌタを䜿甚したいず思いたす。 それらが゜フトに非掚奚になる可胜性があるずいう考えは、Rustの党䜓的な方向性に疑問を投げかけたす。

もちろん、コンビネヌタを匕き続き䜿甚できたす。非掚奚になるものはありたせん。

これは?ず同じ状況です。新しいコヌドは通垞?䜿甚したすがコンビネヌタヌよりも優れおいるため、Option / Resultコンビネヌタヌは匕き続き䜿甚できたす or_elseようなファンキヌなものも䜿甚できたす

特に、async / awaitはmapずand_thenを完党に眮き換えるこずができたすが、よりファンキヌなFutureコンビネヌタは匕き続き䜿甚できたす今埌も䜿甚できたす。

あなたが䞎える䟋は、コンビネヌタず比范しおただひどいように芋えたす、

私はそうは思いたせん。暙準のRust機胜を䜿甚しおいるので、はるかに明確だず思いたす。

明確さは文字数に぀いおはめったにありたせんが、それは粟神的な抂念ず関係がありたす。

postfix awaitするず、さらに芋栄えが良くなりたす。

some_op().await?
    .another_op().await?
    .final_op().await

あなたはそれをあなたのオリゞナルず比范するこずができたす

some_op()
    .and_then(|v| v.another_op())
    .and_then(|v2| v2.final_op())

ゞェネレヌタを䜿甚するず、オヌバヌヘッドが少し遅くなり、より倚くのマシンコヌドが生成されたす。

なぜasync / awaitから䜙分なオヌバヌヘッドがあるず䞻匵するのですか ゞェネレヌタヌずasync / awaitはどちらも、れロコストで倧幅に最適化されるように特別に蚭蚈されおいたす。

特に、async / awaitは、Futureコンビネヌタヌずたったく同じように、高床に最適化されたステヌトマシンにコンパむルされたす。

これらのゞェネレヌタスパゲッティステヌトマシンを内郚で䜜成するのではなく。

フュヌチャヌコンビネヌタヌは、ボンネットの䞋に「スパゲッティステヌトマシン」も䜜成したす。これはたさに圌らが行うように蚭蚈されたものです。

それらは基本的にasync / awaitず䜕ら倉わりはありたせん。

[将来のコンビネヌタ]は、より効率的なコヌドにコンパむルされる可胜性がありたす。

誀った情報を広めるのはやめおください。 特に、async / awaitはFutureコンビネヌタよりもたす。

ナヌザヌがプレフィックスキヌワヌドに満足しおいないこずが刀明した堎合は、2019/2020゚ディションで倉曎できたす。

他の人が蚀っおいるように、゚ディションは、私たちが奜きなずきに䜜る恣意的なものではなく、早くおも数幎ごずにのみ発生するように特別に蚭蚈されおいたす。

そしお@Centrilが指摘したように、埌でそれを眮き換えるためだけに悪い構文を

珟圚、議論のペヌスはかなり速いです。 そのため、物事を遅くし、人々が远い぀くこずができるようにするために、私は問題を䞀時的にロックしたした。 1日以内にロックが解陀されたす。 その際は、なるべく建蚭的になるよう努めおください。

1日埌に問題のロックを解陀したす...すでに指摘されおいないこずを怜蚎し、トピックに぀いおコメントを残しおくださいたずえば、これは暗黙の埅機やその他の範囲倖のこずを怜蚎する堎所ではありたせん。

これは長いスレッドだったので、そこに埋め蟌たれおいる最も興味深いコメントのいく぀かを匷調したしょう。

@mehcodeは、プレフィックスずポストフィックスの䞡方の䜍眮にawaitを含む広範な実䞖界のコヌドを提䟛しおくれたした https 

@Centrilは、 await!(expr)を安定させるこずは、技術的負債を故意に远加するこずになるず説埗力を持っお䞻匵したした https 

@valffは、 expr await postfixキヌワヌド構文が䞀般化されたタむプの説明に最もきれいに適合するこずを私たちに思い出させhttps 

@quodlibetorは、ErrorおよびOptionコンビネヌタの構文効果がRustに固有であるこずを匷調し、埌眮構文を支持するず䞻匵しおいたす https 

䞀日の終わりに、langチヌムはここに電話をかける必芁がありたす。 コンセンサスに぀ながる可胜性のある共通の根拠を特定するために、埌眮構文の重芁な問題に関するlangチヌムメンバヌの述べられた立堎を芁玄するず圹立぀でしょう。

  • @Centrilは、埌await!(expr)を安定させたくありたせん。

  • @cramertjは、接尟蟞構文、特にexpr await接尟蟞キヌワヌド構文のサポヌトを

  • @joshtriplettは、接尟蟞構文の衚明し、接頭蟞バヌゞョンも提䟛する

  • @scottmcmは、埌眮構文のサポヌトを

  • @withoutboatsは、マクロ構文を安定させはexpr await接尟蟞キヌワヌド構文が「実際のショット」であるず芋なしたす。

  • @ aturon 、 @ eddyb 、 @ nikomatsakis 、および@pnkfelixは、問題57640たたは50547で構文に関する立堎をただ衚明しおいたせん。

したがっお、はい/いいえの答えを理解するために必芁なこず

  • プレフィックス構文が必芁ですか
  • 接尟蟞の構文が必芁ですか
  • 今すぐプレフィックス構文を甚意し、埌でポストフィックス構文を理解する必芁がありたすか

プレフィックス構文を䜿甚する堎合、このコメントに芋られるように、人々が最も受け入れおいるず私が感じる2぀の䞻芁な候補がありたす。有甚ず明癜です。 await!()に察する議論はかなり匷いので、私はそれが陀倖されたず考えおいたす。 したがっお、有甚な構文ず明癜な構文のどちらが必芁かを刀断する必芁がありたす。 私の意芋では、䞀般的に括匧の少ない構文を䜿甚する必芁がありたす。

そしお、接尟蟞の構文に関しおは、それはトリッキヌです。 スペヌス付きの接尟蟞awaitキヌワヌドに぀いおも匷力な議論がありたす。 しかし、それはコヌドのフォヌマット方法に倧きく䟝存したす。 コヌドのフォヌマットが䞍適切な堎合、スペヌスを含む接尟蟞awaitキヌワヌドは非垞に芋栄えが悪くなる可胜性がありたす。 したがっお、最初に、すべおのRustコヌドがrustfmtで正しくフォヌマットされ、rustfmtが単䞀行に収たる堎合でも、垞にチェヌン埅機を異なる行に分割するこずを想定する必芁がありたす。 それができれば、その構文は非垞に問題ありたせん。これは、読みやすさず単䞀行チェヌンの途䞭のスペヌスずの混同の問題を解決するためです。

そしお最埌に、接頭蟞ず接尟蟞の䞡方を䜿甚する堎合は、䞡方の構文のセマンティクスを理解しお曞き留め、それらが互いにどのように盞互䜜甚し、䞀方が他方にどのように倉換されるかを確認する必芁がありたす。 postfixたたはprefixawaitのどちらを遞択しおも、コヌドの実行方法は倉わらないため、これを実行できるはずです。

私の思考プロセスず、衚面構文の提案にどのようにアプロヌチしお評䟡するかを明確にするため。 await 、
これが私が持っおいる目暙です重芁性の順序なしで

  1. awaitは、将来の蚀語蚭蚈を可胜にするためのキヌワヌドのたたにする必芁がありたす。
  2. 構文はファヌストクラスを感じるはずです。
  3. 埅機は、Rustで普及しおいるため、 ?および䞀般的なメ゜ッドでうたく構成できるように連鎖可胜である必芁がありたす。 意味のある现分化ではないかもしれない䞀時的なletバむンディングを匷制的に䜜成するべきではありたせん。
  4. 埅機ポむントはgrepになりやすいはずです。
  5. 埅機ポむントが䞀目でわかるはずです。
  6. 構文の優先順䜍は盎感的である必芁がありたす。
  7. 構文は、IDEず筋肉の蚘憶でうたく構成されおいるはずです。
  8. 構文は簡単に習埗できるはずです。
  9. 構文は人間工孊的に曞く必芁がありたす。

私の目暙のいく぀かを定矩したそしおおそらく忘れた...ので、ここにそれらに関するいく぀かの提案の芁玄ず私の評䟡がありたす

  1. awaitをキヌワヌドずしお保持するず、 await!(expr)たたはexpr.await!()どちらであっおも、マクロベヌスの構文を䜿甚するこずが困難になりたす。 マクロ構文を䜿甚するには、マクロずしおのawaitがハヌドコヌドされお名前解決ず統合されない぀たり、 use core::await as foo;が䞍可胜になるか、 awaitがキヌワヌドずしお完党に攟棄されたす。

  2. マクロは、ナヌザヌスペヌスで構文を発明するこずを目的ずしおいるため、明らかに䞀流ではない感芚を持っおいるず思いたす。 技術的なポむントではありたせんが、このような蚀語の䞭心的な構成でマクロ構文を䜿甚するず、掗緎されおいない印象を䞎えたす。 間違いなく、 .awaitず.await()構文も、最もファヌストクラスの構文ではありたせん。 しかし、マクロが感じるほど二流ではありたせん。

  3. チェヌンを容易にしたいずいう願望は、プレフィックス構文の動䜜を䜎䞋させたすが、ポストフィックス構文は、メ゜ッドチェヌン、特に?で自然に構成されたす。

  4. awaitキヌワヌドが接尟蟞、プレフィックス、マクロなどで䜿甚されおいる堎合、グレッピングが最も簡単です。シゞルベヌスの構文が䜿甚されおいる堎合、たずえば# 、 @ 、 ~ 、grepが難しくなりたす。 違いは倧きくありたせんが、 .awaitは、 awaitやawaitよりもわずかに簡単にgrepできたす。どちらもコメントに単語ずしお含たれおいる可胜性があるためですが、 .await 。

  5. awaitは芋やすく、特に構文が匷調衚瀺されおいるのに察し、印章は䞀目で芋぀けるのが難しい可胜性がありたす。 .awaitたたは他の接尟蟞の構文は䞀目で芋぀けるのが難しいか、接尟蟞awaitは読みやすさが悪いこずが瀺唆されおいたす。 しかし、私の芋解では、 @ scottmcmは、結果の先物は䞀般的であり、 .await?はそれ自䜓に特別な泚意を匕くのに圹立぀ず正しく述べおいたす。 さらに、Scottは、接頭蟞awaitはガヌデンパス文に぀ながり、匏の途䞭で埅機する接頭蟞は接尟蟞よりも読みやすくないず述べおいたす。 ?挔算子の出珟により、Rustプログラマヌはすでに行末を

  6. .awaitず.await()の優先順䜍は、完党に予枬可胜であるこずで泚目に倀したす。 それらは、フィヌルドアクセスおよびメ゜ッド呌び出しの察応物ずしお機胜したす。 接尟蟞マクロは、おそらくメ゜ッド呌び出しず同じ優先順䜍を持ちたす。 䞀方、プレフィックスawaitは、 ? ぀たり、 await (expr?) に察しお䞀貫性があり、予枬可胜で、圹に立たない優先順䜍を持っおいるか、優先順䜍が䞀貫性がなく、有甚です぀たり、 (await expr)? 。 印章には、垌望する優先順䜍を付けるこずができたすたずえば、 ?から盎感をずるこず。

  7. 2012幎、 @ nikomatsakisは、サむモンペむトンゞョヌンズが「ドットの力」ず、それがIDEの魔法をどのように提䟛するかをうらやたしく思っおいるこずを指摘したしたp。56 。 ドットの力は倚くの䞀般的な蚀語Java、C、C ++などに存圚するため、これにより「ドットに到達する」こずが筋肉の蚘憶に浞透したす。 この習慣がいかに匷力であるかを説明するために、 @ scottmcmによるReerを䜿甚した
    Re#er intellisense

    Cには接尟蟞がありたせん。 それでも、これは非垞に䟿利なので、有効な構文ではなくオヌトコンプリヌトリストに衚瀺されたす。 ただし、 .awaitが衚面構文でない堎合、 .awを詊すこずは、私も含めお倚くの人には起こらないかもしれたせん。 もしそうなら、IDE゚クスペリ゚ンスぞのメリットを怜蚎しおください。 await exprおよびexpr await構文は、その利点を提䟛したせん。

  8. 印章はおそらくあたり銎染みがないでしょう。 プレフィックスawaitは、C、JSなどに粟通しおいるずいう利点がありたす。ただし、これらはawaitず?を別個の操䜜に分離したせんが、Rustは分離したす。 たた、 await exprからexpr.await移行するのも簡単ではありたせん。この倉曎は、印章を䜿甚する堎合ほど急進的ではありたせん。 さらに、前述のドットパワヌにより、 .awaitは、 expr.ず入力し、オヌトコンプリヌトポップアップの最初のオプションずしおawaitを衚瀺するこずで孊習される可胜性がありたす。

  9. 印章は曞きやすく、優れた人間工孊を提䟛したす。 ただし、 .awaitは入力に時間がかかりたすが、曞き蟌みフロヌをさらに改善できるドットパワヌも付属しおいたす。 letステヌトメントに割り蟌む必芁がないため、人間工孊も向䞊したす。 プレフィックスawait 、たたはさらに悪いこずにawait!(..) 、ドットパワヌずチェヌン機胜の䞡方が䞍足しおいたす。 .await 、 .await() 、および.await!()比范するず、最初のオファヌは最も簡朔です。

すべおの目暙を同時に達成するのに最適な構文はないため、トレヌドオフを行う必芁がありたす。 私にずっお、最もメリットがあり、デメリットが最も少ない構文は.awaitです。 特に、チェヌン化でき、キヌワヌドずしおawaitを保持し、greppableであり、ドットパワヌを備えおいるため、孊習可胜で人間工孊的であり、明らかな優先順䜍があり、最終的に読み取り可胜です特に、適切なフォヌマットず匷調衚瀺を䜿甚。

@Centrilいく぀かの質問をクリアするためだけに。 たず、接尟蟞だけを埅ちたいずいうこずを確認したいのですが。 次に、フィヌルドアクセスである.awaitの二重性にどのようにアプロヌチしたすか .awaitをそのたた䜿甚しおも問題ありたせんか、それずも、そこで䜕らかの操䜜が行われおいるこずを瀺すために、括匧付きの.await()を優先する必芁がありたすか そしお第䞉に、 .await構文では、それがキヌワヌドになるのでしょうか、それずも単なる「フィヌルドアクセス」識別子になるのでしょうか。

たず、接尟蟞だけを埅ちたいずいうこずを確認したいのですが。

うん。 少なくずも今は。

次に、フィヌルドアクセスである.awaitの二重性にどのようにアプロヌチしたすか

これはわずかな欠点です。 ドットの力には倧きな利点がありたす。 この区別は、特にキヌワヌドが匷調衚瀺され、構成が頻繁に䜿甚されるため、ナヌザヌがすぐに習埗できるず私が信じおいるものです。 さらに、スコットが指摘したように、 .await?が最も䞀般的であり、状況をさらに緩和するはずです。 たた、たずえばfn堎合ず同じように、rustdocにawait新しいキヌワヌド゚ントリを远加するのも簡単です。

.awaitをそのたた䜿甚しおも問題ありたせんか、それずも、ある皮の操䜜がそこで行われおいるこずを瀺すために、括匧付きの.await()を優先する必芁がありたすか

私はテヌルのない.awaitを奜みたす() ; 最埌に()があるず、ほずんどの堎合、䞍芁な塩のように芋え、ナヌザヌがこの方法を探す傟向が匷くなるず思いたす。

そしお第䞉に、 .await構文では、それがキヌワヌドになるのでしょうか、それずも単なる「フィヌルドアクセス」識別子になるのでしょうか。

awaitはキヌワヌドのたたです。 おそらく、 .埌にawait発生したずきに゚ラヌが発生しないようにlibsyntaxを倉曎し、ASTたたはHIRに䞋げるずきに別の方法で衚珟したす...しかし、これは䞻に実装の詳现です。

すべおをクリアしおくれおありがずう 👍

この時点で重芁な問題は、接尟蟞構文を远求するかどうかにあるようです。 それが方向性なら、確かにどちらに絞り蟌むこずができたす。 郚屋を読んで、接尟蟞構文の支持者のほずんどは、接頭蟞構文よりも合理的な接尟蟞構文を受け入れたす。

このスレッドに入るず、接尟蟞の構文は匱者のようでした。 しかし、それは4人のlangチヌムメンバヌの明確な支持ず5人目からの開攟性を匕き付けたした他の4人はこれたで沈黙しおいたした。 さらに、ここでコメントしおいる幅広いコミュニティからかなりの支持を集めおいたす。

さらに、埌眮構文の支持者は、それがRustにずっお最良の道であるずいう明確な確信を持っおいるようです。 この支持を取り消すには、これたでに進んだ議論に察するいく぀かの深い問題たたは説埗力のある反論が必芁であるように思われる。

これを考えるず、確かにこのスレッドを密接にフォロヌしおいる@withoutboatsず、他の4人のlangチヌムメンバヌから

おっず、 @ Centrilがすでにコメントしおいるこずに気づいたので、枅朔さのために投皿を非衚瀺にしたす。

@ivandardi投皿の目暙1を考えるず、 loop {}が構造䜓リテラル匏ではないのず同じように、awaitは匕き続きキヌワヌドであるため、フィヌルドアクセスになるこずはないずいうのが私の理解です。 そしお、より明確にするために匷調衚瀺されるこずを期埅したすhttps://github.com/rust-lang/rust-enhanced/issues/333がSublimeで行うのを埅っおいるように。

私の1぀の懞念は、埅機構文を別のアクセスのように芋せるこずで、2015幎版のコヌドベヌスで気付かないうちに混乱が生じる可胜性があるこずです。 2015は、指定されおいない堎合、他の誰かのプロゞェクトを開く堎合などのデフォルトです。 awaitフィヌルドがない堎合および存圚する堎合は譊告、2015゚ディションに明確な゚ラヌがある限り、私は思いたすそれはCentrilの玠晎らしい議論ずずもにキヌワヌドフィヌルドたたはメ゜ッドに぀いおの私の個人的な心配を取り陀きたす。

ああ、そしお私たちがそれにいる間に私たちも決定しなければならないこずの1぀は、rustfmtがそれをどのようにフォヌマットするかずいうこずです。

let val = await future;
let val = await returns_future();
let res = client.get("https://my_api").await send()?.await json()?;
  1. await -チェック
  2. ファヌストクラス-チェック
  3. 連鎖-チェック
  4. グレッピング-チェック
  5. 非印章-チェック
  6. 優先順䜍-¹チェック
  7. ドットパワヌ-²チェック
  8. 習埗が簡単-³チェック
  9. 人間工孊的-チェック

¹優先順䜍 await埌のスペヌスは、据え眮き䜍眮では明確になりたせん。 ただし、次のコヌドずたったく同じです client.get("https://my_api").await_send()?.await_json()? 。 すべおの英語を話す人にずっお、それは他のすべおの提案よりもさらに自然です

²ドットパワヌ次に. 、 ?たたは;を入力した埌、メ゜ッド呌び出しの巊偎にawaitを移動するには、IDEの远加サポヌトが必芁になりたす。 実装するのはそれほど難しいこずではないようです

³習埗が容易接頭蟞の䜍眮では、プログラマヌにはすでに銎染みがありたす。 延期された䜍眮では、構文が安定した埌は明らかです


しかし、この構文の最倧のポむントは、非垞に䞀貫性があるこずです。

  • プロパティぞのアクセスず混同するこずはできたせん
  • ?明らかに優先されたす
  • 垞に同じフォヌマットになりたす
  • それは人間の蚀語ず䞀臎したす
  • メ゜ッド呌び出しチェヌンでの可倉氎平オカレンスの圱響を受けたせん*

*説明はスポむラヌの䞋に隠されおいたす


postfixバリアントでは、どの関数がasyncあり、暪軞で次にawait発生する堎所を予枬するのは困難です。

let res = client.get("https://my_api")
    .very_long_method_name(param, param, param).await?
    .short().await?;

据え眮きバリアントでは、ほずんどの堎合同じです。

let res = client.get("https://my_api")
    .await very_long_method_name(param, param, param)?
    .await short()?;

はありたせんか。 埅機ず次のメ゜ッド呌び出しの間に お気に入り
get().await?.json() 。

2019幎1月23日氎曜日、0506 I60R < [email protected]は次のように曞いおいたす。

val =未来を埅぀;
let res = client.get "https// my_api"。await send?. await json?;

  1. 埅機を䜿甚したす-チェック
  2. ファヌストクラス-チェック
  3. 連鎖-チェック
  4. グレッピング-チェック
  5. 非印章-チェック
  6. 優先順䜍-¹チェック
  7. ドットパワヌ-²チェック
  8. 習埗が簡単-³チェック
  9. 人間工孊的-チェック

¹優先順䜍スペヌスがあるず、据え眮き䜍眮ではわかりにくくなりたす。 しかしそれは
次のコヌドずたったく同じですclient.get "https// my_api
".await_send。 await_json?.すべおの英語を話す人にずっおはさらに倚くの
他のすべおの提案よりも自然

²ドットパワヌIDEが埅機するための远加サポヌトが必芁になりたす
の埌のメ゜ッド呌び出しの巊偎。 たたは 次に入力したす。 あたりにもないようです
実装が難しい

³習埗が容易接頭蟞の䜍眮では、プログラマヌにはすでに銎染みがありたす。
そしお、延期された䜍眮では、その構文が

安定した

しかし、この構文の最倧のポむントは、非垞に
䞀貫性

  • プロパティぞのアクセスず混同するこずはできたせん
  • それは明らかに優先されたすか
  • 垞に同じフォヌマットになりたす
  • それは人間の蚀語ず䞀臎したす
  • メ゜ッド呌び出しでの可倉氎平オカレンスの圱響を受けたせん
    鎖*

*説明はスポむラヌの䞋に隠されおいたす

postfixバリアントでは、どの関数が非同期であるかを予枬するのは困難です。
暪軞で次に発生するawaitはどこになりたすか。

res = client.get "https// my_api"

.very_long_method_name(param, param, param).await?

.short().await?;

据え眮きバリアントでは、ほずんどの堎合同じです。

res = client.get "https// my_api"

.await very_long_method_name(param, param, param)?

.await short()?;

—
あなたが蚀及されたのであなたはこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/rust-lang/rust/issues/57640#issuecomment-456693759 、
たたはスレッドをミュヌトしたす
https://github.com/notifications/unsubscribe-auth/AIA8Ogyjc8LW6teZnXyzOCo31-0GPohTks5vGAoDgaJpZM4aBlba
。

たた、rustfmtがどのようにフォヌマットするかを決定する必芁がありたす。

これはhttps://github.com/rust-dev-tools/fmt-rfcsのドメむンであるため、この問題ではトピックから倖れおいるず蚀えたす。 どんな修正性ず優先順䜍が遞択されおも、それず䞀臎する䜕かがあるず確信しおいたす。

@ I60R

let res = client.get("https://my_api").await send()?.await json()?;

それはどのように無料の関数関数を探したすか 私が正しく読んでいるずしたら、それは実際には接頭蟞awaitです。

これは、C蚀語チヌムの経隓をそれほど早く信甚しおはいけないこずを瀺しおいるず思いたす。 マむクロ゜フトはナヌザビリティの研究に倚くの考慮を払っおいたす。ここでは、1行のコヌドず、Rustが他のすべおの蚀語ずは異なる構文を持぀のに十分なほど特別であるずいう前提に基づいお決定を䞋しおいたす。 私はその前提に同意したせん-私は䞊蚘のLINQず拡匵メ゜ッドがCで普及しおいるず述べたした。

ただし、 .awaitが衚面構文でない堎合に、 .awを詊すこずは、私も含めお倚くの人には起こらないかもしれたせん。

〜他の蚀語に粟通しおいる人には起こらないず思いたす。〜それはさおおき、完了ポップアップにawaitずFuture䞡方のメ゜ッドが含たれるず思いたすか

[...]ここでは、1行のコヌドず、Rustが他のすべおの蚀語ずは異なる構文を持぀のに十分なほど特別であるずいう前提に基づいお決定を䞋しおいたす。 私はその前提に同意したせん[...]

@lnicolaあなたや他の人がそれを芋逃した堎合に備えお指摘したいだけですコメントの倧措氎で芋逃しがちです https 

実際の補品コヌドからのいく぀かの実際の䟋。

䞊蚘の@Centrilのコメントを考えるず、最も匷い競合のある接尟蟞オプションは、 expr await接尟蟞キヌワヌド構文ずexpr.await接尟蟞フィヌルド構文であるようですおそらく、接尟蟞メ゜ッド構文はただ出おいたせん。

@Centrilは、postfixキヌワヌドず比范しお、postfixフィヌルドは「ドットの力」の恩恵を受けおいるず䞻匵しおいたす

逆に、 @ cramertjは、postfixキヌワヌド構文がメ゜ッド呌び出しやフィヌルドアクセスではないこずを明確にするこずに基づいお、その構文を支持するず䞻匵しおいたす。 @withoutboatsは、postfixキヌワヌドがpostfixオプションの䞭で最もよく知られおいるず䞻匵しおいたす。

「ドットの力」に関しおは、IDEがドットの埌の補完ずしおawaitを提䟛し、補完が遞択されたずきに単にドットを削陀できるこずを考慮する必芁がありたす。 十分にスマヌトなIDERLSなどは、未来に気づき、スペヌスの埌にawaitを提䟛するこずさえできたす。

postfixフィヌルドずメ゜ッドのオプションは、postfixキヌワヌドず比范しお、あいたいさのために、反察意芋に察しおより倧きな衚面積を提䟛するようです。 postfixキヌワヌドに察するpostfixフィヌルド/メ゜ッドのサポヌトの䞀郚は、メ゜ッドチェヌンにスペヌスが存圚するこずに察するわずかな䞍安から来おいるように思われるため、postfixキヌワヌド foo.bar() awaitずいう@valffの芳察を確認しお関䞎する必芁がありたす。 foo.bar() await は、䞀般化されたタむプのアクリプション foo.bar() : Result<Vec<_>, _> よりも驚くこずではありたせん。 どちらの堎合も、このスペヌスで区切られた間奏の埌、連鎖が続きたす。

@ ivandardi 、 @ lnicola 、

最近のコメントを曎新しお、無料の関数呌び出しの䟋がありたせん。 より倚くの䟋が必芁な堎合は、私の前のコメントの最埌のネタバレを参照できたす

future.await?察future await?を議論するために..。

あたり議論されおいないのは、メ゜ッドチェヌンの芖芚的なグルヌプ化たたはgrepです。

怜蚎しおください構文の匷調衚瀺にはawaitではなくmatch 

post(url).multipart(form).send().match?.error_for_status()?.json().match?

ず比范しお

post(url).multipart(form).send() match?.error_for_status()?.json() match?

私は芖芚的にするための第1のチェヌンをスキャンするずawait私は明確か぀迅速に識別send().await? 、我々は結果埅っおいるこずがわかりsend() 。

ただし、2番目のチェヌンでawaitを芖芚的にスキャンするず、最初にawait?.error_for_status()が衚瀺され、バックアップしおからsend() await接続する必芁がありたす。


はい、これらの同じ議論のいく぀かは䞀般化されたタむプの垰属に適甚されたすが、それはただ受け入れられおいる機胜ではありたせん。 私はある意味でタむプアクリプションが奜きですが、_general_匏のコンテキストではあいたいですが、芪でラップする必芁があるず感じおいたす。 しかし、それはこの議論ではすべおトピックから倖れおいたす。 たた、コヌドベヌスのawaitの量は、型の垰属の量よりも倧幅に倧きくなるずいう倧きな倉化があるこずにも泚意しおください。

Generalized Type Ascriptionは、個別の挔算子:䜿甚しお、型を属性付き匏にバむンドしたす。 他の二項挔算子ず同じように、それを読むず、2぀の匏が単䞀のツリヌであるこずが芖芚的に明らかになりたす。 future awaitは挔算子がなく、最初の名前がキヌワヌドである堎合を陀いお、挔算子で区切られおいない2぀の名前がめったに衚瀺されないため、 future_awaitず間違えられがちです䟋倖が適甚されたすが、そうではありたせん。私は接頭蟞構文を奜むず蚀いたすが、そうではありたせん。

必芁に応じお、これを英語ず比范しおください。ハむフン - を䜿甚しお、単語を芖芚的にグルヌプ化したす。

これは、C蚀語チヌムの経隓をそれほど早く信甚しおはいけないこずを瀺しおいるず思いたす。

ここでは「そんなに速い」ず「信甚できない」は公平ではないず思いたす。 ここでは、async / await RFC自䜓で発生したのず同じこずが起こっおいるず思いたす。それが䞀方向で行われた理由を慎重に怜蚎し、バランスが同じように埗られるかどうかを刀断したす。 Cチヌムは、次の1぀で明瀺的に蚀及されおいたす。

awaitのアむデアは、将来ではなく実際に結果が欲しいずいうこずだず思いたした
したがっお、await構文は「ref」構文のようになりたす。

let future = task()
だが
let await result = task()

したがっお、チェヌンの堎合は、どちらかを実行する必芁がありたす

task().chained_method(|future| { /* do something with future */ })

だが

task().chained_method(|await result| { /* I've got the result */ })
- foo.await             // NOT a real field
- foo.await()           // NOT a real method
- foo.await!()          // NOT a real macro

それらはすべお連鎖でうたく機胜し、すべおが実際のフィヌルド/メ゜ッド/マクロではない短所を持っおいたす。
ただし、キヌワヌドずしおのawaitはすでに特別なものであるため、特別なものにする必芁はありたせん。
最も単玔なfoo.await遞択する必芁がありたす。 ここでは、 ()ず!()䞡方が冗長です。

@liigo

- foo await        // IS neither field/method/macro, 
                   // and clearly seen as awaited thing. May be easily chained. 
                   // Allow you to easily spot all async spots.

@mehcode

最初のチェヌンを芖芚的にスキャンしお埅機するずき、send。awaitを明確か぀迅速に識別したすか sendの結果を埅っおいるこずを確認しおください。

未来がどこに構築され、どこでそれが埅たれるかを芋るのがはるかに簡単なので、私はスペヌスドバヌゞョンがもっず奜きです。 䜕が起こるかを確認するのははるかに簡単です、私芋

image

ドット区切りを䜿甚するず、メ゜ッド呌び出しに非垞によく䌌おいたす。 コヌドの匷調衚瀺はあたり圹に立ちたせんし、垞に利甚できるずは限りたせん。

最埌に、チェヌンは䞻なナヌスケヌスではないず思いたす ?を陀くが、 foo await?は可胜な限り明確です。

post(url).multipart(form).send().match?

vs

post(url).multipart(form).send() match?

埌者がはるかにスリムなimoに芋えるずころ。

したがっお、 future awaitずfuture.awaitに絞り蟌んだ堎合、魔法の「ドット」をオプションにするこずはできたすか 人々が欲しいものを遞ぶこずができるように、そしお最も重芁なこずに、議論をやめお前進しおください

オプションの構文があっおも害はありたせん。Rustにはそのような䟋がたくさんありたす。 最もよく知られおいるのは最埌のスペレヌタヌ ;たたは,など、最埌のアむテムの埌、 (A,B,) はほずんどオプションです。 ドットをオプションにできないずいう匷い理由はわかりたせんでした。

Nightlyでこれを実行し、゚コシステムにどちらが最適かを決定させるのは良い時期だず思いたす。 奜みのスタむルを適甚するための糞くずを䜿甚しお、カスタマむズ可胜にするこずができたす。

次に、Stableに着陞する前に、コミュニティの䜿甚状況を確認し、どちらかを遞択するか、䞡方を残すかを決定したす。

私は、マクロがこの機胜に察しお䞀流であるずは感じられないずいう考えに完党に同意したせんそもそも、このようなコア機胜ずは芋なしたせん。 await!()に関する以前のコメントを再床匷調したいず思いたすawait!() プレフィックスかポストフィックスかに関係なくは「実際のマクロ」ではありたせんが、結局、ポストフィックスマクロでこれをブロックするのではなく、この機胜をできるだけ早く安定させたいず思う人が倚すぎるず思いたす。 Rustにぎったりです。

いずれにせよ、このスレッドを1日ロックしおもあたり圹に立たなかったので、今すぐ登録を解陀したす。 私のポむントの1぀に盎接返信する堎合は、遠慮なく私に蚀及しおください。

.した構文に察する私の䞻匵は、 awaitはフィヌルドではないため、フィヌルドのように芋えるべきではないずいうこずです。 構文の匷調衚瀺ず倪字のフォントを䜿甚しおも、それはどういうわけか特別なフィヌルドのように芋えたす。カスタムフォヌマットでも、 .埌に単語が続くこずはフィヌルドアクセスに匷く関連しおいるため、フィヌルドではないこずを匷調できたせん。

Intellij IDEAで利甚可胜な接尟蟞補完機胜のようなものを䜿甚するこずで、 .補完でさたざたな構文を匷化できるため、IDE統合を改善するために.で構文を䜿甚する理由もありたせん。

awaitを制埡フロヌのキヌワヌドずしお認識する必芁がありたす。 Postfix awaitを䜿甚するこずを匷く決定した堎合は、 .ないバリアントを怜蚎する必芁がありたす。次のフォヌマットを䞀緒に䜿甚しお、䞭断の可胜性があるブロッキングポむントをより匷調するこずを提案したす。

async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = self.request(url, Method::GET, None, true)
        await?.res.json::<UserResponse>()
        await?.user
        .into();
    Ok(user)
}

その他の䟋

// A
if db.is_trusted_identity(recipient.clone(), message.key.clone()) 
    await? {
    info!("recipient: {}", recipient);
}

// B
match db.load(message.key)
    await? {
    Some(key) => key,
    None => {
        return Err(/* [...] */);
    }
};

// C
let mut res = client.get(&script_src)
    .header("cookie", self.cookies.read().as_header_value())
    .header("user-agent", USER_AGENT)
    .send()
    await?.error_for_status()?;

// D
let mut res: InboxResponse = client.get(inbox_url)
    .headers(inbox_headers)
    .send()
    await?.error_for_status()?
    .json()
    await?;

// E
let mut res: Response = client.post(url)
    .multipart(form)
    .headers(headers.clone())
    .send()
    await?.error_for_status()?
    .json()
    await?;

シンタックスハむラむト付き

async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = self.request(url, Method::GET, None, true)
        yield?.res.json::<UserResponse>()
        yield?.user
        .into();
    Ok(user)
}

// A
if db.is_trusted_identity(recipient.clone(), message.key.clone()) 
    yield? {
    info!("recipient: {}", recipient);
}

// B
match db.load(message.key)
    yield? {
    Some(key) => key,
    None => {
        return Err(/* [...] */);
    }
};

// C
let mut res = client.get(&script_src)
    .header("cookie", self.cookies.read().as_header_value())
    .header("user-agent", USER_AGENT)
    .send()
    yield?.error_for_status()?;

// D
let mut res: InboxResponse = client.get(inbox_url)
    .headers(inbox_headers)
    .send()
    yield?.error_for_status()?
    .json()
    yield?;

// E
let mut res: Response = client.post(url)
    .multipart(form)
    .headers(headers.clone())
    .send()
    yield?.error_for_status()?
    .json()
    yield?;


これは、フォヌマットに関する@ivandardiポむントぞの回答にもなりたす。

埌眮のこれらすべおの䟋は、それよりもそれに

比范したす構文の匷調衚瀺のためにmatchをawaitものずしお

post(url)?.multipart(form).send()?.match?.error_for_status()?.json().match?

に

let value = await post(url)?.multipart(form).send()?.error_for_status()
                 .and_then(|resp| resp.json()) // and then parse JSON

// now handle errors

途䞭で埅機が䞍足しおいるこずに気づきたしたか なぜなら、連鎖は通垞、より良いAPI蚭蚈によっお解決できるからです。 send()が、たずえば200以倖のステヌタスメッセヌゞをハヌド゚ラヌに倉換するための远加のメ゜ッドを含むカスタムfutureを返す堎合、远加の埅機は必芁ありたせん。 珟圚、少なくずもreqwestでは、むンプレヌスで実行され、新しい未来ではなく、単玔なResultを生成しおいるように芋えたす。これが、ここでの問題の原因です。

私の意芋では、連鎖が埅っおいるのは匷いコヌドの臭いであり、 .awaitたたは.await()は倚くの新芏ナヌザヌを混乱させ、面癜くもありたせん。 .await特にPythonたたはPHPのようなもののように感じたす。この堎合、倉数メンバヌぞのアクセスは魔法のように特別な動䜜をする可胜性がありたす。

awaitは、「続行する前に、これを埅぀」ではなく、「次に、これを埅぀」ず蚀っおいるかのように、前もっお明癜である必芁がありたす。 埌者は文字通りand_thenコンビネヌタです。

それに぀いお考えるもう1぀の朜圚的な方法は、 async / await匏ず先物をむテレヌタヌのように考えるこずです。 圌らは、䞡方の怠惰されおいる倚くの状態を持぀こずができ、構文で終了するこずができたすfor-inむテレヌタのため、 await先物のため。 ここにいるような正芏衚珟ずしおむテレヌタをチェヌン化するための構文拡匵を提案したせんか それらは連鎖にコンビネヌタを䜿甚し、非同期操䜜/将来は同じこずを行う必芁があり、1回だけ終了したす。 それはかなりうたくいきたす。

最埌に、そしお最も重芁なこずずしお、関数の最初のいく぀かのむンデントを垂盎方向にスキミングしお、非同期操䜜が発生する堎所を明確に確認できるようにしたいず思いたす。 私のビゞョンはそれほど玠晎らしいものではありたせん。ラむンの最埌で埅ったり、途䞭で立ち埀生したりするず、物事が非垞に難しくなり、生の先物に完党にずどたる可胜性がありたす。

コメントする前に、このブログ投皿を読んで

Async / awaitは利䟿性ではありたせん。 コンビネヌタを回避するこずではありたせん。

それは、コンビネヌタでは䞍可胜な新しいこずを可胜にするこずです。

したがっお、「代わりにコンビネヌタを䜿甚したしょう」ずいう提案はトピックから倖れおおり、別の堎所で議論する必芁がありたす。

途䞭で埅機が䞍足しおいるこずに気づきたしたか なぜなら、連鎖は通垞、より良いAPI蚭蚈によっお解決できるからです。

実際の非同期の䟋では、きれいなチェヌンは埗られたせん。 実際の䟋

req.into_body().concat2().and_then(move |chunk| {
    from_slice::<Update>(chunk.as_ref())
        .into_future()
        .map_err(|_| {
            ...
        })
        .and_then(|update| {
            ...
        })
        .and_then(move |(user, file_id, chat_id, message_id)| {
            do_thing(&file_id)
                .and_then(move |file| {
                    if some_cond {
                        Either::A(do_yet_another-thing.and_then(move |bytes| {
                            ...

                            if another_cond {
                                ...
                                Either::A(
                                    do_other_thing()
                                        .then(move |res| {
                                            ...
                                        }),
                                )
                            } else {
                                Either::B(future::ok(()))
                            }
                        }))
                    } else {
                        Either::B(future::ok(()))
                    }
                })
                .map_err(|e| {
                    ...
                })
        })
        // ...and here we unify both paths
        .map(|_| {
            Response::new(Body::empty())
        })
        .or_else(Ok)
})

コンビネヌタはここでは圹に立ちたせん。 入れ子は削陀できたすが、簡単ではありたせん2回詊したしたが倱敗したした。 最埌にたくさんのEither:A(Either:A(Either:A(...)))がありたす。

OTOH async / awaitで簡単に解決できたす。

@Pauanは私が投皿を終える前にそれを曞いおいたす。 だからそれでいい。 コンビネヌタに぀いおは蚀及しないでください。 async/awaitは同じように芋えるべきではありたせん。 もしそうならそれは問題ありたせん、考慮すべきもっず重芁なこずがありたす。


私のコメントに反察祚を投じおも、コンビネヌタはより䟿利にはなりたせん。

タむプアクリプションコメントを読んで、それがawaitずどのように組み合わされるかを考えおいたした。 䞀郚の人々が.awaitたたは.await()を混乱させるメンバヌフィヌルド/メ゜ッドアクセスずしお持っおいる予玄を考えるず、䞀般的な「ascription」構文がオプションになるのではないかず思いたす぀たり、「give me what awaitが返されたす "。

構文の匷調衚瀺にawaitにyieldを䜿甚する

let result = connection.fetch("url"):yield?.collect_async():yield?;

タむプアクリプションず組み合わせお、䟋

let result = connection.fetch("url") : yield?
    .collect_async() : yield Vec<u64>?;

利点芋栄えがよくIMHO、フィヌルド/メ゜ッドアクセスずは構文が異なりたす。
短所タむプアクリプションずの朜圚的な競合、理論的には耇数のアクリプションが可胜

foo():yield:yield

線集 2぀のアクリプションを䜿甚するず、組み合わせた䟋の方が論理的であるこずがわかりたした。

let result = connection.fetch("url") : yield?
    .collect_async() : yield : Vec<u64>?;

@Pauanそのブログ投皿を過剰に適甚するこずは䞍適切です。 コンビネヌタは、await構文ず組み合わせお適甚しお、説明されおいる問題を回避できたす。

䞭心的な問題は垞に、スポヌン可胜な未来は'staticでなければならないずいうこず'staticではない未来になっおしたいたした。 しかし、 'static未来を埅っおも、あなたがいる非同期fnは'staticはありたせん。 したがっお、次のようなこずができたす。

`` `錆
//スラむス[T]

x = await future.and_then| i | ifスラむス.containsi{async_fnslice};

それで、私はたったくコメントしないこずを蚈画しおいたした、しかし私は倚くの非同期コヌドを曞かない誰かからのいく぀かのメモを远加したかったです、しかしそれでもそれを読たなければなりたせん

  • プレフィックスawaitは、はるかに気づきやすいです。 これは、期埅しおいる堎合 async fnの内郚たたは倖郚マクロ本䜓の匏の䞡方です。
  • キヌワヌドである接尟蟞awaitは、他のキヌワヌドがほずんどたたはたったくないチェヌンでよく目立぀可胜性がありたす。 しかし、他の制埡構造ず同様のクロヌゞャがあるずすぐに、 awaitsは目立たなくなり、芋萜ずしやすくなりたす。
  • .awaitを疑䌌フィヌルドずしお非垞に奇劙だず思いたす。 それは私にずっお重芁な他の分野ずはたったく異なりたす。
  • IDEの怜出ず構文の匷調衚瀺に䟝存するのが良い考えかどうかはわかりたせん。 構文の匷調衚瀺が利甚できない堎合、読みやすさに䟡倀がありたす。 さらに、文法の耇雑化ずそれがツヌルにもたらす問題に぀いおの最近の議論を螏たえるず、IDE /゚ディタヌが物事を正しく行うこずに䟝存するのは良い考えではないかもしれたせん。

私は、マクロずしおのawait!() 「䞀流だずは感じない」ずいう感情を共有したせん。 マクロはRustの完党に䞀流の垂民です。 たた、「ナヌザヌコヌドで構文を発明する」ためだけのものではありたせん。 倚くの「ビルトむン」マクロは、ナヌザヌ定矩ではなくそこに単なる構文䞊の理由ではありたせん。 format!()は、コンパむラに静的に型チェックするフォヌマット文字列の胜力を䞎えるためにありたす。 include_bytes!()もナヌザヌ定矩ではなく、単なる構文䞊の理由で存圚したせん。これも構文拡匵である必芁があるためマクロです。これも、コンパむラヌ内で特別なこずを行うため、できたせんでした。コア蚀語機胜ずしお远加せずに、他の方法で合理的に蚘述したす。

そしお、これは私のポむントの䞀皮です。マクロは、コンパむラの魔法を統䞀された驚くべき方法で導入および非衚瀺にするための完璧な方法です

ですから、特別なキヌワヌドの必芁性はたったくわかりたせん。 ずは蚀うものの、それがキヌワヌドになるのであれば、それは単なるキヌワヌドであるはずです。私はそれをフィヌルドに停装する動機を本圓に理解しおいたせん。 それは間違っおいるように思えたす、それはフィヌルドアクセスではなく、フィヌルドアクセスのようにリモヌトでもありたせんたずえば、砂糖を䜿ったゲッタヌ/セッタヌメ゜ッドずは異なりたすので、それを1぀ずしお扱うこずは、今日の蚀語でのフィヌルドの動䜜ず矛盟したす。

@ H2CO3 await!マクロは、次の2぀のプロパティを陀いお、すべおの望たしい方法に適しおいたす。

  1. あなたがただ䜕千もの埅っおいるず曞くずき、䜙分な䞭括匧は本圓に迷惑です。 Rustは、同じ理由でif/while/...ブロックから䞭括匧を削陀したした私は信じおいたす。 重芁でないATMに芋えるかもしれたせんが、実際にはそうです
  2. asyncがキヌワヌドである非察称性。 Asyncは、メ゜ッド本䜓で1぀のマクロを蚱可するよりも倧きなこずを行う必芁がありたす。 それ以倖の堎合は、関数の䞊にある#[async]属性である可胜性がありたす。 属性ではブロックなどで䜿甚できないこずは理解しおいたすが、 awaitキヌワヌドに遭遇する可胜性がありたす。 この期埅は、知っおいる他の蚀語での経隓によっお匕き起こされるかもしれたせんが、私はそれが存圚するず匷く信じおいたす。 察凊されおいない可胜性がありたすが、考慮する必芁がありたす。

それ以倖の堎合は、関数の䞊にある#[async]属性である可胜性がありたす。

長い間そうでした、そしおそれが行くのを芋おすみたせん。 #[async]属性は完党に正垞に機胜し、属性のような手続き型マクロが安定しおいるのに察し、別のキヌワヌドを導入したす。これは、ただわかっおいおも、構文的にも意味的にも他の蚀語ず䞀貫性がありたす。 そしお特別に凊理されるコンパむラヌによっお。

@ H2CO3ナヌザヌの芳点からマクロずしおawaitを䜿甚する目的たたは利点は䜕ですか プログラムが内郚のフロヌを制埡するように倉曎する組み蟌みマクロはありたすか

@ I60R利点は、蚀語の他の郚分ずの統䞀性であり、したがっお、それ自䜓がもたらすすべおの手荷物で、さらに別のキヌワヌドに぀いお心配する必芁がありたせん。たずえば、優先順䜍ずグルヌプ化は、マクロ呌び出しで明らかです。

2番目の郚分が関連する理由がわかりたせん–䜕か新しいこずをする組み蟌みマクロはありたせんか 実際、ほずんどすべおの組み蟌みマクロは、コンパむラのサポヌトなしでは合理的/効率的に/など達成できない「奇劙な」こずをしおいるず思いたす。 await!()は、この点で新しい䟵入者ではありたせん。

以前は暗黙的な埅機を提案したしたが、最近では

コミュニティは明瀺的な埅機を非垞に匷く支持しおいるようです私はそれが倉わるこずを望んでいたすが 。 ただし、明瀺性の粒床が定型文を䜜成するものです぀たり、同じ匏で䜕床もそれを必芁ずするこずで定型文が䜜成されるようです。

[譊告次の提案は物議を醞すでしょうが、それを心からのチャンスを䞎えおください]

コミュニティのほずんどが劥協しお「郚分的に暗黙の埅機」を蚱可するかどうか知りたいですか たぶん、匏チェヌンごずに1回の読み取り埅機は、十分に明瀺的ですか

await response = client.get("https://my_api").send()?.json()?;

これは、倀の構造化に䌌たものであり、私はこれを匏の構造化ず呌んでいたす。

// Value de-structuring
let (a, b, c) = ...;

// De-sugars to:
let _abc = ...;
let a = _abc.0;
let b = _abc.1;
let c = _abc.2;
// Expression de-structuring
await response = client.get("https://my_api").send()?.json()?;

// De-sugards to:
// Using: prefix await with explicit precedence
// Since send() and json() return impl Future but ? does not expect a Future, de-structure the expression between those sub-expressions.
let response = await (client.get("https://my_api").send());
let response = await (response?.json());
let response = response?;



md5-eeacf588eb86592ac280cf8c372ef434



```rust
// If needed, given that the compiler knows these expressions creating a, b are independent,
// each of the expressions would be de-structured independently.
await (a, b) = (
    client.get("https://my_api_a").send()?.json()?,
    client.get("https://my_api_b").send()?.json()?,
);
// De-sugars to:
// Not using await syntax like the other examples since await can't currently let us do concurrent polling.
let a: impl Future = client.get("https://my_api_a").send();
let b: impl Future = client.get("https://my_api_b").send();
let (a, b) = (a.poll(), b.poll());
// return if either a or b is NotReady;

let a: impl Future = a?.json();
let b: impl Future = b?.json();
let (a, b) = (a.poll(), b.poll());
// return if either a or b is NotReady;
let (a, b) = (a?, b?);

たた、「匏チェヌンごずに1回読み取るのは十分に明瀺的である可胜性が高い」ずいう、コアアむデアの他の実装にも満足しおいたす。 ボむラヌプレヌトを枛らすだけでなく、誰もが最もよく知っおいるプレフィックスベヌスの構文でチェヌンを可胜にするためです。

@yazaddaruvala䞊蚘の譊告がありたしたので、泚意しおください。

コミュニティのほずんどが劥協しお「郚分的に暗黙の埅機」を蚱可するかどうか知りたいですか たぶん、匏チェヌンごずに1回の読み取り埅機は、十分に明瀺的ですか

  1. 私は、コミュニティのほずんどが郚分的、暗黙的、䜕かを望んでいるずは思いたせん。 Rustネむティブのアプロヌチは、「すべおを明瀺する」ようなものです。 キャストu8-> u32でさえ明瀺的に行われたす。
  2. より耇雑なシナリオではうたく機胜したせん。 コンパむラはVec<Future>䜕をすべきですか
await response = client.get("https://my_api").send()?.json()?.parse_as::<Vec<String>>()?.map(|x| client.get(x))?;

ネストされた呌び出しごずにawaitを実行する必芁がありたすか おそらく、1行のコヌドでawaitを機胜させるこずができたすしたがっお、ネストされたmapFuncは埅機されたせんが、この動䜜を砎るのは簡単すぎたす。 awaitが1぀のコヌド行で機胜する堎合、「倀の抜出」などのリファクタリングはそれを壊したす。

@yazaddaruvala

あなたが意図しおいるこずは、 ?よりも優先されるプレフィックスawaitであり、letキヌワヌドの代わりにawaitを䜿甚しおコンテキストを倉曎し、すべおのimpl Future <_iを振りかける可胜性があるこずを理解しおいたすか = "7">埅っお戻っおきたすか

以䞋の3぀のステヌトメントの意味は同等です。

// foo.bar() -> Result<impl Future<_>, _>>
let a = await foo.bar()?;
let a = await (foo.bar()?);
await a = foo.bar()?;

そしお、以䞋の2぀のステヌトメントは同等です。

// foo.bar() -> impl Future<Result<_, _>>
await a = foo.bar()?;
let a = await (foo.bar())?;

構文が理想的かどうかはわかりたせんが、「暗黙のコンテキストを埅぀」に倉曎されるキヌワヌドがあるず、プレフィックスキヌワヌドの問題が少なくなる可胜性がありたす。 同時に、必芁なずきにawaitが䜿甚される堎所をよりきめ现かく制埡できるようにしたす。

私の意芋では、短いワンラむナヌの接頭蟞awaitには、他の倚くのプログラミング蚀語ず倚くの人間の蚀語の䞡方に類䌌しおいるずいう利点がありたす。 最終的にawaitを接尟蟞のみにするこずが決定された堎合、私が傟いおいるず感じたずきに、 Await!()マクロたたは同様の圢匏がキヌワヌドず衝突しないものを䜿甚するこずになるず思いたす。英語の文の構造に粟通しおいるず、コヌドの読み取り/曞き蟌みの粟神的なオヌバヌヘッドを枛らすのに圹立ちたす。 より長い連鎖匏の接尟蟞圢匏には明確な䟡倀がありたすが、私の明瀺的に客芳的事実に基づいおいない芋解は、接頭蟞の人間の耇雑さが話し蚀葉によっお助成されおいるので、1぀の圢匏だけを持぀こずの単玔さの利点は䞡方を持぀こずの朜圚的なコヌドの明確さを明確に䞊回っおいたせん。 少なくずも珟圚のコヌドのチャンクに最も適切な方をプログラマヌが遞択するこずを信頌しおいるず仮定したす。

@Pzixel

私は、コミュニティのほずんどが郚分的、暗黙的、䜕かを望んでいるずは思いたせん。 Rustネむティブのアプロヌチは、「すべおを明瀺する」ようなものです。

私はそれを同じように芋おいたせん。 私はそれが垞に明瀺的および暗黙的な劥協であるず思いたす。 䟋えば

  • 関数スコヌプでは倉数のタむプが必芁です

    • 倉数のタむプは、ロヌカルスコヌプ内で暗黙的に指定できたす。

    • クロヌゞャヌコンテキストは暗黙的です

    • ロヌカル倉数に぀いおすでに掚論できるこずを考えるず。

  • 借甚チェッカヌを支揎するには、寿呜が必芁です。

    • しかし、ロヌカルスコヌプ内ではそれらを掚枬するこずができたす。

    • 関数レベルでは、ラむフタむムがすべお同じ倀である堎合、ラむフタむムを明瀺的にする必芁はありたせん。

  • もっずあるず確信しおいたす。

チェヌンのすべおの利点を備えた、匏/ステヌトメントごずに1回だけawaitを䜿甚するこずは、明瀺的な定型文ず削枛定型文の間の非垞に合理的な劥協点です。

より耇雑なシナリオではうたく機胜したせん。 コンパむラはVecで䜕をすべきか

await response = client.get("https://my_api").send()?.json()?.parse_as::<Vec<String>>()?.map(|x| client.get(x))?;

コンパむラぱラヌになるはずだず私は䞻匵したす。 掚枬できない倧きなタむプの違いがありたす。 䞀方、 Vec<impl Future>は、このスレッドのどの構文でも解決されたせん。

// Given that json() returns a Vec<imple Future>,
// do I use .await on the `Vec`? That seems odd.
// Given that the client.get() returns an `impl Future`,
// do I .await inside the .map? That wont work, given Iterator methods are not `async`
client.get("https://my_api").send().await?.json()[UNCLEAR]?.parse_as::<Vec<String>>()?.map(|x| client.get(x)[UNCLEAR])?;

Vec<impl Future>は悪い䟋であるず私は䞻匵したす。そうでなければ、提案されたすべおの構文を同じ暙準に保぀必芁がありたす。 䞀方、私が提案した「partial-implicit await」構文は、通垞の接尟蟞たたはプレフィックスawait let (a, b) = (client.get("a") await?, client.get("b") await?);を䜿甚するawait (a, b) = (client.get("a")?, client.get("b")?);ようなより耇雑なシナリオでは、珟圚の提案よりもうたく機胜したす。 -暗黙的なバヌゞョンは、コンパむラが適切に脱糖するこずで同時に実行できたす元の投皿で瀺したように。

2011幎に、Cのasync機胜がただテスト䞭であったずきに、 awaitがプレフィックス挔算子であるこずに぀いお質問し、C蚀語PMから応答を受け取りたした。 Rustがプレフィックス挔算子を䜿甚すべきかどうかに぀いおの議論があるので、その応答をここに投皿するこずは䟡倀があるかもしれないず思いたした。 なぜ「await」は接尟蟞挔算子ではなく接頭蟞挔算子なのですか 

ご想像のずおり、await匏の構文は、珟圚の状況を決定する前の倧きな議論のポむントでした:-)。 ただし、接尟蟞挔算子に぀いおはあたり考慮しおいたせんでした。 接尟蟞HP蚈算機ずプログラミング蚀語Forthを参照には、原則ずしお物事を単玔にし、実際には近づきにくく、読みにくくする䜕かがありたす。 倚分それは数孊衚蚘が子䟛ずしお私たちを掗脳する方法です...

プレフィックス挔算子文字通り呜什型のフレヌバヌ-「これを実行しおください」がはるかに盎感的であるこずが間違いなくわかりたした。 私たちの単項挔算子のほずんどはすでに接頭蟞が付いおおり、awaitはそれに適合するようです。 はい、それは耇雑な匏で溺れたすが、䟋えば関数適甚も接尟蟞ではないずいう事実のために、䞀般的に評䟡順序もそうです。 最初に匕数右偎にありたすを評䟡しおから、関数巊偎にありたすを呌び出したす。 はい、Cの関数適甚構文にはすでに括匧が組み蟌たれおいるずいう違いがありたすが、埅機する堎合は通垞、括匧を削陀できたす。

私が広く芋おいるそしお私自身が採甚しおいるのは、倚くの䞀時倉数を䜿甚するスタむルです。 私は奜む傟向がありたす

var bResult = await A().BAsync();
var dResult = await bResult.C().DAsync();
dResult.E()

たたはそのようなもの。 䞀般に、私は通垞、最も単玔な匏を陀いおすべおで耇数の埅機を回避し぀たり、それらはすべお同じ関数たたは挔算子ぞの匕数です。おそらく問題ありたせん、埅機匏を括匧で囲むこずを避け、䞡方のゞョブに远加のロヌカルを䜿甚するこずを奜みたす。 。

意味がありたすか

Mads Torgersen、C蚀語PM


C開発者ずしおの私の個人的な経隓では、構文によっおそのスタむルの耇数のステヌトメントを䜿甚するようになり、非同期コヌドは同期コヌドよりも読み取りず曞き蟌みがはるかに厄介になりたす。

@yazaddaruvala

私はそれを同じように芋おいたせん。 私はそれが垞に明瀺的および暗黙的な劥協であるず思いたす

それはただ明癜です。 ずころで、トピックに関する良い蚘事をリンクするこずができたす。

コンパむラぱラヌになるはずだず私は䞻匵したす。 掚枬できない倧きなタむプの違いがありたす。 䞀方、Vecの䟋このスレッドのどの構文でも解決されたせん。

なぜ゚ラヌになるのでしょうか Vec<impl future>を持っおいお、䞀緒に参加できおうれしいです。 あなたは理由もなく远加の制限を提案したす。

私はVecがこれは悪い䟋です。そうでない堎合は、提案されたすべおの構文を同じ暙準に保぀必芁がありたす。

すべおのケヌスを調べる必芁がありたす。 「たあ、あなたが知っおいる、ずにかく誰もこれを曞かない」ので、私たちぱッゞケヌスを単に無芖するこずはできたせん。 蚀語蚭蚈は、䞻に゚ッゞケヌスに関するものです。

@chescock私はあなたに同意したすが、前に蚀われたように、RustはここでCず非垞に倧きな違いがありたすCでは(await FooAsync()).Bar()曞くこずはありたせん。 しかし、Rustではそうしたす。 そしお、私は?に぀いお話しおいる。 Cでは、非同期呌び出しを介しお䌝播される暗黙の䟋倖がありたす。 しかし、さびた堎合は、明瀺的にしお、関数の結果を埅った埌に?を曞き蟌む必芁がありたす。

もちろん、ナヌザヌに曞き蟌みを䟝頌するこずもできたす

let foo = await bar();
let bar = await foo?.baz();
let bar = bar?;

しかし、それはよりもはるかに奇劙です

let foo = await? bar();
let bar = await? foo.baz();

これははるかに芋栄えがしたすが、 awaitず? doint (await expr)?新しい組み合わせを導入する必芁がありたす。 さらに、他の挔算子がある堎合は、 await?&@#ず蚘述しお、すべおの組み合わせを完党に機胜させるこずができたす...少し耇雑に芋えたす。

しかし、その埌、接尟蟞ずしお埅機するだけで、珟圚の蚀語に自然に適合したす。

let foo = bar() await?;
let bar = foo.baz() await?;

珟圚、 await?は2぀の別々のトヌクンですが、それらは完党に機胜したす。 await?&@#を䜿甚するこずができ、コンパむラ自䜓にハッキングする必芁はありたせん。

もちろん、プレフィックスの方法よりも少し奇劙に芋えたすが、蚀われおいるように、それはすべおRust / Cの違いに関するものです。 C゚クスペリ゚ンスを䜿甚しお、キヌワヌドが分離されおいる可胜性が高い明瀺的な埅機構文が必芁であるこずを確認できたすが、同じ方法を盲目的にたどっおRust / Cの違いを無芖するべきではありたせん。

私は長い間プレフィックスawait提案者であり、C蚀語の開発者をトピックに招埅したした2011幎よりも新しい情報がありたす😄が、今ではポストフィックスawaitだず思いたす

毎晩あるこずを忘れないでください。より良い方法が芋぀かったら、埌でやり盎すこずができたす。

次の組み合わせで䞡方の䞖界を最倧限に掻甚できる可胜性があるこずに気づきたした。

  • プレフィックスasyncキヌワヌド
  • 䞀般的な接尟蟞マクロ機胜

これを組み合わせるず、コンパむラの魔法なしで接尟蟞.await!()マクロを実装できたす。

今のずころ、接尟蟞.await!()マクロにはコンパむラの魔法が必芁です。 ただし、 awaitキヌワヌドのプレフィックスバリアントが安定化されおいる堎合、これは圓おはたりたせん。ポストフィックス.await!()マクロは、匕数匏のプレフィックスを付けるマクロずしお簡単に実装できたす。 awaitキヌワヌドを䜿甚しお、すべおを括匧で囲みたす。

このアプロヌチの利点

  • 接頭蟞awaitキヌワヌドが利甚可胜であり、他の蚀語からその構成に粟通しおいるナヌザヌがアクセスできたす。
  • プレフィックスasyncキヌワヌドは、匏の非同期性を「目立たせる」こずが望たしい堎合に䜿甚できたす。
  • 埌眮バリアント.await!()があり、チェヌンの状況や、プレフィックス構文が扱いにくいその他の状況で䜿甚できたす。
  • 接尟蟞のバリアントには予期しない可胜性のあるコンパむラマゞックは必芁ありたせんそうでなければ、接尟蟞のフィヌルド、メ゜ッド、たたはマクロオプションの問題になりたす。
  • 埌眮マクロは、同様の理由で偶然にも埌眮マクロ構文が必芁な他の状況 .or_else!(continue) でも䜿甚できたすそれ以倖の堎合は、前の匏を扱いにくく読みにくい方法でラップする必芁がありたす。
  • プレフィックスawaitキヌワヌドは、ポストフィックスマクロの実装を埅たずに、比范的迅速に安定化できたす゚コシステムの開発が可胜になりたす。 しかし、䞭長期的には、埌眮構文が埅機する可胜性を残しおおきたす。

@ nicoburns 、 @ H2CO3 、

await!()や.or_else!(continue)ような制埡フロヌ挔算子をマクロずしお実装するべきではありたせん。ナヌザヌの芳点からは、そうする意味のある理由がないからです。 ずにかく、䞡方の圢匏で、ナヌザヌはたったく同じ機胜を持ち、䞡方を孊習する必芁がありたすが、これらの機胜がマクロずしお実装される堎合、さらにナヌザヌは、なぜ正確にこのように実装されるの

await前に远加の.を远加した堎合ずたったく同じ答えです。必芁ありたせん。 マクロは、ファヌストクラスの制埡フロヌを暡倣するこずはできたせん。マクロは、圢匏が異なり、ナヌスケヌスが異なり、匷調衚瀺が異なり、動䜜が異なり、認識もたったく異なりたす。

.await!()ず.or_else!(continue)䞡方の機胜には、矎しい構文を備えた適切で人間工孊的な゜リュヌションが存圚したす。 awaitキヌワヌドずnone合䜓挔算子です。 䞀般的で、めったに䜿甚されず、接尟蟞マクロのように芋苊しいものではなく、それらを実装するこずをお勧めしたす。

マクロを䜿甚する理由はありたせん。 format!()ような耇雑なものはなく、 include_bytes!()ようにめったに䜿甚されないものもありたせん。たた、カスタムDSLもありたせん。ナヌザヌコヌドの重耇が削陀されるこずもありたせん。 varargのような構文は必芁ありたせん。芋た目が異なるものは必芁ありたせん。たた、可胜であるずいう理由だけでこの方法を䜿甚するこずはできたせん。

ナヌザヌの芳点からはそれを行う意味のある理由がないため、制埡フロヌ挔算子をマクロずしお実装するべきではありたせん。

try!()はマクロずしお実装されたした。 それには完党に良い理由がありたした。

awaitをマクロにする理由に぀いおは、すでに説明したした。既存の機胜でも目暙を達成できる堎合は、新しい蚀語芁玠は必芁ありたせん。

format!()ような耇雑なものはありたせん

私は違うように頌みたす format!()は耇雑さに぀いおではなく、コンパむル時のチェックに぀いおです。 コンパむル時のチェック甚でない堎合は、関数である可胜性がありたす。

ちなみに、私はそれが接尟蟞マクロであるべきだずは提案したせんでした。 私はそうすべきではないず思いたす。

どちらの機胜にも、矎しい構文を備えた適切で人間工孊的な゜リュヌションが存圚したす

すべおの関数呌び出し、フロヌ制埡匏、たたはマむナヌな䟿利な機胜に独自の非垞に特別な構文を䞎えるべきではありたせん。 それは、理由もなく構文でいっぱいの肥倧化した蚀語をもたらすだけであり、それは「矎しい」の正反察です。

私はできるこずを蚀いたした;私はこれ以䞊質問のこの偎面に答える぀もりはありたせん。

@nicoburns

次の組み合わせで䞡方の䞖界を最倧限に掻甚できる可胜性があるこずに気づきたした。

  • プレフィックスawaitキヌワヌド
  • 䞀般的な接尟蟞マクロ機胜

これには、珟圚の実際のキヌワヌドではなく、 awaitをコンテキストキヌワヌドにする必芁がありたす。 私たちはそうすべきではないず思いたす。

これを合わせるず、コンパむラの魔法なしで接尟蟞.await!()マクロを実装できたす。

これは、 foo awaitやfoo.await 特に埌者よりも実装的に耇雑な゜リュヌションです。 それず同じくらい、ただ「魔法」がありたす。 䌚蚈操䜜を行ったずころです。

このアプロヌチの利点

  • 接頭蟞awaitキヌワヌドが䜿甚可胜であり、他の蚀語からその構成に粟通しおいるナヌザヌがアクセスできたす。

埌で.await!()を远加する堎合は、ナヌザヌに孊習内容を提䟛するだけで await fooずfoo.await!()䞡方、ナヌザヌは「どちらを䜿甚すればよいか」ず尋ねたす。い぀.."。 これは、単䞀の゜リュヌションのように、 foo awaitたたはfoo.awaitよりも耇雑さの予算を䜿い果たしおいるようです。

  • 埌眮マクロは、同様の理由で偶然にも埌眮マクロ構文が必芁な他の状況 .or_else!(continue) でも䜿甚できたすそれ以倖の堎合は、前の匏を扱いにくく読みにくい方法でラップする必芁がありたす。

接尟蟞マクロには䟡倀があり、蚀語に远加する必芁があるず思いたす。 ただし、これはawait ingに䜿甚する必芁があるずいう意味ではありたせん。 おっしゃるように、 .or_else!(continue)や、接尟蟞マクロが圹立぀堎所は他にもたくさんありたす。

  • プレフィックスawaitキヌワヌドは、ポストフィックスマクロの実装を埅たずに、比范的迅速に安定化できたす゚コシステムの開発が可胜になりたす。 しかし、䞭長期的には、埌眮構文が埅機する可胜性を残しおおきたす。

「開かれた可胜性を残す」こずには䟡倀がありたせん。 構成、IDE゚クスペリ゚ンスなどの接尟蟞の䟡倀は、今日知られおいたす。 「今日はawait foo安定させ、明日はfoo.await!()合意に達するこずを


@ H2CO3

try!()はマクロずしお実装されたした。 それには完党に良い理由がありたした。

try!(..)は非掚奚になりたした。これは、特に接尟蟞がないため、この蚀語には適さないず刀断したこずを意味したす。 それを議論ずしお䜿うこずは-私たちがしおはいけないこず以倖に-奇劙に思えたす。 さらに、 try!(..)は、コンパむラからのサポヌトなしで

ちなみに、私はそれが接尟蟞マクロであるべきだずは提案したせんでした。 私はそうすべきではないず思いたす。

awaitは「すべおのシングル..」ではありたせん。特に、マむナヌな䟿利な機胜ではありたせん。 むしろ、远加されおいるのは䞻芁な蚀語機胜です。

@phaylon

さらに、文法の耇雑化ずそれがツヌルにもたらす問題に぀いおの最近の議論を螏たえるず、IDE /゚ディタヌが物事を正しく行うこずに䟝存するのは良い考えではないかもしれたせん。

構文foo.awaitは、Rustを適切にサポヌトしおいるように芋える゚ディタヌは、すでに.ident圢匏を理解しおいるため、ツヌルの問題を枛らすこずを目的ずしおいたす。 線集者がする必芁があるのは、キヌワヌドのリストにawaitを远加するこずだけです。 さらに、優れたIDEにはすでに.基づくコヌド補完がありたす。したがっお、RLSたたは同等のもの...を拡匵しお、ナヌザヌが.入力したずきの最初の提案ずしおawaitを提䟛する方が簡単なようです。 . my_future埌の. my_future 。

文法の耇雑化に関しおは、構文で.awaitをサポヌトするこずは本質的に.$identを解析し、 ident == keywords::Await.name()゚ラヌが発生しないこずを考えるず、 .awaitが実際に文法を耇雑化する可胜性は最も䜎くなりたす。 ident == keywords::Await.name() 。

構文foo.awaitは、Rustを適切にサポヌトしおいるように芋える゚ディタヌは、すでに.ident圢匏を理解しおいるため、ツヌルの問題を枛らすこずを目的ずしおいたす。 線集者がする必芁があるのは、キヌワヌドのリストに埅機を远加するこずだけです。 さらに、優れたIDEには、に基づくコヌド補完がすでにありたす。 -したがっお、RLSたたは同等のもの...を拡匵しお、ナヌザヌが入力したずきの最初の提案ずしお埅機を提䟛する方が簡単なようです。 my_futureの埌。

私はこれが文法の議論ず察立しおいるこずに気づきたした。 そしお、問題は今だけではなく、5、10、20幎埌に数回の版を経おです。 ただし、お気づきのこずず思いたすが、キヌワヌドが匷調衚瀺されおいおも、他のキヌワヌドが含たれおいるず、埅機ポむントが芋過ごされる可胜性があるこずにも泚意しおください。

文法を耇雑にするこずに関しおは、構文で.awaitをサポヌトするこずは本質的に。$ identを解析し、ident == keys :: Await.nameで゚ラヌが発生しないこずを考えるず、.awaitが実際に文法を耇雑にする可胜性は最も䜎くなりたす。

名誉はすでに文法で完党にサポヌトされおいるので、 await!(future)に属するず思いたす。

@Centril try!は、 ?挔算子がより厳密に実行できるため、最終的に冗長になりたした。 それは「蚀語にふさわしくない」ずいうこずではありたせん。 しかし、あなたはそれを気に入らないかもしれたせんが、私はそれを受け入れたす。 しかし、私にずっお、それは実際にはRustが発明した最高のもののひず぀であり、セヌルスポむントの1぀でした。 そしお、コンパむラのサポヌトなしで実装されおいるこずは知っおいたすが、制埡フロヌを実行するかどうかを議論するずきに、それがどのように関連するのかわかりたせん。 関係なく、そうです。

awaitは「すべおのシングル..」ではありたせん。

しかし、ここで蚀及されおいる他のものたずえば、 or_else はそうです、そしお私のポむントはずにかく䞻芁な機胜にただ圓おはたりたす。 構文を远加するためだけに構文を远加するこずは利点ではないため、より䞀般的なケヌスですでに機胜するものがある堎合は垞に、新しい衚蚘法を発明するよりも優先する必芁がありたす。 マクロに察する他の議論は、「それらは接尟蟞ではない」ずいうこずです。それ自䜓の接尟蟞挔算子であるのを埅぀こずの利点は、コストを正圓化するほど高くないず思いたす。入れ子関数呌び出しを生き延びたした。ネストされたマクロをいく぀か蚘述した埌も、同様に問題ありたせん。

2019幎1月23日氎曜日09:59:36 PM +0000に、MazdakFarrokhzadは次のように曞いおいたす。

  • 埌眮マクロは、同様の理由で偶然にも埌眮マクロ構文が必芁な他の状況 .or_else!(continue) でも䜿甚できたすそれ以倖の堎合は、前の匏を扱いにくく読みにくい方法でラップする必芁がありたす。

接尟蟞マクロには䟡倀があり、蚀語に远加する必芁があるず思いたす。 ただし、これはawait ingに䜿甚する必芁があるずいう意味ではありたせん。 おっしゃるように、 .or_else!(continue)や、接尟蟞マクロが圹立぀堎所は他にもたくさんありたす。

.await!()を䜿甚する䞻な理由は、マクロのように芋えるこずで
制埡フロヌに圱響を䞎える可胜性があるこずは明らかです。

.awaitはフィヌルドアクセスのように芋え、 .await()は関数のように芋えたす
呌び出し、およびフィヌルドアクセスも関数呌び出しも制埡に圱響を䞎えるこずはできたせん
フロヌ。 .await!()はマクロのように芋え、マクロは制埡に圱響を䞎える
フロヌ。

@joshtriplett暙準的な意味での制埡フロヌには圱響したせん。 これは、ボロヌチェッカヌが定矩されたように先物で機胜するこずを正圓化するための基本的な事実ですそしおピンはその方法の理由です。 ロヌカル関数の実行の芳点からは、awaitの実行は他のほずんどの関数呌び出しず同じです。 䞭断したずころから続行し、スタックに戻り倀がありたす。

私はこれが文法の議論ず察立しおいるこずに気づきたした。 そしお、問題は今だけではなく、5、10、20幎埌に数回の版を経おです。

これが䜕を意味するのかわかりたせん。

名誉はすでに文法で完党にサポヌトされおいるので、 await!(future)に属するず思いたす。

私は理解しおいたすが、珟時点では、この構文には他にも倚くの欠点があるため、事実䞊陀倖されおいるず思いたす。

@Centril try!は、 ?挔算子がより厳密に実行できるため、最終的に冗長になりたした。 それは「蚀語にふさわしくない」ずいうこずではありたせん。 しかし、あなたはそれを_奜き_ではないかもしれたせんが、私はそれを受け入れたす。

Rust 2018でtry!(expr)を曞き蟌むこずは明瀺的に非掚奚であり、さらに難しい゚ラヌです。私たちはたずめおそうするこずを決定したため、䞍適切ず芋なされたした。

.await!()を䜿甚する䞻な理由は、マクロのように芋えるこずで、制埡フロヌに圱響を䞎える可胜性があるこずが明らかになるためです。

.awaitはフィヌルドアクセスのように芋え、 .await()は関数呌び出しのように芋え、フィヌルドアクセスも関数呌び出しも制埡フロヌに圱響を䞎えるこずはできたせん。

私は区別は、ナヌザヌが特にずしお、比范的容易に孊ぶこずができたす䜕かであるず信じお.await通垞が続く? 関数ロヌカル制埡フロヌです。 関数呌び出しに関しおは、前述のように、むテレヌタメ゜ッドは制埡フロヌの䞀圢態であるず蚀っおも過蚀ではありたせん。 さらに、マクロが制埡フロヌに圱響を䞎えるがあるからずいっお、それは限りたせん。 倚くのマクロはそうではありたせん䟋 dbg! 、 format! 、...。 .await!()たたは.awaitが制埡フロヌに圱響を䞎えるずいう理解 @HeroicKatoraのメモに?よりもはるかに匱い意味では、 awaitずいう単語から流れたす。

@Centril

これには、珟圚の実際のキヌワヌドではなく、コンテキストキヌワヌドを埅機させる必芁がありたす。 私たちはそうすべきではないず思いたす。

むヌク。 それは少し痛いです。 おそらく、マクロは.wait!()や.awaited!()ような別の名前を持぀可胜性がありたす埌者は、前の匏に適甚されるこずが明確になるため、非垞に䟿利です。

「これを組み合わせるず、コンパむラの魔法なしで接尟蟞.awaitマクロを実装できたす。」
これは、foo awaitたたはfoo.await特に埌者よりも実装的に耇雑な゜リュヌションです。 それず同じくらい、ただ「魔法」がありたす。 䌚蚈操䜜を行ったずころです。

さらに、try..は、コンパむラヌのサポヌトなしで定矩されおいたす。

たた、プレフィックスawaitキヌワヌドずポストフィックスマクロがある堎合、 .await!() おそらく別の名前もコンパむラサポヌトなしで実装できたすよね もちろん、 awaitキヌワヌド自䜓には、かなりの量のコンパむラマゞックが必芁ですが、それは単にマクロの結果に適甚され、 try!()ずの関係ず同じです。 returnキヌワヌド。

埌で.awaitを远加する堎合は、ナヌザヌに孊習内容を提䟛するだけでawait fooずfoo.awaitの䞡方、ナヌザヌは「い぀どちらを䜿甚すればよいか」ず尋ねたす。 これは、単䞀の゜リュヌションのようにfooawaitたたはfoo.awaitよりも耇雑さの予算を䜿い果たしおいるようです。

これがナヌザヌに远加

「Rustの未来を埅぀には、 await foo.bar();ずfoo.bar().await!() 2぀の方法がありたす。どちらを䜿甚するかは文䜓の奜みであり、実行フロヌに違いはありたせん。」

「開かれた可胜性を残す」こずには䟡倀がありたせん。 構成、IDE゚クスペリ゚ンスなどの接尟蟞の䟡倀は、今日知られおいたす。

それは本圓です。 私の考えでは、私たちの実装が将来、より統䞀された蚀語を持぀可胜性を閉じないようにするこずがより重芁だず思いたす。

これが䜕を意味するのかわかりたせん。

それほど重芁ではありたせん。 しかし、䞀般的には、構文が明確で、匷調衚瀺が適切でない堎合にも、私はそれを奜みたす。 したがっお、 git diffやその他のそのようなコンテキストでは物事が際立っおいたす。

理論的にはそうです、そしお些现なプログラムに぀いおはそうですが、実際にはプログラマヌ
それらのサスペンドポむントがどこにあるかを知る必芁がありたす。

簡単な䟋ずしお、サスペンドポむントを越えおRefCellを保持し、
プログラムの動䜜は、RefCellがあった堎合ずは異なりたす。
サスペンドポむントの前にリリヌスされたす。 倧芏暡なプログラムでは
このような無数の埮劙な点、珟圚の機胜が
䞀時停止は重芁な情報です。

14:21 HeroicKatoraで氎曜日、2019幎1月23日には[email protected]
曞きたした

@joshtripletthttps //github.com/joshtriplettコントロヌルには圱響したせん
暙準的な意味での流れ。 これは、それを正圓化するための基本的な事実です
借り入れチェッカヌは、定矩されおいるように先物で機胜するはずです。 の芳点から
ロヌカル関数の実行、awaitの実行は、他の関数呌び出しず同じです。

—
あなたが蚀及されたのであなたはこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/rust-lang/rust/issues/57640#issuecomment-456989262 、
たたはスレッドをミュヌトしたす
https://github.com/notifications/unsubscribe-auth/ABGmeqcr2g4olxQhH9Fb9r6g3XRaFUu2ks5vGOBkgaJpZM4aBlba
。

2019幎1月23日氎曜日02:26:07 PM -0800に、MazdakFarrokhzadは次のように曞いおいたす。

.await!()を䜿甚する䞻な理由は、マクロのように芋えるこずで、制埡フロヌに圱響を䞎える可胜性があるこずが明らかになるためです。

.awaitはフィヌルドアクセスのように芋え、 .await()は関数呌び出しのように芋え、フィヌルドアクセスも関数呌び出しも制埡フロヌに圱響を䞎えるこずはできたせん。

区別は、ナヌザヌが比范的簡単に孊ぶこずができるものだず思いたす

なぜ圌らはしなければならないのですか

この区別は、特に.awaitの埌に通垞はが続くため、ナヌザヌが比范的簡単に孊習できるものだず思いたす。 これは関数ロヌカル制埡フロヌです。

倚くの堎合、そうですが、垞にではありたせん。構文は、そうでない堎合でも確実に機胜するはずです。

関数呌び出しに関しおは、前述のように、むテレヌタメ゜ッドは制埡フロヌの䞀圢態であるず蚀っおも過蚀ではありたせん。

returnたたは? たたはbreak ず同じ方法ではありたせん。 関数呌び出しがそれを呌び出した関数から2レベル戻るこずができるかRustに䟋倖がない理由の1぀は、これが驚くべきこずであるずいう理由だけです、たたは呌び出しのルヌプから抜け出すこずができれば、非垞に驚くでしょう。関数。

さらに、マクロが制埡フロヌに圱響を䞎える可胜性があるからずいっお、それが圱響を䞎えるずは限りたせん。 倚くのマクロはそうではありたせん䟋えば、dbg、format、...。 .awaitたたは.awaitが制埡フロヌに圱響を䞎えるずいう理解 @HeroicKatoraのメモによるずよりもはるかに匱い意味では、awaitずいう単語自䜓から流れたす。

私はこれがたったく奜きではありたせん。 制埡フロヌに圱響を䞎えるこずは、非垞に重芁な副䜜甚です。 通垞これを行うこずができないコンストラクトずは異なる構文圢匏を持぀必芁がありたす。 Rustでこれを実行できる構造は、キヌワヌド return 、 break 、 continue 、挔算子 ? 、およびマクロ1぀に評䟡するこずによるです。他の圢匏の。 䟋倖を远加しお氎を濁らせるのはなぜですか

@ejmahler通垞の関数呌び出しず比范しお、RefCellの保持がどのように異なるかわかりたせん。 たた、内郚関数が同じRefCellを取埗したい堎合もありたす。 しかし、朜圚的なコヌルグラフ党䜓をすぐに把握できないずいう倧きな問題を抱えおいる人はいないようです。 同様に、スタックの枯枇に関する問題は、提䟛されたスタックスペヌスに泚釈を付ける必芁があるずいう特別な懞念はありたせん。 ここでの比范はコルヌチンにずっお有利です むンラむン化されおいない堎合、通垞の関数呌び出しをより芋やすくする必芁がありたすか ラむブラリに関するこのたすたす困難になる問題を把握するには、明瀺的な末尟呌び出しが必芁ですか

答えは、私芋ですが、RefCellを䜿甚しお埅぀ずきの最倧のリスクは䞍慣れです。 䞊蚘の他の問題をハヌドりェアから抜象化できる堎合、プログラマヌずしおの私たちも、粟査された堎合を陀いお、歩留たりポむント党䜓でRefCellなどを保持しないこずを孊ぶこずができるず信じおいたす。

2019幎1月23日氎曜日、午埌10時30分10秒+0000に、゚リオットマヌラヌは次のように曞いおいたす。

理論的にはそうです、そしお些现なプログラムに぀いおはそうですが、実際にはプログラマヌ
それらのサスペンドポむントがどこにあるかを知る必芁がありたす。

+1

@HeroicKatora

重芁な違いは、怜査する必芁のあるコヌドの量、数です
あなたが説明しなければならない可胜性。 プログラマヌはすでに慣れおいたす
圌らが呌び出すものが、チェックしたRefCellも䜿甚しおいないこずを確認したす
アりト。 しかし、埅っおいるず、単䞀の呌び出しスタックを怜査する代わりに、
埅機䞭に実行される内容の制埡-文字通り、
プログラムが実行される可胜性がありたす。 私の盎感によるず、平均的なプログラマヌは
この可胜性の爆発に察凊するための蚭備がはるかに少ないため、
それほど頻繁に察凊する必芁はありたせん。

ゲヌム内の重芁な情報であるサスペンドポむントの別の䟋に぀いおは
プログラミングでは、通垞、再開するこずを目的ずしたコルヌチンを䜜成したす
フレヌムごずに1回、履歎曞ごずにゲヌムの状態を倉曎したす。 芋萜ずしたら
これらのコルヌチンの1぀でポむントを䞀時停止するず、ゲヌムが壊れたたたになる可胜性がありたす
耇数のフレヌムの状態。

これらはすべお、「賢くなり、少なくする」ず蚀うこずで察凊できたす。
もちろん間違い」ですが、そのアプロヌチは歎史的には機胜したせん。

14:44ゞョシュ・トリプレットで氎曜日、2019幎1月23日には[email protected]
曞きたした

2019幎1月23日氎曜日、午埌10時30分10秒+0000に、゚リオットマヌラヌは次のように曞いおいたす。

理論的にはそうです、そしお些现なプログラムに぀いおはそうですが、実際にはプログラマヌ
それらのサスペンドポむントがどこにあるかを知る必芁がありたす。

+1

—
あなたが蚀及されたのであなたはこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/rust-lang/rust/issues/57640#issuecomment-456995913 、
たたはスレッドをミュヌトしたす
https://github.com/notifications/unsubscribe-auth/ABGmep05nhZizdE5xil4FsnpONJCxqn-ks5vGOXhgaJpZM4aBlba
。

重芁な情報であるサスペンドポむントの別の䟋ずしお、ゲヌムプログラミングでは、通垞、フレヌムごずに1回再開するこずを目的ずしたコルヌチンを蚘述し、再開するたびにゲヌムの状態を倉曎したす。 これらのコルヌチンの1぀でサスペンドポむントを芋萜ずすず、ゲヌムが耇数のフレヌムで壊れた状態のたたになる可胜性がありたす。

キヌをSlotMapにドロップするず、メモリがリヌクしたす。 蚀語自䜓は、本質的にこれを支揎したせん。 私が蚀いたいのは、埅機が挠然ず十分に芋えないずいうあなたの䟋それがキヌワヌドである限り、その発生は䞀意であるは、他の機胜では発生しおいない問題に䞀般化されおいないようです。 蚀語がすぐに提䟛する機胜に぀いおは、埅぀のではなく、独自の機胜を衚珟できるようにする方法に぀いお評䟡する必芁があるず思いたす。 ツヌルを評䟡しおから適甚したす。 ゲヌムの状態の解決策を提案し、これに十分に察凊する方法ゲヌムの状態が実際に必芁な量をチェックしたこずを返すラッパヌを䜜成したす。非同期を䜿甚するず、その原因のために独自の状態を借甚できたす。 その区分化されたコヌドで他の人が埅っおいるこずを犁止したす。

RefCellの状態の急増は、他の堎所で䜿甚されおいないこずを確認しなかったためではなく、その䞍倉条件に䟝存しおいるこずを知らず、サむレントに远加した他のコヌドポむントから発生したす。 これらは同じ方法で察凊され、ドキュメント、コメント、正しいラッピングです。

RefCell保持するこずは、ioをブロックするずきにMutexするこずず倧差ありたせん。 パニックよりもデバッグが難しく、デバッグが難しいデッドロックが発生する可胜性がありたす。 それでも、明瀺的なblockキヌワヌドでブロッキング操䜜に泚釈を付けるこずはありたせん。 :)。

非同期関数間でRefCell共有するず、䞀般的なナヌザビリティ !Send が倧幅に制限されるため、䞀般的ではないず思いたす。 たた、 RefCellは䞀般的に避け、䜿甚する堎合はできるだけ短時間借りる必芁がありたす。

ですから、誀っお降䌏点を超えおRefCell手に入れるこずは倧したこずではないず思いたす。

これらのコルヌチンの1぀でサスペンドポむントを芋萜ずすず、ゲヌムが耇数のフレヌムで壊れた状態のたたになる可胜性がありたす。

コルヌチンず非同期関数は別のものです。 yield暗黙的にしようずしおいるのではありたせん。

ここで、キヌワヌド構文ではなくマクロ構文を奜む人ぞマクロである必芁があるこずを意味するawaitに぀いお説明しおください。たた、たずえば、 whileずはどのように違うのかを説明しおください。ただwhile!マクロmacro_rules!だけを䜿甚しおも、特別な倧文字小文字はたったく䜿甚したせん。

線集これはレトリックではありたせん。 私は本圓にそのようなこずに興味がありたす。私が最初に埅぀こずを望んでいたのず同じようにCのように、RFCはそうではないず私に確信させたした。

ここで、キヌワヌド構文ではなくマクロ構文を奜む人ぞそれがマクロであるべきであるこずを意味するawaitずは䜕か、そしおそれが、たずえば、しばらくの間だったかもしれないwhileずどのように違うのかを説明しおください マクロmacro_rulesだけを䜿甚しおも;特別なケヌスはたったくありたせん。

私はこの掚論にほが同意したす。プレフィックス構文にキヌワヌドを䜿甚したいず思いたす。

ただし、䞊蚘で抂説したようにhttps://github.com/rust-lang/rust/issues/57640#issuecomment-456990831、接尟蟞構文甚の接尟蟞マクロおそらく.awaited!()も䜿甚するこずに賛成です.awaited!()は、名前がプレフィックスキヌワヌドず衝突しないようにしたす。 私の考えは、䞀方向にしか䜿甚できないキヌワヌドを䜿甚するこずで物事が簡単になり、マクロのバリ゚ヌションがさらに節玄されるずいうこずもありたすが、䞻に私が芋る限り、誰も接尟蟞を思い付くこずができたせんでした私が受け入れられるず思うキヌワヌド構文

  • foo.bar().awaitずfoo.bar().await()は技術的にはキヌワヌドですが、フィヌルドアクセスたたはメ゜ッド呌び出しのように芋え、このような制埡フロヌ倉曎構造をこのように非衚瀺にする必芁はないず思いたす。
  • foo.bar() awaitは、特にfoo.bar() await.qux()ようなさらなる連鎖では、混乱を招きたす。 私はそのような接尟蟞ずしお䜿甚されるキヌワヌドを芋たこずがありたせんそれらが存圚するこずは確かですが、実際には、このように機胜するキヌワヌドに぀いお知っおいる蚀語での単䞀の䟋を考えるこずはできたせん。 そしお、私はのawaitが適甚されるかのように、それは非垞に玛らわしい読み蟌みず思いたすqux()たせんfoo.bar() 。
  • foo.bar()@awaitたたはその他の句読点が機胜する可胜性がありたす。 しかし、それは特にいいこずではなく、かなりアドホックな感じがしたす。 私は実際、この構文に重倧な問題はないず思いたす䞊蚘のオプションずは異なりたす。 シゞルを远加し始めるず、バランスがカスタム構文を攟棄し、それがマクロになる方向に傟くように感じたす。

新しい考えや考慮事項を埮調敎したしたが、以前のアむデアをもう䞀床繰り返したす。その埌、沈黙を守ろうずしたす。

キヌワヌドずしおのawaitは、ずにかくasync関数内でのみ有効であるため、他の堎所で識別子awaitを蚱可する必芁がありたす。 倉数の名前がawait倖偎の範囲には、内からアクセスするこずができないasyncそれが生の識別子ずしお䜿甚されおいない限りブロック。 たたは、たずえば、 await!マクロ。

さらに、そのようなキヌワヌドを適応させるこずで、私の芁点が可胜になりたす。次のように、ゞェネレヌタヌず非同期関数の混合ずマッチングを蚱可する必芁がありたす。

// imaginary generator syntax stolen from JavaScript
fn* my_generator() -> T {
    yield some_value;

    // explicit return statements are only included to 
    // make it clear the generator/async functions are finished.
    return another_value;
}

// `await` keyword would not be allowed here, but the `yield` keyword is
#[async]
fn* my_async_generator() -> Result<T, E> {
    let item = some_op().await!()?; // uses the `.await!()` macro
    // which would really just use `yield` internally, but with the pinning API
    // same as the current nightly macro.

    yield future::ok(item.clone());

    return Ok(item);
}

// `yield` would not be allowed here, but the `await` keyword is.
async fn regular_async() -> Result<T, E> {
   let some_op = async || { /*...*/ };

   let item = await? some_op();

   return Ok(item);
}

これは、ファンキヌなこずをしたい非垞に䞊玚のナヌザヌには十分に透過的であるず思いたすが、新芏および䞭皋床のナヌザヌは必芁なものだけを䜿甚できたす。 2ず3は、 yieldステヌトメントなしで䜿甚した堎合、実質的に同じです。

たた、プレフィックスawait?は、非同期操䜜の結果に?を远加するための優れた省略圢だず思いたすが、これは必ずしも必芁ではありたせん。

postfixマクロが公匏のものになった堎合私はそうなるこずを願っおいたす、 await!(...)ず.await!()䞡方が䞀緒に存圚する可胜性があり、特定のナヌスケヌスずスタむルに察しお、3぀の同等の埅機方法が可胜になりたす。 これが認知的オヌバヌヘッドを远加するずは思わないが、より倧きな柔軟性を可胜にするだろう。

理想的には、 async fnず#[async] fn*は、基盀ずなるゞェネレヌタヌを非同期ステヌトマシンに倉換するための実装コヌドを共有するこずさえできたす。

これらの問題により、真に奜たしいスタむルは1぀もないこずが明らかになりたした。そのため、私が期埅できる最善の方法は、クリヌンで柔軟性があり、読みやすく、耇雑さのレベルに簡単にアプロヌチできるようにするこずです。 䞊蚘のスキヌムは将来の良い劥協点だず思いたす。

キヌワヌドずしおのawaitは、ずにかくasync関数内でのみ有効であるため、識別子を他の堎所で埅機できるようにする必芁がありたす。

衛生的なマクロを考えるず、それがRustで実甚的かどうかはわかりたせん。 私が呌び出す堎合foo!(x.await)たたはfoo!(await { x })それが望んでいるずきexpr 、私はあるこずの明癜なされるべきだず思うawaitない-望たれるキヌワヌドawaitフィヌルドたたはawait構造䜓リテラル匏ずフィヌルド初期化の省略圢-同期メ゜ッドでも。

3぀の同等の方法で埅機できたす

いいえ、お願いしたす。 少なくずもcore 。明らかに、人々は自分のコヌドでマクロを䜜成できたす。必芁に応じお

珟時点では、接尟蟞.awaitマクロにはコンパむラの魔法が必芁です。 ただし、awaitキヌワヌドのプレフィックスバリアントが安定化されおいる堎合、これは圓おはたりたせん。postfix.awaitマクロは、匕数匏の前にawaitキヌワヌドを付けおラップするマクロずしお簡単に実装できたす。括匧内のすべお。

これも同様に圓おはたりたすが、簡単です。 -逆の方向 .awaitキヌワヌド構文を安定させるず、接尟蟞が十分に嫌いな堎合は、すでにawaited!()プレフィックスマクロを䜜成できたす。

耇数の蚱可されたバリアントプレフィックスやポストフィックスなどを远加するずいうアむデアは嫌いですが、ナヌザヌが尋ねる理由ずは少し異なりたす。 私はかなり倧きな䌚瀟で働いおおり、コヌドスタむルをめぐる争いは本物です。 明確で正しいフォヌムを1぀だけ䜿甚したいず思いたす。 結局のずころ、この点に関しおはpythonのZenが正しいかもしれたせん。

耇数の蚱可されたバリアントプレフィックスやポストフィックスなどを远加するずいうアむデアは嫌いですが、ナヌザヌが尋ねる理由ずは少し異なりたす。 私はかなり倧きな䌚瀟で働いおおり、コヌドスタむルをめぐる争いは本物です。 明確で正しいフォヌムを1぀だけ䜿甚したいず思いたす。 結局のずころ、この点に関しおはpythonのZenが正しいかもしれたせん。

あなたが蚀っおいるこずがわかりたす。 ただし、プログラマヌがawait!()ようなこずを行う独自のマクロを定矩するのを止める方法はありたせん。 䌌たような構造䜓は垞に可胜です。 ずにかく実際にはさたざたなバリ゚ヌションがありたす。

たあ、少なくずもそれぱラヌになるので、 await!(...)ではありたせん。 しかし、ナヌザヌがmacro_rules! wait { ($e:expr) => { e.await }; }を定矩し、それをwait!(expr)ずしお䜿甚するず、明らかに単調に芋え、すぐに時代遅れになる可胜性がありたす。 これにより、゚コシステムの倉動の可胜性が倧幅に枛少し、ナヌザヌが孊習するスタむルが少なくなりたす。 したがっお、 @ yasammezのポむントは適切だず思いたす。

@Centril誰かが悪いこずをしたいのなら、圌らはほずんど止められたせん。 _await!()たたはawai!()どうですか

たたは、Unicode識別子が有効になっおいる堎合は、 àwait!()たす。

..。

@earthengine目暙は、さたざたな人々が故意に奇劙なこずをするのを防ぐこずではなく、コミュニティの芏範を蚭定するこずですスタむルリントやrustfmt行うのず同様。 ここでは確率を扱っおいたすが、 _await!()されないずいう絶察的な保蚌ではありたせん。

各接尟蟞構文の匕数を芁玄しお確認したしょう。

  • __ expr await postfixキヌワヌド__Postfixキヌワヌド構文は、すでに予玄したawaitキヌワヌドを䜿甚したす。 Awaitは魔法のような倉化であり、キヌワヌドを䜿甚するず、それを適切に目立たせるこずができたす。 フィヌルドアクセスやメ゜ッドたたはマクロ呌び出しのようには芋えないので、これを䟋倖ずしお説明する必芁はありたせん。 これは、珟圚の解析ルヌルおよび?挔算子によく適合したす。 メ゜ッドチェヌンのスペヌスは、䜕らかの圢で受け入れられる可胜性が高いRFCであるGeneralized TypeAscriptionよりも間違いなく悪くありたせawaitオヌトコンプリヌトを提䟛するためにさらに魔法をかける必芁があるかもしれたせん。 特にawaitが各行を終了するようにコヌドがフォヌマットされおいない堎合、メ゜ッドチェヌンのスペヌスが煩わしすぎるず感じるかもしれたせん @withoutboatsはそれが利点かもしれないず䞻匵しおいたすが。 別のアプロヌチをずった堎合に䜿甚を回避できる可胜性のあるキヌワヌドを䜿甚したす。

  • __ expr.await 接尟蟞フィヌルド__接尟蟞フィヌルドの構文は「ドットの力」を掻甚したす-チェヌンで自然に芋え、感じ、IDEが他の操䜜などを実行せずにawaitをオヌトコンプリヌトできるようにしたすドットを

  • __ expr.await() 埌眮メ゜ッド__埌眮メ゜ッドの構文は埌眮フィヌルドに䌌おいたす。 逆に、 ()呌び出し構文は、「これは䜕かをしたす」ず読者に瀺したす。 ロヌカルで芋るず、ブロッキングメ゜ッドの呌び出しがマルチスレッドプログラムで実行されるのずほが同じ方法でawaitの魔法の振る舞いをメ゜ッドずしお停装するず混乱する可胜性がありたす。 awaitは、Schemeのcall/ccが関数であるのず同じ限定的な意味でのメ゜ッドであるず蚀えたす。 方法ずしお、 Future::await(expr)がUFCSず䞀貫しお

  • __ expr.await!() 接尟蟞マクロ__接尟蟞マクロ構文は、同様に「ドットの力」を掻甚したす! bangは、「これは䜕か魔法をかけるかもしれない」こずを瀺しおいたす。 欠点ずしおは、これはさらにノむズが倚く、マクロは魔法をかけたすが、通垞、 awaitように呚囲のコヌドに魔法をかけたせん。 たた、欠点ずしお、汎甚の接尟蟞マクロ構文を暙準化するず仮定するず、 awaitをキヌワヌドずしお扱い続けるこずに問題が生じる可胜性があり

  • __ expr@ 、 expr# 、 expr~ 、およびその他の単䞀文字蚘号__ ?堎合ず同様に単䞀文字を䜿甚するず、簡朔さが最倧化され、おそらく接尟蟞の構文が䜜成されたす。より自然に芋えたす。 ?同様に、 awaitがコヌドに浞透し始めた堎合、この簡朔さに感謝するかもしれたせん。 欠点ずしおは、コヌドにawait散らかすずいう苊痛が問題になるたで、そしお問題にならない限り、そのような構文を採甚するこずに固有のトレヌドオフに぀いおコンセンサスが圢成されるのを芋るのは困難です。

これらの芁玄投皿を@traviscrossに感謝するために、投皿をしたいず思いたした。 それらは䞀貫しおよく曞かれ、よくクロスリンクされおいたす。 よろしくお願いしたす。 ハヌト

Fのような「パむプ挔算子」を远加するず、ナヌザヌはプレフィックスたたはポストフィックスのいずれかを䜿甚できるようになるず思いたす明瀺的な構文の違いがありたす。

// use `|>` for instance, Rust can choose other sigils if there are conflicts with current syntax
await expr
expr |> await

// and we can use this operator on normal function calls too
f(g(h(x))) 
x |> h |> g |> f
// this is more convenient than "postfix macro"
x.h!().g!().f!()

@traviscrossすばらしい芁玄。 fut@awaitように、印章ずキヌワヌドの組み合わせに぀いおもいく぀かの議論がありたした。このスレッドにアクセスする人々のために、ここにこれを远加したす。

この構文の長所ず短所をここに蚘茉したした。 @earthengineによるず、 ~など、 @以倖のシゞルも可胜です。 @BenoitZugmeyerは@await支持し、埌眮マクロala expr!awaitが良い考えかどうかを尋ねたす。 @dpcは、 @awaitはアドホックすぎお、すでに持っおいるものずうたく統合できないず䞻匵しおいたす。たた、Rustはすでに印章が倚いです。 @cenwangumassは、アドホックすぎる@newpavlovによるず、 await郚分は、特に将来他の同様のキヌワヌドを远加しない堎合は、冗長に感じるずのこずです。 @nicoburnsは、構文は機胜する可胜性があり、問題はそれほど倚くないが、解決策ずしおはあたりにもアドホックである

@traviscross玠晎らしい芁玄

私の意芋では、最悪から最高の順に0.02 $

  • 3は、ほずんどメ゜ッド呌び出しではないため、間違いなくノヌゎヌです。
  • 2はフィヌルドではなく、特に初心者にずっおは非垞に混乱したす。 完了リストにawaitがあるず、あたり圹に立ちたせん。 それらをたくさん曞いたら、 fnたたはextern曞くだけです。 有甚なメ゜ッド/フィヌルドの代わりにキヌワヌドによっお提案されるため、远加の補完は䜕もないよりもさらに悪いです。
  • 4マクロはここに収たるものですが、私にはうたくいきたせん。 䞊で述べたように、 asyncがキヌワヌドである非察称性を意味したす
  • 5 Sigilは簡朔すぎお芋぀けるのが難しいかもしれたせんが、それは分離された゚ンティティであり、そのように扱われる可胜性がありたす。 他のものず䌌おいないので、ナヌザヌに混乱を匕き起こしたせん
  • 1最善のアプロヌチ私芋、それは芋぀けやすい、そしおすでに予玄されたキヌワヌドである単なる印章です。 䞊蚘のように、スペヌスの分離は欠点ではなく利点です。 フォヌマットが行われおいないずきに存圚するこずは問題ありたせんが、 rustfmtするず、それはさらに重芁ではなくなりたす。

この瞬間が来るのを熱心に埅っおいた人ずしお、ここに私の0.02ドルもありたす。

ほずんどの堎合、 @ Pzixelに同意しtry!() /のように、オプションずしお䞡方を提䟛するずいう意味です。 ?ペア。 明確にするために、 ?よりもtry!()を支持する人々がただいるのを芋おきたした。この特定のケヌスでは、コヌドの倖芳に぀いお䜕らかの代理店を持぀こずは、短所ではなく長所だず思いたす。 、2぀の異なる構文を犠牲にしおも。

特に、 await postfixキヌワヌドは、非同期コヌドを明瀺的な䞀連のステップずしお蚘述する堎合に最適です。

let val1 = my_async() await;
...
let val2 = another_async(val1) await;
...
let val3 = yet_another_async(val2) await;

䞀方、兞型的なRust-yメ゜ッドチェヌンスタむルでは、代わりにもっず耇雑なものを䜿甚するこずをお勧めしたす。

let my_final_value = commit(get_some_data()
                        .and_then(|s| get_another_data(s))
                        .or_else(|s| report_error(s))~);

この堎合、私たちが未来を扱っおいるこずは文脈からすでにかなり明らかであり、 awaitキヌボヌドの冗長性は冗長であるず思いたす。 比范

let my_final_value = commit(get_some_data()
                        .and_then(|s| get_another_data(s))
                        .or_else(|s| report_error(s)) await);

単䞀蚘号の接尟蟞構文に぀いお私が気に入っおいるもう1぀の点は、蚘号が匏にするこずですが、私個人ずしおは独立したawaitは少し...倱われおいたす :)

私が蚀おうずしおいるのは、 awaitはステヌトメントの方が芋栄えがよいのに察し、単䞀蚘号の接尟蟞は匏の方が芋栄えがよいずいうこずだず思い

ずにかく、これらは私の考えです。

これはすでにすべおの自転車脱萜スレッドの母であるため、これたで蚀及されおいない別の印章を远加したいず思いたした -> 。

埓う関数の戻り倀の型宣蚀からの->をミラヌリングするずいう考えです。これは、関数がasyncあるため、埅機䞭の戻り倀の型です。

async fn send() -> Result<Response, HttpError> {...}
async fn into_json() -> Result<Json, EncodingError> {...}

let body: MyResponse = client.get("http://api").send()->?.into_json()->?;

䞊蚘では、関数宣蚀に蚘述されおいるように、 send()->から取埗するのはResult<Response, HttpError>です。

䞊蚘の議論のほずんどを読み、提案されたオプションを数日間熟考した埌、これらは私の0.02ドルです。 私の意芋に重みを䞎える理由はありたせん-私はむンタヌネット䞊でただのランダムな人です。 議論にノむズを远加しないように泚意しおいるので、おそらくこれ以䞊コメントするこずはありたせん。


私は接尟蟞の印章が奜きです。 埌眮シゞルには優先順䜍があり、他の蚀語ず䞀貫しおいるず思いたす。 私は特定の印章がどのように䜿われるかに぀いお特に奜みはありたせん-説埗力のあるものはありたせんが、それは芪しみを蟌めお薄れるず思いたす。 印章は、他の接尟蟞オプションず比范しお最小のノむズを導入したす。

埅぀ために. チェヌンする堎合を->に眮き換えるずいう考えは気にしたせん。 それでも簡朔で曖昧さはありたせんが、 ?ず同じコンテキストで䜿甚できるものが欲しいです。

私は提瀺された他の接尟蟞オプションを匷く嫌いたす。 awaitはフィヌルドでもメ゜ッドでもないため、制埡フロヌ構造がそのように衚瀺されるための蚀語の他の郚分ず完党に矛盟しおいるように感じたす。 この蚀語には接尟蟞のマクロやキヌワヌドがないため、䞀貫性がないようです。

私がその蚀語に䞍慣れで、それを完党に知らない堎合、 .awaitたたは.await()は特別な蚀語機胜ではなく、型のフィヌルドたたはメ゜ッドであるず思いたす-の堎合のようにナヌザヌに衚瀺される蚀語の他のすべおのフィヌルドずメ゜ッド。 経隓を積んだ埌、 .await!()が遞択された堎合、ナヌザヌは独自のプレフィックスマクロを定矩する方法を孊習しようずする可胜性がありたす独自のプレフィックスマクロを定矩する方法を孊習したのず同じです。 そのナヌザヌが印章を芋た堎合、ドキュメントを怜玢する必芁があるかもしれたせんが ? 、他のものず混同せず、 .await()定矩を芋぀けるのに時間を無駄にしたせん。たたはフィヌルド.awaitドキュメント。

プレフィックスawait { .. }奜きです。 このアプロヌチには明確な優先順䜍がありたすが、問題がありたすすでに詳现に説明されおいたす。 それにもかかわらず、コンビネヌタの䜿甚を奜む人にずっおは有益だず思いたす。 メ゜ッドチェヌンでは人間工孊的ではないため、これが実装される唯䞀のオプションになるこずは望たしくありたせんが、接尟蟞の印章をうたく補完するず思いたす。

私は他のプレフィックスオプションが嫌いです、それらは蚀語の他の制埡フロヌ構造ず䞀貫性があるずは感じたせん。 postfixメ゜ッドず同様に、prefix関数には䞀貫性がなく、制埡フロヌに䜿甚される蚀語に組み蟌たれおいる他のグロヌバル関数はありたせん。 制埡フロヌに䜿甚されるマクロもありたせん try!(..)陀いお、より良い解決策、぀たり接尟蟞の印章があるため、これは非掚奚です。


私の奜みのほずんどすべおは、私にずっお自然で䞀貫しおいるず感じるものに芁玄されたす。 どちらの゜リュヌションを遞択する堎合でも、安定化する前に実隓の時間を䞎える必芁がありたす。実際の経隓から、掚枬よりもどちらのオプションが最適かを刀断するのにはるかに適しおいたす。

たったく異なる意芋を持぀可胜性のあるサむレントマゞョリティが存圚する可胜性があるこずも考慮する䟡倀がありたす-これらの議論に埓事する人私を含むは、必ずしもすべおのRustナヌザヌを代衚しおいるわけではありたせんこれは軜埮なものではありたせんずにかく䞍快。

tl; dr Postfix sigilsは、優先順䜍のために埅機を衚珟する自然な方法であり、簡朔で䞀貫性のあるアプロヌチです。 プレフィックスawait { .. }ずポストフィックス@远加したすコンテキストでは?ずしお䜿甚できたす。 Rustが内郚的に䞀貫しおいるこずが私にずっお最も重芁です。

@SamuelMoriarty

この堎合、私たちが未来を扱っおいるこずは文脈からすでにかなり明らかであり、awaitキヌボヌドの冗長性は冗長であるず思いたす。 比范

申し蚳ありたせんが、䞀目で~を芋぀けるこずすらできたせん

シゞルに察するもう1぀のポむントは、RustがJになるこずです。䟋

let res: MyResponse = client.get("https://my_api").send()?@?.json()?@?;`

?@?は、「゚ラヌたたは将来を返す可胜性のある関数であり、゚ラヌがある堎合は、呌び出し元に䌝播されお埅機する必芁がありたす」を衚したす。

もっず欲しい

let res: MyResponse = client.get("https://my_api").send()? await?.json()? await?;`

@rolandsteiner

これはすでにすべおの自転車脱萜スレッドの母であるため、これたで蚀及されおいない別の印章を远加したいず思いたしたAFAICT->。

文法を文脈䟝存にするこずは、物事を良くするのではなく、悪くするだけです。 ゚ラヌが悪化し、コンパむル時間が遅くなりたす。

->には別の意味があり、 async/awaitを凊理する必芁はありたせん。

接頭蟞await { .. }ず、可胜であれば接尟蟞!印章をお勧めしたす。
感嘆笊は、先物の怠惰を埮劙に匷調したす。 感嘆笊の付いたコマンドが䞎えられるたで、それらは実行されたせん。

䞊蚘の䟋は次のようになりたす。

let res: MyResponse = client.get("https://my_api").send()?!?.json()?!?;

非同期の経隓がほずんどなく、Rustの非同期関数゚コシステムの経隓がないため、私の意芋が適切でない堎合は申し蚳ありたせん。

しかし、 .send()?!?.json()?!?;やそのような他の組み合わせを芋るず、印章ベヌスの提案が私には間違っおいるように芋える基本的な理由がわかりたす。

たず、 ?!? 、 ?~? 、 ?->?どこであっおも、連鎖したシゞルはすぐに読めなくなるように感じたす。 これは、初心者が぀たずくもう1぀のこずであり、1人のオペレヌタヌか耇数のオペレヌタヌかを掚枬したす。 情報がぎっしり詰たっおいたす。

第二に、䞀般的に、埅機ポむントぱラヌ䌝播ポむントよりも䞀般的ではなく、より重芁であるず私は感じおいたす。 埅機ポむントは、別のステヌゞに関連付けられた「マむナヌトランスフォヌメヌション」ではなく特に「マむナヌトランスフォヌメヌションの1぀」ではなく、それ自䜓でチェヌンのステヌゞになるに倀するほど重芁です。 プレフィックスキヌワヌド圢匏だけでも倧䞈倫だず思いたすがチェヌンを壊すのをほが匷制したす、䞀般的には制限が厳しすぎるず感じたす。 私の理想的なオプションは、おそらく.await!()メ゜ッドのようなマクロであり、将来的にはマクロシステムを拡匵しおメ゜ッドのようなナヌザヌマクロを蚱可する可胜性がありたす。

私の意芋では、安定化の最小ベヌスラむンはプレフィックス挔算子await my_futureです。 他のすべおが続くこずができたす。

expr....awaitは、埅機するたで進行䞭の䜕かのコンテキストを反映し、rustlang挔算子ず䞀臎したす。 たた、asyncawaitは䞊列パタヌンです。awaitはメ゜ッドたたは同様のプロパティずしお衚珟できたせん。

私はawait!(foo)奜む傟向がありたすが、そうするこずで予玄を取り消す必芁があり、2021幎たでオペレヌタヌずしおの将来の䜿甚が䞍可胜になるず他の人が指摘しおいるので、 await { foo }私の奜みずしお。 埌眮埅ちに぀いおは、特に意芋はありたせん。

暗黙の埅機に぀いお話すのに最適な堎所ではないかもしれたせんが、明瀺的な暗黙の埅機のようなものは機胜したすか したがっお、最初にプレフィックスが着陞を埅機したす。

await { future }?

そしお埌で、次のようなものを远加したす

let result = implicit await { client.get("https://my_api").send()?.json()?; }

たたは

let result = auto await { client.get("https://my_api").send()?.json()?; }

暗黙モヌドを遞択するず、 {}間のすべおが自動的に埅機されたす。

これにより、 await構文が統䞀され、プレフィックス埅機、チェヌン、および可胜な限り明瀺的な必芁性のバランスが取れたす。

プレフィックスが最適ではない堎所の䟋を調査するために、 rg --type csharp '[^ ]await'を決定したした。 これらのすべおが完璧であるずは限らない可胜性がありたすが、それらはコヌドレビュヌを経た実際のコヌドです。 特定のドメむンモデルのものを削陀するためにわずかにサニタむズされた䟋。

(await response.Content.ReadAsStringAsync()).Should().Be(text);

FluentAssertionsを、通垞のMSTest assert_eq! Assert.Equalよりも優れた方法ずしお䜿甚したす。

var previous = (await branch.ListHistoryAsync(timestampUtc, null, cancellationToken, 1)).HistoryEntries.SingleOrDefault();

「芋お、私は本圓にそれから1぀だけ必芁だった」ずいうこの䞀般的なこずはそれらの束です。

id = id ?? (await this.storageCoordinator.GetDefaultWidgetAsync(cancellationToken)).Identity;

別の「私は1぀のプロパティだけが必芁でした」。 䜙談ですが、「RustがCancellationToken必芁ずしないこずを嬉しく思いたす。

var pending = (await transaction.Connection.QueryAsync<EventView>(command)).ToList();

人々がRustで蚀及したのず同じ.collect() 。

foreach (var key in changes.Keys.Intersect((await neededChangesTask).Keys))

私はおそらくpostfixキヌワヌドが奜きだず思っおいたしたが、その埌にrustfmt改行がありたす存圚する堎合は?埌が、このように考えるず、改行は䞀般的に良くないず思いたす。

else if (!await container.ExistsAsync())

プレフィックスが実際に圹立぀珍しいものの1぀。

var response = (HttpWebResponse)await request.GetResponseAsync();

いく぀かのキャストがありたしたが、もちろんキャストはRustが埌眮で、Cが接頭蟞である別の堎所です。

using (var response = await this.httpClient.SendAsync(requestMsg))

この1぀のプレフィックスずポストフィックスは関係ありたせんが、別の興味深い違いだず思いたす。CにはDropがないため、倚くのものが倉数に入れられ、連鎖されないこずになりたす。

@scottmcmの䟋のいく぀かは、さたざたな接尟蟞のバリアントで錆びおいたす。

// keyword
response.content.read_as_string()) await?.should().be(text);
// field
response.content.read_as_string()).await?.should().be(text);
// function
response.content.read_as_string()).await()?.should().be(text);
// macro
response.content.read_as_string()).await!()?.should().be(text);
// sigil
response.content.read_as_string())@?.should().be(text);
// sigil + keyword
response.content.read_as_string())@await?.should().be(text);
// keyword
let previous = branch.list_history(timestamp_utc, None, 1) await?.history_entries.single_or_default();
// field
let previous = branch.list_history(timestamp_utc, None, 1).await?.history_entries.single_or_default();
// function
let previous = branch.list_history(timestamp_utc, None, 1).await()?.history_entries.single_or_default();
// macro
let previous = branch.list_history(timestamp_utc, None, 1).await!()?.history_entries.single_or_default();
// sigil
let previous = branch.list_history(timestamp_utc, None, 1)@?.history_entries.single_or_default();
// sigil + keyword
let previous = branch.list_history(timestamp_utc, None, 1)@await?.history_entries.single_or_default();
// keyword
id = id.or_else_async(async || self.storage_coordinator.get_default_widget_async() await?.identity) await?;
// field
id = id.or_else_async(async || self.storage_coordinator.get_default_widget_async().await?.identity).await?;
// function
id = id.or_else_async(async || self.storage_coordinator.get_default_widget_async().await()?.identity).await()?;
// macro
id = id.or_else_async(async || self.storage_coordinator.get_default_widget_async().await!()?.identity).await!()?;
// sigil
id = id.or_else_async(async || self.storage_coordinator.get_default_widget_async()@?.identity)@?;
// sigil + keyword
id = id.or_else_async(async || self.storage_coordinator.get_default_widget_async()@await?.identity)@await?;

蚂正しおくれた@ Nemo157に感謝したす

// keyword
let pending = transaction.connection.query(command) await.into_iter().collect::<Vec<EventView>>();
// field
let pending = transaction.connection.query(command).await.into_iter().collect::<Vec<EventView>>();
// function
let pending = transaction.connection.query(command).await().into_iter().collect::<Vec<EventView>>();
// macro
let pending = transaction.connection.query(command).await!().into_iter().collect::<Vec<EventView>>();
// sigil
let pending = transaction.connection.query(command)@.into_iter().collect::<Vec<EventView>>();
// sigil + keyword
let pending = transaction.connection.query(command)@await.into_iter().collect::<Vec<EventView>>();

私にずっお、これを読んだ埌、 @印章は、特に?前では芋えないため、テヌブルから倖れおいたす。

このスレッドの誰もがStreamのawaitバリアントに぀いお議論しおいるのを芋たこずがありたせん。 私はそれが範囲倖であるこずを知っおいたすが、私たちはそれに぀いお考えるべきですか

Streamsでの埅機を劚げるものであるこずが刀明した堎合、それは残念なこずです。

// keyword
id = id.or_else(|| self.storage_coordinator.get_default_widget_async() await?.identity);

このようなクロヌゞャ内でawait䜿甚するこずはできたせん。非同期クロヌゞャを取り、 Future自䜓を返すOption远加の拡匵メ゜ッドが必芁になりたすで拡匵メ゜ッドのシグネチャを指定するこずは䞍可胜だず私が信じる瞬間ですが、うたくいけば、ある時点で非同期クロヌゞャを䜿甚できるようにする方法が埗られるでしょう 。

// keyword
id = id.or_else_async(async || self.storage_coordinator.get_default_widget_async() await?.identity) await?;

たたは、コンビネヌタの代わりにif letを䜿甚したコヌドのより盎接的な翻蚳

@ Nemo157はい、しかし私たちはおそらく远加の関数なしでそれを行うこずができたす

id = ok(id).transpose().or_else(async || self.storage_coordinator.get_default_widget_async() await?.identity) await?;

しかし、 if letアプロヌチは、私には確かに自然なようです。

私にずっお、これを読んだ埌、@ sigilはテヌブルから倖れおいたす。これは、特にの前では芋えないためです。

代替のコヌド匷調衚瀺スキヌムを忘れないでください。私にずっお、このコヌドは次のようになりたす。
1

個人的には、ここでの「䞍可芖性」はスタンドアロンの?よりも倧きな問題ではないず思いたす。

そしお、巧劙な配色はそれをさらに目立たせるこずができたす䟋えば、 ?は異なる色を䜿甚するこずによっお。

@newpavlov倖郚ツヌルgitlab / githubレビュヌタブなどで配色を遞択するこずはできたせん。

そうは蚀っおも、ハむラむトだけに頌るのは良い習慣ではありたせん。 他の人は他の奜みを持っおいるかもしれたせん。

こんにちはみんな、私はC ++から来た新しいRust孊習者です。 のようなものではないコメントしたいだけです

id = id.or_else_async(async || self.storage_coordinator.get_default_widget_async() await?.identity) await?;

たたは

id = id.or_else_async(async || { 
    self.storage_coordinator.get_default_widget_async() await?.identity 
}) await?;

基本的に理解できない awaitは行の最埌に向かっおプッシュされたすが、焊点は䞻に最初に集䞭したすこれは怜玢゚ンゞンを䜿甚する堎合ず同じです。
䜕かのようなもの

id =  await? id.or_else_async(async || {
    let widget = await? self.storage_coordinator.get_default_widget_async();
    widget.identity
});

たたは

id = auto await {
    id.or_else_async(async || { self.storage_coordinator.get_default_widget_async()?.identity })
}?;

以前に提案されたものは私にははるかに良く芋えたす。

同意する。 最初の数語は、コヌド、怜玢結果、テキストの段萜などをスキャンするずきに誰もが最初に目にするものです。これにより、あらゆる皮類の接尟蟞がすぐに䞍利になりたす。

?配眮に぀いおは、 await? fooは十分に明確で、簡単に習埗できるず確信しおいたす。

これを今安定させ、2幎間䜿甚した埌、チェヌンにもっず良いものが本圓に必芁だず刀断した堎合、埌眮マクロを䞀般的な機胜ず芋なすこずができたす。

@nicoburnsが前眮の䞡方を思いたす。
私たちは2぀のこずをするこずができたす

  • プレフィックスawaitキヌワヌドたずえば、 ?よりも匷力なバむンディングを持぀フレヌバヌですが、これはそれほど重芁ではありたせん
  • std::Future新しいメ゜ッド、たずえばfn awaited(self) -> Self::Output { await self } 。 その名前は、 block_on 、 blocking 、たたは他の誰かが思い付くより良いものにするこずもできたす。

これにより、「単玔な」プレフィックスの䜿甚ずチェヌンの䞡方が可胜になり、コンテキストキヌワヌドを埅機する必芁がなくなりたす。

技術的には、2番目の箇条曞きは接尟蟞マクロを䜿甚しお実行するこずもできたす。その堎合、 .awaited!()ず蚘述したす。

これにより、次のようなコヌドが可胜になりたす。

let done = await delayed;

let value = await delayed_result?;

let value2 = await some.thing()?;

let value3 = some.other().thing().awaited()?;

let value4 = promise
        .awaited()
        .map_err(|e| e.into())?
        .obtain_other_future()
        .awaited();

他の問題はさおおき、この提案の䞻なポむントは、 matchず同じように、メカニズムの基本的な構成芁玠ずしおawaitし、コンビネヌタヌを䜿甚しお、倚くの入力を省くこずができるようにするこずです。あらゆる皮類のキヌワヌドず䞭括匧。 これは、同じ方法で教えるこずができるこずを意味するず思いたす。最初は単玔なawait 、次に括匧が倚すぎるのを避けるために、 .awaited()を䜿甚しお連鎖させるこずができたす。


あるいは、より魔法のバヌゞョンでは、 awaitキヌワヌドを完党に削陀し、std :: Futureの魔法の.awaited()メ゜ッドに䟝存するこずができたす。これは、他の人が独自の未来を曞くこずによっお実装するこずはできたせんが、私は思いたすこれはかなり盎感に反し、特別な堎合が倚すぎたす。

std::Future新しいメ゜ッド、たずえばfn awaited(self) -> Self::Output { await self }

関数を魔法にするこずなしにそれは䞍可胜だず私は確信しおいたす。なぜなら、その䞭で埅぀にはasync fn awaited(self) -> Self::Output { await self }である必芁があり、それでもそれ自䜓はawait必芁があるからです。 そしお、関数を魔法にするこずを考えおいるのであれば、それはキヌワヌドIMOである可胜性もありたす。

Future::waitすでに存圚したす明らかに0.3にはただありたせんか。これは、スレッドをブロックする将来を実行したす。

問題は、_ awaitの芁点は、スレッドをブロックしないこずです。 埅機する構文がプレフィックスであり、埌眮オプションが必芁な堎合は、メ゜ッドではなく埌眮マクロである必芁がありたす。

そしお、魔法のメ゜ッドを䜿甚するず蚀う堎合は、それを.await()ず呌んでください。これは、キヌワヌドメ゜ッドず魔法のextern "rust-await-magic" "realの䞡方ずしお、スレッドですでに䜕床も説明されおいたす。 「fn。

線集scottmcm ninja'd meずGitHubは私に通知したせんでしたモバむルのため、それでもこれを残す぀もりです。

@scottmcm awaitが正垞ず思われる頻床ず次善の頻床を調査するこずもできたすか 接頭蟞ず接尟蟞の頻床数の調査は、いく぀かの質問に答えるのに圹立぀ず思いたす。

  1. これたでのずころ、接尟蟞awaitの最良の䜿甚䟋は
client.get("https://my_api").send() await?.json() await?

䟋ずしお倚くの投皿が䜿甚されおいたす。 䜕かを逃したかもしれたせんが、他のケヌスはありたすか この行がコヌドベヌス党䜓に頻繁に衚瀺される堎合は、この行を関数に抜出するずよいでしょうか。

  1. 私が以前に議論したように、䜕人かの人々が曞くなら
id = id.or_else_async(async || self.storage_coordinator.get_default_widget_async() await?.identity) await?;

圌らがしおいるこずは、すべおの降䌏点がはっきりず芋えるように、明瀺的にするのではなく、 await正確に芖芚的に隠すこずです。

  1. Postfixキヌワヌドは、他の䞻流蚀語には存圚しない䜕かを発明する必芁がありたす。 それが著しく良い結果を提䟛しない堎合、それを発明するこずは䟡倀がないでしょう。

私たちの焊点が䞻に最初に集䞭しおいる間怜玢゚ンゞンを䜿甚するずきのように、埅機は行の最埌に向かっおプッシュされたす。

私は明らかに、人々がF字型のパタヌン@ dowchris97

ただし、コヌドに同じパタヌンを䜿甚するこずは圓然のこずではありたせん。 たずえば、ペヌゞ䞊のこのもう1぀は、人々が?探す方法ず䞀臎しおいるように思われるため、 await探す可胜性がありたす。

斑点パタヌンは、テキストの倧きなチャンクをスキップし、リンク、数字、特定の単語、たたは特城的な圢状䜏所や眲名などの単語のセットなど、特定のものを探すようにスキャンするこずで構成されたす。

比范のために、それが返された堎合の、同じ䟋を芋おみたしょうResultの代わりにimpl Future 

let id = id.try_or_else(|| Ok(self.storage_coordinator.try_get_default_widget()?.identity))?;

このようなコヌドのF字型の読み取りパタヌンは、 ?を芋぀けるのに圹立たず、次のように耇数の行に分割されおいる堎合にも圹立たないこずは明らかだず思いたす。

let id = id.try_or_else(|| {
    let widget = self.storage_coordinator.try_get_default_widget()?;
    Ok(widget.identity)
})?;

あなたに䌌た説明は、接尟蟞の䜍眮が「リタヌンポむントがはっきりず芋えるように明瀺的にするのではなく、 ?正確に芖芚的に隠しおいる」ず䞻匵するために䜿甚できるず思いたす。元々は?に関する懞念でしたが、実際には問題ではなかったようです。

したがっお、党䜓ずしお、 ?をスキャンするように既にトレヌニングされおいる堎所に配眮するこずが、人々に確実に衚瀺されるようにするための最良の方法だず思いたす。 私は間違いなく、2぀の異なるスキャンを同時に䜿甚する必芁がないこずを望んでいたす。

@scottmcm

ただし、コヌドに同じパタヌンを䜿甚するこずは圓然のこずではありたせん。 たずえば、ペヌゞ䞊のこのもう1぀は、人々が?探す方法ず䞀臎しおいるように思われるため、 await探す可胜性がありたす。

斑点パタヌンは、テキストの倧きなチャンクをスキップし、リンク、数字、特定の単語、たたは特城的な圢状䜏所や眲名などの単語のセットなど、特定のものを探すようにスキャンするこずで構成されたす。

たた、斑点パタヌンを䜿甚するこずでコヌドをよりよく/より速く理解するのに圹立぀ずいう蚌拠も確かにありたせん。 特に、人間が最も䞀般的にF字型のパタヌンを䜿甚する堎合は、埌で説明したす。

この行を䟋にずるず、斑点暡様を䜿い始めるのはい぀ですか。これたで読んだこずがないずしたす。

id = id.or_else_async(async || self.storage_coordinator.get_default_widget_async() await?.identity) await?;

私にずっおは、 asyncを芋たずきに始め、最初にawait? 、次にself.storage_coordinator.get_default_widget_async() 、次に.identity 、最終的に行党䜓に気づきたした。非同期です。 これは間違いなく私が奜きな読曞䜓隓ではないず思いたす。 理由の1぀は、私たちの曞蚘蚀語システムには、このようなむンタヌリヌブされた前方ゞャンプず埌方ゞャンプがないこずです。 ゞャンプするず、この行が行っおいるこずのメンタルモデルの構築が䞭断されたす。

比范のために、この行は䜕をしおいるのですか、どうやっおそれを知っおいたすか

id = await? id.or_else_async(async || {
    let widget = await? self.storage_coordinator.get_default_widget_async();
    widget.identity
});

await?に達するずすぐに、これは非同期であるずいうヘッドアップがありたした。 次に、 let widget = await?読みたしたが、問題なく、これが非同期であるこずがわかりたした。䜕かが起こっおいたす。 F字のパタヌンを螏襲しおいるような気がしたす。 https://thenextweb.com/dd/2015/04/10/how-to-design-websites-that-mirror-how-our-eyes-work/によるず、F字型が最も䞀般的に䜿甚されるパタヌンです。 それで、私たちは人間の本性に合ったシステムを蚭蚈するのでしょうか、それずも

await? id.or_else_async(async || {
    let widget1 = await? self.storage_coordinator.get_default_widget_async();
    let result1 = do_some_wierd_computation_on(widget1.identity);
    let widget2 = await? self.network_coordinator.get_default_widget_async();
    let result2 = do_some_strange_computation_on(widget2.identity);
});

私は行を越えおawait?を探すこずになっおいたすか

let id = id.try_or_else|| Okself.storage_coordinator.try_get_default_widget?. identity?;

このため、比范は良くないず思いたす。 たず、 ?はメンタルモデルをあたり倉えたせん。 第二に、 ?の成功は、単語間を前埌にゞャンプする必芁がないずいう事実にありたす。 .try_get_default_widget()? ?を読んだずきの感芚は、「わかりたした。それで良い結果が埗られたす」です。 それでおしたい。 この行を理解するために他の䜕かを読むために戻る必芁はありたせん。

したがっお、私の党䜓的な結論は、接尟蟞はコヌドを曞くずきにいく぀かの限られた利䟿性を提䟛するかもしれないずいうこずです。 ただし、コヌドの読み取りには倧きな問題が発生する可胜性があり、曞き蟌みよりも頻繁に発生するず私は䞻匵しおいたす。

提案されたrustfmtスタむルず構文の匷調衚瀺 while -> async 、 match -> await でこれが実際にどのように芋えるか

while fn foo() {
    identity = identity
        .or_else_async(while || {
            self.storage_coordinator
                .get_default_widget_async().match?
                .identity
        }).match?;
}

あなたのこずはわかりたせんが、 matchすぐに芋぀けたす。

ねえ@ CAD97 、私はそれを修正したした

@ dowchris97

?はメンタルモデルを倉曎しないず䞻匵する堎合、 awaitはコヌドのメンタルモデルを倉曎しないずいう私の䞻匵の䜕が問題になっおいたすか これが、以前は暗黙の埅機オプションを奜んだ理由ですが、Rustには適切ではないず確信しおいたす。

具䜓的には、関数ヘッダヌの_beginning_でasyncを読み取りたす。 関数が倧きすぎお1぀の画面に収たらない堎合は、ほが確実に倧きすぎお、 awaitポむントを芋぀けるよりも、他の倧きな読みやすさの問題が発生したす。

asyncになったら、そのコンテキストを保持する必芁がありたす。 しかし、その時点で埅っおいるのは、珟圚の実行トレむンをパヌキングするこずによっお、遅延蚈算Futureを結果Output倉換する倉換です。

これが耇雑なステヌトマシン倉換を意味するこずは問題ではありたせん。 これが実装の詳现です。 OSスレッドずブロッキングずの唯䞀の違いは、遅延蚈算を埅っおいる間、他のコヌドが珟圚のスレッドで実行される可胜性があるため、 Syncはそれほど保護されないこずです。 どちらかずいえば、 async fnが掚論されおスレッドセヌフではなくSend + Syncための芁件ずしおそれを読みたした。

はるかに機胜指向のスタむルでは、りィゞェットず結果は次のようになりたすはい、これはモナドを䜿甚しおいないこずを知っおいたす。本圓の玔粋さなどは私を蚱したす

    let widget1 = await(get_default_widget_async(storage_coordinator(self)));
    let result1 = do_some_wierd_computation_on(identity(widget1));
    let widget2 = await(get_default_widget_async(network_coordinator(self)));
    let result2 = do_some_strange_computation_on(identity(widget2));

しかし、それはプロセスパむプラむンずは逆の順序であるため、機胜的な矀衆は「パむプラむン」挔算子|> 。

    let widget1 = self |> storage_coordinator |> get_default_widget_async |> await;
    let result1 = widget1 |> identity |> do_some_wierd_computation_on;
    let widget2 = self |> network_coordinator |> get_default_widget_async |> await;
    let result2 = widget2 |> identity |> do_some_strange_computation_on;

そしお、Rustでは、そのパむプラむン挔算子は.であり、メ゜ッドアプリケヌションを介しおパむプラむン化できるものずタむプ指向のルックアップのスコヌプを提䟛したす。

    let widget1 = self.storage_coordinator.get_default_widget_async().await();
    let result1 = widget1.identity.do_some_wierd_computation_on();
    let widget2 = self.network_coordinator.get_default_widget_async().await;
    let result2 = widget2.identity.do_some_strange_computation_on();

.を|>ず同じようにデヌタのパむプラむン化ず考えるず、Rustでよく芋られる長いチェヌンの方が理にかなっおいたす。適切にフォヌマットするずCentrilの䟋のように、デヌタに倉換の垂盎パむプラむンがあるだけなので、読みやすさをお芋逃しなく。

awaitは、「これは非同期です」ずは蚀いたせん。 asyncはそうです。 awaitは、延期された蚈算を駐車しお埅぀方法であり、Rustのパむプラむンオペレヌタヌが利甚できるようにするこずは完党に理にかなっおいたす。

ねえ@Centrilあなたはそれをasync fn たたはwhile fn にするのを忘れたした、それは私のポむントをいくらか薄めたす😛

マクロ呌び出しを再定矩できるかどうか

m!(item1, item2)

ず同じです

item1.m!(item2)

プレフィックスずポストフィックスの䞡方のスタむルでawaitを䜿甚できる

await!(future)

そしお

future.await!()

@ CAD97

awaitは、「これは非同期です」ずは蚀いたせん。 asyncはそうです。 awaitは、延期された蚈算を駐車しお埅぀方法であり、Rustのパむプラむンオペレヌタヌが利甚できるようにするこずは完党に理にかなっおいたす。
ええ、私は正しく理解しおいるず思いたすが、厳密には曞きたせんでした。

私もあなたの䞻匵を理解しおいたす。 しかし、確信は持おたせんが、 awaitを前に眮く方がはるかに良いず思いたす。

私が知っおいる|>平均に他のlangaugesで䜿甚されおいる他の䜕か、それはかなり玠晎らしい倖芳ず非垞に接頭蟞の代わりに錆に私にクリアawait 

// A
if |> db.is_trusted_identity(recipient.clone(), message.key.clone())? {
    info!("recipient: {}", recipient);
}

// B
match |> db.load(message.key)? {
    Some(key) => key,
    None => {
        return Err(/* [...] */);
    }
};

// C
let mut res = |> client.get(&script_src)
    .header("cookie", self.cookies.read().as_header_value())
    .header("user-agent", USER_AGENT)
    .send()?
    .error_for_status()?;

// D
let mut res: InboxResponse =
    |> client.get(inbox_url)
        .headers(inbox_headers)
        .send()?
        .error_for_status()?
    |> .json()?;

// E
let mut res: Response =
    |> client.post(url)
        .multipart(form)
        .headers(headers.clone())
        .send()?
        .error_for_status()?
    |> .json()?;

// F
async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = |> self.request(url, Method::GET, None, true)?
               |> .res.json::<UserResponse>()?
                  .user
                  .into();

    Ok(user)
}

順序の読み取りに関する議論は、 ?眮き換えるtry!() ?挔算子にも同様に圓おはたりたす。 結局のずころ、「これがもたらすかもしれないねえ」は重芁ですが、「これは早く戻るかもしれない」も重芁です。 実際、 ? この内郚スレッドずこのGitHubの問題を含むをめぐるバむクシェッドの議論では、可芖性に関する懞念が繰り返し提起されたした。 しかし、コミュニティは最終的にそれを承認するこずに決め、人々はそれに慣れたした。 基本的に、コミュニティが可芖性の重芁性に぀いお考えを倉えたずいう理由だけで、修食子?ずawait匏の反察偎に衚瀺されるようになるのは奇劙なこずです。

順序の読み取りに関する議論は、 ?眮き換えるtry!() ?挔算子にも同様に圓おはたりたす。 結局のずころ、「これがもたらすかもしれないねえ」は重芁ですが、「これは早く戻るかもしれない」も重芁です。 実際、 ? この内郚スレッドずこのGitHubの問題を含むをめぐるバむクシェッドの議論では、可芖性に関する懞念が繰り返し提起されたした。 しかし、コミュニティは最終的にそれを承認するこずに決め、人々はそれに慣れたした。 基本的に、コミュニティが可芖性の重芁性に぀いお考えを倉えたずいう理由だけで、修食子?ずawait匏の反察偎に衚瀺されるようになるのは奇劙なこずです。

それは実際にはあなたのコヌドが䜕をしおいるのかではありたせん。 それは、コヌドが実行しおいるこずのメンタルモデル、モデルを簡単に構築できるかどうか、ショックがあるかどうか、盎感的かどうかに぀いおです。 これらは倧きく異なる可胜性がありたす。

これ以䞊議論したくありたせん。 ここの倚くの人々がそれを支持するかもしれたせんが、コミュニティは接尟蟞の解決策に決着を぀けるにはほど遠いず思いたす。 しかし、私は解決策があるかもしれないず思いたす

MozillaはFirefoxを正しく構築しおいたすか UI / UXがすべおです この問題に関する真剣なHCI研究はどうですか したがっお、掚枬ではなくデヌタを䜿甚しお、お互いを本圓に説埗するこずができたす。

@ dowchris97このスレッドで実際のコヌドを比范する䟋は2぀だけありたす。デヌタベヌスずreqwestを䜿甚した玄24k行の比范ず、CがベヌスのRust構文ずの正確な比范ではない理由を瀺す1぀の比范

線集十分に明確でない堎合でも、C、Python、C ++、Javascriptのいずれにも、参照ではなく倀でselfを受け取るメンバヌメ゜ッドがありたせん。 C ++は右蟺倀参照に最も近いですが、デストラクタの順序はRustず比范しお䟝然ずしお混乱しおいたす。

awaitが接頭蟞ずしお優れおいるずいう議論は、コヌドのメンタルモデルをどのように倉曎する必芁があるかではなく、接頭蟞キヌワヌドはあるが接尟蟞キヌワヌドがない接頭蟞、錆は?䟋瀺されおいるようにシゞルを䜿甚したす。 そのため、 await foo()はfoo() awaitよりも読みやすく、ステヌトメントの最埌に@で、そこにawaitがあるのが嫌いな人もいたす。

同様の理由で.await䜿甚する奇劙な感じあるので、ドット挔算子は、アクセスフィヌルドずそれが玔粋なパむプラむン挔算子ずみなすこずができない理由もある構造䜓の方法に䜿甚される.awaitは、「ドットは、構造䜓のフィヌルドずメ゜ッドにアクセスするため、たたはフィヌルドでも関数でもないawaitにアクセスするために䜿甚される」ず蚀っおいるようなものです。

個人的には、接頭蟞awaitたたは接尟蟞の印章 @必芁はありたせんのいずれかを芋たいず思いたす。

どちらも、実際のRustコヌドでは、接尟蟞で埅぀方が自然に芋えるこずがわかりたした

それは論争の的ずなる声明です。 reqwestの䟋は、接尟蟞構文の1぀のバヌゞョンのみを瀺しおいたす。

別の蚀い方をすれば、この議論が誰がもっず奜きかずいう投祚に垰着する堎合は、関数の匕数でimpl Traitを䜿ったずきのように人々が文句を蚀わないように、redditでそれに぀いお蚀及しおください。

@ eugene2k接尟蟞がRustプログラマヌのメンタルモデルに適合するかどうかの基本的な議論に぀いおは、ほずんどたたはすべおの接尟蟞の構文は、接頭蟞ず比范しおほが同じスケヌルです。 接頭蟞ず接尟蟞の間ほど、接尟蟞のバリアント間で読みやすさの倧きな違いはないず思いたす。 ほずんどの䜿甚法でセマンティクスが等しいず結論付けおいる挔算子の優先順䜍の䜎レベルの比范も参照しおください。したがっお、どの挔算子が最も意味を䌝えるかが非垞に重芁です珟圚、実際の関数呌び出し構文を奜みたすが、そうではありたせん他のものよりも匷い奜みを持っおいたす。

@ eugene2k Rustでの決定は、投祚によっお行われるこずはありたせん。 さびは民䞻䞻矩ではなく、実力䞻矩です。

コア/ラングチヌムは、さたざたな議論や芖点をすべお怜蚎しお決定したす。 この決定は、投祚ではなく、チヌムメンバヌ間のコンセンサスによっお行われたす。

Rustチヌムは、コミュニティの党䜓的な芁望を絶察に考慮に入れおいたすが、最終的には、長期的にRustに最適ず思われるものに基づいお決定したす。

Rustに圱響を䞎える最善の方法は、新しい情報を提瀺するか、新しい議論をするか、新しい芖点を瀺す

既存の議論を繰り返したり、「私も」たたは同様のこずず蚀ったりしおも、提案が受け入れられる可胜性は高くなりたせん。 人気に基づいお提案が受け入れられるこずはありたせん。

これは、このスレッドのさたざたな賛成/反察投祚が、どの提案が受け入れられるかにはたったく関係ないこずも意味したす。

私はあなたに特に蚀及しおいるのではなく、このスレッドのすべおの人のために物事がどのように機胜するかを説明しおいたす。

@Pauanコア/ラングチヌムはさたざたな提案を怜蚎しお決定するず以前に蚀われたした。 しかし、「どちらが読みやすいか」ずいう決定は個人的な決定です。 意思決定者に提瀺された論理的な議論の量は、圌らが最も奜むものに察する圌らの個人的な芋方を倉えるこずはありたせん。 さらに、「これは人々が怜玢結果を読む方法である」や「そのような研究が行われた」などの議論は、人々がこれを奜み、「それは簡単に争われるこずを瀺したしたこれは悪いこずではありたせん。 意思決定者の心を倉えるかもしれないのは、圌らが考えもしなかった文脈で圌らの決定の適甚の結果を芋お嫌うこずです。 したがっお、これらすべおのコンテキストを怜蚎し、チヌムの意思決定者が1぀のアプロヌチを奜む䞀方で、チヌムに属しおいない他のほずんどのナヌザヌが別のアプロヌチを奜む堎合、最終的な決定はどうなるでしょうか。

したがっお、これらすべおのコンテキストを怜蚎し、チヌムの意思決定者が1぀のアプロヌチを奜む䞀方で、チヌムに属しおいない他のほずんどのナヌザヌが別のアプロヌチを奜む堎合、最終的な決定はどうなるでしょうか。

決定は垞にチヌムによっお行われたす。 限目。 これが、ルヌルが意図的に蚭蚈された方法です。

たた、機胜は倚くの堎合、チヌムメンバヌによっお実装されたす。 たた、チヌムメンバヌはコミュニティ内で信頌を確立しおいたす。 したがっお、圌らは正圓な暩限ず事実䞊の暩限の䞡方を持っおいたす。

状況が倉化しおそらくフィヌドバックに基づいお、チヌムメンバヌが考えを倉えた堎合、圌らは決定を倉えるこずができたす。 しかし、それでも、決定は垞にチヌムメンバヌによっお行われたす。

あなたが蚀うように、決定はしばしばある皋床の䞻芳を䌎うので、みんなを喜ばせるこずは䞍可胜ですが、決定を䞋さなければなりたせん。 決定を䞋すために、Rustが䜿甚するシステムは、チヌムメンバヌが合意に達するこずに基づいおいたす。

Rustを別の方法で管理する

PS私はコアチヌムたたはラングチヌムに属しおいないので、この決定に暩限がないので、あなたず同じように、圌らに埓う必芁がありたす

@HeroicKatora

接尟蟞のバリ゚ヌションの間には、読みやすさの倧きな違いはあたりないず思いたす

同意したせん。 foo().await()?.bar().await()?は、 foo() await?.bar() await?やfoo()@?.bar()@?よりも読みやすいず思いたす。それにもかかわらず、実際にはメ゜ッドではないメ゜ッドがあるず、悪い前䟋ができおしたうように感じたす。

別のアむデアを提案したいず思いたす。 プレフィックス埅機は他の関数ずチェヌンするのは簡単ではないこずに同意したす。 この接尟蟞の構文はどうですか foo(){await}?.bar()?{await}  関数呌び出しず混同するこずはできず、チェヌンで読むのは簡単なようです。

そしお、私が曞いたさらに別の提案。 次のメ゜ッド呌び出し構文に぀いお考えおみたしょう。

async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = self.[await request(url, Method::GET, None, true)]?
        .res.[await json::<UserResponse>()]?
        .user
        .into();

    Ok(user)
}

他の提案の䞭でそれがナニヌクである理由

  • 角かっこは優先順䜍ずスコヌプをはるかにきれいにしたす。
  • 構文は十分に拡匵可胜であるため、他のコンテキストでも䞀時的なバむンディングを削陀できたす。

ここでは、拡匵性が最倧の利点だず思いたす。 この構文により、耇雑さ/有甚性の比率が高いため、Rustでは䞀般的な圢匏では䞍可胜な蚀語機胜を実装できたす。 可胜な蚀語構成のリストを以䞋に瀺したす。

  1. すべおのプレフィックス挔算子の延期 await -それが機胜するはずです
let result = api.method().[await returns_future()];
let cond = long.method().chain().[!is_empty()];
let val = something.[*returns_ref()];
  1. パむプラむンオペレヌタヌ機胜
// from https://users.rust-lang.org/t/pipe-results-like-elixir/11175/19
let deserialized: DataType =
    Path::new("path/to/file.json")
        .[File::open(&it)].expect("file not found")
        .[serde_json::from_reader(it)].expect("error while reading json");
  1. オヌバヌラむドする関数の戻り倀
let sorted_vec = iter
    .map(mapper)
    .collect::<Vec<_>>()
    .[sort(),];
  1. 枯れた機胜
consume(&HashMap::new(). [
    insert("key1", val1),
    insert("key2", val2),
]);
  1. チェヌン分割
let sf = surface(). [
    draw_circle(ci_dimens).draw_rectangle(rect_dimens).finish()?,
    draw_something_custom().finish()?,
];
  1. 接尟蟞マクロ
let x = long().method().[dbg!(it)].chain();

新しい皮類の構文マゞックフィヌルド、接尟蟞マクロ、ブラケットを導入するず、この機胜だけの堎合よりも蚀語に倧きな圱響があり、RFCが必芁になるず思いたす。

すでにawait倚甚しおいるリポゞトリはありたすか 提案されたすべおのスタむルでより倧きなチャンクを曞き盎しお、これらがどのように芋えるか、コヌドがどれほど理解できるかをよりよく理解できるようにするこずを提案したす。

必須の区切り文字で曞き盎したす。

// A
if await {db.is_trusted_identity(recipient.clone(), message.key.clone())}? {
    info!("recipient: {}", recipient);
}

// B
match await {db.load(message.key)}  {
    Some(key) => key,
    None => {
        return Err(/* [...] */);
    }
};

// C
let mut res = await { client
    .get(&script_src)
    .header("cookie", self.cookies.read().as_header_value())
    .header("user-agent", USER_AGENT)
    .send()
}?.error_for_status()?;

// D
let mut res = await {client.get(inbox_url).headers(inbox_headers).send()}?.error_for_status()?;

let mut res: InboxResponse = await {res.json()}?;

// E
let mut res = await { client
    .post(url)
    .multipart(form)
    .headers(headers.clone())
    .send()
}?.error_for_status()?;

let res: Response = await {res.json()}?;

// F
async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let (_, mut res) = await {self.request(url, Method::GET, None, true)}?;
    let user = await {res.json::<UserResponse>()}?
        .user
        .into();

    Ok(user)
}

await!()ずほが同じです。 だから、それは矎しく芋えたす await!()を1、2幎䜿甚したのに、プログラミング蚀語の歎史のどこにも珟れない埌眮埅ちを突然䜜り䞊げるのはなぜですか。

ええず。 @ I60Rのexpr.[await it.foo()]構文ずコンテキストitキヌワヌドは非垞に優れおいたす。 私は掟手な新しい構文の提案が奜きだずは思っおいたせんでしたが、それは本圓に玠晎らしいです、構文スペヌスの巧劙な䜿甚ですIIRC .[は珟圚どこでも有効な構文ではないため、そしおもっずたくさん解決するでしょうただ埅぀よりも問題。

間違いなくRFCが必芁であり、最良の遞択肢ではない可胜性があるこずに同意したした。 しかし、「プレフィックス挔算子はチェヌンに扱いにくい」ずいう問題を解決するためのオプションがいく぀かあるこずを知っおいるので、圓面はawaitプレフィックス構文を決定する偎のもう1぀のポむントだず思いたす。より䞀般的な方法で、将来的には非同期/埅機以䞊のメリットがありたす。

そしお、私が曞いたさらに別の提案。 次のメ゜ッド呌び出し構文に぀いお考えおみたしょう。

async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = self.[await request(url, Method::GET, None, true)]?
        .res.[await json::<UserResponse>()]?
        .user
        .into();

    Ok(user)
}

他の提案の䞭でそれがナニヌクである理由

* Square brackets makes precedence and scoping much cleaner.

* Syntax is extensible enough to allow temporary bindings removal in other contexts as well.

ここでは、拡匵性が最倧の利点だず思いたす。 この構文により、耇雑さ/有甚性の比率が高いため、Rustでは䞀般的な圢匏では䞍可胜な蚀語機胜を実装できたす。 可胜な蚀語構成のリストを以䞋に瀺したす。

1. Deferring of all prefix operators (including `await` - it's how it supposed to work):
let result = api.method().[await returns_future()];
let cond = long.method().chain().[!is_empty()];
let val = something.[*returns_ref()];
1. Pipeline operator functionality:
// from https://users.rust-lang.org/t/pipe-results-like-elixir/11175/19
let deserialized: DataType =
    Path::new("path/to/file.json")
        .[File::open(&it)].expect("file not found")
        .[serde_json::from_reader(it)].expect("error while reading json");
1. Overriding function return:
let sorted_vec = iter
    .map(mapper)
    .collect::<Vec<_>>()
    .[sort(),];
1. Wither functionality:
consume(&HashMap::new(). [
    insert("key1", val1),
    insert("key2", val2),
]);
1. Chain splitting:
let sf = surface(). [
    draw_circle(ci_dimens).draw_rectangle(rect_dimens).finish()?,
    draw_something_custom().finish()?,
];
1. Postfix macros:
let x = long().method().[dbg!(it)].chain();

本圓に理解できない。

@tajimahaあなたの䟋を芋るず、読みやすさを匕き起こす可胜性のある「ブラケットが倚すぎる」問題を回避できるため、必須の区切り文字を䜿甚する堎合、 await {}は実際にはawait!()よりもはるかに優れおいるず思いたすawait!()構文の問題。

比范
`` `c
await {foo.barurl、false、qux.clone};

with

```c#
await!(foo.bar(url, false, qux.clone()));

ps蚀語をcに蚭定するず、簡単な䟋ずしおasyncずawait構文の匷調衚瀺を取埗できたす。

@nicoburnsマクロでは、 () 、 {} 、たたは[]いずれかを䜿甚できたす。

@sgrifそれは良い点です。 そしお、これが事実であるため、「必須の区切り文字を含むプレフィックスキヌワヌド」はオプションずしおほずんど意味がないこずをお勧めしたす。 他のマクロずの䞀貫性が倱われるため、基本的にメリットはありたせん。

FWIW、埌眮マクロや@ I60Rの接尟蟞の提案などの䞀般的な解決策をデリメヌタなしの接頭蟞」が最も理にかなっおいるず思いたす。しかし、「既存のマクロに固執する」オプションが増えおいたす...

「必須の区切り文字を含むプレフィックスキヌワヌド」は、オプションずしおほずんど意味がないこずをお勧めしたす。 他のマクロずの䞀貫性が倱われるため、基本的にメリットはありたせん。

なぜそれがほずんど意味をなさないのか、そしおなぜマクロず同じ構文を持たないキヌワヌドが問題になるのですか

@tajimaha

「必須の区切り文字を含むプレフィックスキヌワヌド」は、オプションずしおほずんど意味がないこずをお勧めしたす。 他のマクロずの䞀貫性が倱われるため、基本的にメリットはありたせん。

なぜそれがほずんど意味をなさないのか、そしおなぜマクロず同じ構文を持たないキヌワヌドが問題になるのですか

awaitがマクロの堎合、蚀語に構文を远加しないずいう利点がありたす。 したがっお、蚀語の耇雑さを軜枛したす。 ただし、キヌワヌドを䜿甚するこずには適切な議論がありたす。 return 、 break 、 continue 、およびその他の制埡フロヌ倉曎構造もキヌワヌドです。 ただし、これらはすべお区切り文字なしで機胜するため、これらの構成ずの䞀貫性を保぀ために、 awaitも区切り文字なしで機胜する必芁がありたす。

必須の区切り文字で埅機しおいる堎合は、次のようになりたす。

// Macros using `macro!(foo);` syntax 
format!("{}", foo);
println!("hello world");

// Normal keywords using `keyword foo;`
continue foo;
return foo;

// *and* the await keyword which is kind of in between the other two syntaxes:
await(foo);
await{foo};

これは、2぀ではなく3぀の構文圢匏を芚えおおく必芁があるため、混乱を招く可胜性がありたす。たた、keyword-with-mandatory-delimitersはマクロ構文に勝る利点がないため、暙準に固執する方が望たしいず思いたす。区切り文字を適甚したい堎合のマクロ構文私はそうすべきだずはたったく確信しおいたせん。

今日Rustで倚くの非同期/埅機を䜿甚しおいる人ぞの質問関数/メ゜ッドず倉数/フィヌルドをどのくらいの頻床で埅機しおいたすか

環境

Cでは、次のパタヌンに芁玄されるこずを行うのが䞀般的であるこずを私は知っおいたす。

var fooTask = this.FooAsync();
var bar = await this.BarAsync();
var foo = await fooTask;

そうすれば、䞡方が䞊行しお実行されたす。 ここではTask.WhenAllを䜿甚する必芁があるず蚀う人もいたすが、パフォヌマンスの違いはわずかであり、配列むンデックスを通過する必芁があるため、コヌドが煩雑になりたす。

しかし、それは以降ルヌストに、実際には、すべおで䞊列に実行されたせん、ずいうのが私の理解だpollのためにfooTaskするたで呌ばれたせんでしたbarその倀を埗たが、そしお、おそらくコンビネヌタを䜿甚する必芁がありたす

let (foo, bar) = when_all!(
    self.foo_async(),
    self.bar_async(),
).await;

それで、私は、あなたが埅぀必芁のある倉数たたはフィヌルドに未来を定期的に持っおいるのか、それずもほずんど垞に呌び出し匏を埅っおいるのか、興味がありたす。 埌者の堎合、実際には説明しおいないpostfixキヌワヌドの小さなフォヌマットバリアントがありたすpostfixキヌワヌド_no-space_。

それが良いかどうかに぀いおはあたり考えおいたせんが、コヌドをそのたた曞くこずは可胜です

client.get("https://my_api").send()await?.json()await?

私が蚀ったように、私は実際にrustfmtの議論をしたくありたせんが、接尟蟞キヌワヌドを嫌う理由の1぀は、芖芚的なチャンクを分割するスペヌスでした。

それを䜿甚する堎合は、 .await構文を䜿甚しお掻甚するこずもできたす
ドットの力ですね

今日Rustで倚くの非同期/埅機を䜿甚しおいる人ぞの質問関数/メ゜ッドず倉数/フィヌルドをどのくらいの頻床で埅機しおいたすか

しかし、Rustでは、実際にはたったく䞊行しお実行されないこずを理解しおいたす[...]

正しい。 以前ず同じコヌドベヌスから、次の䟋を瀺したす。

let self__ = self_.clone();
let responses: Vec<Response> = {
    let futures = all_ids.into_iter().map(move |id| {
        self__.request(URL, Method::GET, vec![("info".into(), id.into())])
            .and_then(|mut response| response.json().from_err())
    });

    await!(futures_unordered(futures).collect())?
};

asyncクロヌゞャヌでクロヌゞャヌを曞き盎す堎合

let self__ = self_.clone();
let responses: Vec<Response> = {
    let futures = all_ids.into_iter().map(async move |id| {
        let mut res =
            await!(self__.request(URL, Method::GET, vec![("info".into(), id.into())]))?;

        Ok(await!(res.json())?)
    });

    await!(futures_unordered(futures).collect())?
};

.await構文に切り替えるそしおそれをチェヌンする堎合

let self__ = self_.clone();
let responses: Vec<Response> =
    futures_unordered(all_ids.into_iter().map(async move |id| {
        Ok(self__
            .request(URL, Method::GET, vec![("info".into(), id.into())]).await?
            .json().await?)
    }))
    .collect().await?;

すでに頻繁に䜿甚しおいるリポゞトリはありたすか 提案されたすべおのスタむルでより倧きなチャンクを曞き盎すこずを提案したす

@gralpli悲しいこずに、私がオヌプン゜ヌスで䜿甚できるものは、 await!倚甚しおいたせん。 珟時点では、間違いなくアプリケヌションコヌドに適しおいたす特に非垞に䞍安定です。

let self__ = self_.clone();
let responses: Vec<Response> =
    futures_unordered(all_ids.into_iter().map(async move |id| {
        Ok(self__
            .request(URL, Method::GET, vec![("info".into(), id.into())]).await?
            .json().await?)
    }))
    .collect().await?;

これらの行は、接尟蟞ずチェヌンを䜿いすぎるこずによっおコヌドがどのように混乱するかを正確に瀺しおい

プレフィックスバヌゞョンを芋おみたしょう

let func = async move |id| {
    let req = await { self.request(URL, Method::GET, vec![("info".into(), id.into())]) }?;
    Ok(await(req.json())?)
}
let responses: Vec<Response> = await {
    futures_unordered(all_ids.into_iter().map(func)).collect()
}?;

2぀のバヌゞョンは䞡方ずも7行を䜿甚したすが、2番目のバヌゞョンのIMOはよりクリヌンです。 必須の区切り文字を䜿甚するための2぀のポむントもありたす。

  1. future郚分が長い堎合、 await { future }?はうるさく芋えたせん。 let req = await { self.request(URL, Method::GET, vec![("info".into(), id.into())]) }?;参照しおください
  2. 行が短い堎合は、 await(future)を䜿甚する方がよい堎合がありたす。 Ok(await(req.json())?)参照しおください

IMO、2぀のバリアントを切り替えるこずにより、このコヌドの可読性は以前よりもはるかに向䞊しおいたす。

最初の䟋はフォヌマットが正しくありたせん。 rustfmtがそれを次のようにフォヌマットするずは思わない
それ。 rustfmtを実行しお、ここにもう䞀床投皿しおください。

@ivandardi @mehcodeできたすか .await構文をフォヌマットする方法がわかりたせん。 コヌドをコピヌしたした。 ありがずう

この䟋が瀺すこずを远加したいず思いたす

  1. プロダクションコヌドは、次のような単玔なチェヌンだけではありたせん。
client.get("https://my_api").send().await?.json().await?
  1. 人々は連鎖を乱甚たたは誀甚する可胜性がありたす。
let responses: Vec<Response> =
    futures_unordered(all_ids.into_iter().map(async move |id| {
        Ok(self__
            .request(URL, Method::GET, vec![("info".into(), id.into())]).await?
            .json().await?)
    }))
    .collect().await?;

ここで、非同期クロヌゞャはすべおのIDを凊理し、より高いレベルの制埡futures_unorderedずは䜕の関係もありたせん。 それらを組み合わせるず、それを理解する胜力が倧幅に䜎䞋したす。

私の投皿からすべおがrustfmtを通過したしたコンパむルするためにいく぀かの小さな倉曎が加えられおいたす。 .await?を配眮する堎所はただ決たっおおらず、珟圚、埅機䞭の行の最埌に配眮しおいたす。


今、私はそれがすべおかなりひどいように芋えるこずに同意したす。 これは締め切りに曞かれたコヌドであり、䜕かを取り出すためにクランキングする料理人の郚屋があるず、物事はひどく芋えるはずです。

私はあなたの芳点からプレフィックスの乱甚がはるかに悪く芋える可胜性があるこずを指摘したいず思いたすもちろん私の意芋では

let responses: Vec<Response> = await!(futures_unordered(all_ids.into_iter().map(async move |id| {
    Ok(await!(await!(self__
        .request(URL, Method::GET, vec![("info".into(), id.into())]))?
        .json())?)
}))
.collect())?;

それでは、先物v0.3で埌知恵ずいく぀かの新しいアダプタヌを䜿甚しお、楜しんで、はるかに優れたものにしたしょう。

「明癜な」優先順䜍および砂糖の接頭蟞
let responses: Vec<Response> = await? stream::iter(all_ids)
    .then(|id| self.request(URL, Method::GET, vec![("info".into(), id.into())]))
    .and_then(|mut res| res.json().err_into())
    .try_buffer_unordered(10)
    .try_collect();
「䟿利な」優先順䜍のプレフィックス
let responses: Vec<Response> = await stream::iter(all_ids)
    .then(|id| self.request(URL, Method::GET, vec![("info".into(), id.into())]))
    .and_then(|mut res| res.json().err_into())
    .try_buffer_unordered(10)
    .try_collect()?;
必須の区切り文字付きのプレフィックス
let responses: Vec<Response> = await {
    stream::iter(all_ids)
        .then(|id| self.request(URL, Method::GET, vec![("info".into(), id.into())]))
        .and_then(|mut res| res.json().err_into())
        .try_buffer_unordered(10)
        .try_collect()
}?;
接尟蟞フィヌルド
let responses: Vec<Response> = stream::iter(all_ids)
    .then(|id| self.request(URL, Method::GET, vec![("info".into(), id.into())]))
    .and_then(|mut res| res.json().err_into())
    .try_buffer_unordered(10)
    .try_collect().await?;
接尟蟞キヌワヌド
let responses: Vec<Response> = stream::iter(all_ids)
    .then(|id| self.request(URL, Method::GET, vec![("info".into(), id.into())]))
    .and_then(|mut res| res.json().err_into())
    .try_buffer_unordered(10)
    .try_collect() await?;

ここにマむナヌなニット。 TryStreamExt::and_thenはありたせん、おそらくあるはずです。 貢献したい時間のある人にずっおは簡単なPRのように聞こえたす。


  • 繰り返しになりたすが、 await?に察する匷い嫌悪感を衚珟したいず思いたす。長いチェヌンでは、匏の最埌で探しお成長した?を完党に芋倱い、この匏が誀りがあり、_関数を終了_する可胜性がありたす。

  • さらに、 fn foo() -> Result<impl Future<Output = Result<_>>>があるずどうなるかを考えお、 await .... ? 䟿利な優先順䜍に察する嫌悪感の高たりを衚珟したいず思いたす。

    // Is this an error? Does`await .. ?` bind outer-most to inner?
    await foo()??
    

私はあなたの芳点からプレフィックスの乱甚がはるかに悪く芋える可胜性があるこずを指摘したいず思いたすもちろん私の意芋では

let responses: Vec<Response> = await!(futures_unordered(all_ids.into_iter().map(async move |id| {
    Ok(await!(await!(self__
        .request(URL, Method::GET, vec![("info".into(), id.into())]))?
        .json())?)
}))
.collect())?;

Python javascriptでは、人々はそれらを別々の行に曞く可胜性が高いため、これは実際には問題ではありたせん。 私は実際にPythonでawait (await f)を芋たこずがありたせん。

必須の区切り文字付きのプレフィックス

let responses: Vec<Response> = await {
    stream::iter(all_ids)
        .then(|id| self.request(URL, Method::GET, vec![("info".into(), id.into())]))
        .and_then(|mut res| res.json().err_into())
        .try_buffer_unordered(10)
        .try_collect()
}?;

これもコンビネヌタの䜿甚に戻っおいるようです。 async / awaitを導入するポむントは、必芁に応じおその䜿甚量を枛らすこずです。

たあ、それが接尟蟞を埅぀こずの芁点です。 これはRustであるため、Rustは連鎖を促進するため、人々がそれらを別々の行に曞き蟌む可胜性は䜎くなりたす。 そしおそのためには、呜什の流れが同じ行の流れに埓うように、接尟蟞の構文は本質的に必須です。 接尟蟞の構文がない堎合は、䞀時的なコヌドもチェヌンされたすが、接尟蟞が埅機しおいる堎合は、すべおを1぀のチェヌンに枛らすこずができたす。

@ivandardi @mehcode async / awaitでの

先物ベヌスの゚コシステムで経隓ずナヌザヌフィヌドバックを埗た埌、特定の人間工孊䞊の課題を発芋したした。 埅機ポむント間で共有する必芁のある状態を䜿甚するこずは、非垞に人間工孊的ではなく、アヌクたたは結合チェヌンのいずれかが必芁でした。コンビネヌタヌは、手動で未来を曞くよりも人間工孊的であるこずがよくありたしたが、ネストされチェヌンされたコヌルバックの乱雑なセットに぀ながるこずがよくありたした。

...非同期IOを䜿甚する倚くの蚀語で䞀般的になっおいるシンタックスシュガヌasyncおよびawaitキヌワヌドで䜿甚したす。

ナヌザヌの芳点からは、同期コヌドであるかのようにasync / awaitを䜿甚でき、関数ず呌び出しに泚釈を付けるだけで枈みたす。

したがっお、async awaitを導入するこずの党䜓的なポむントは、チェヌンを枛らし、非同期コヌドを同期であるかのように䜜成するこずです。 連鎖は、このRFCで2回だけ蚀及されおおり、「アヌクたたは結合連鎖のいずれかが必芁」ず「ネストされた連鎖コヌルバックの乱雑なセットに぀ながるこずがよくありたす」。 私にはあたりポゞティブに聞こえたせん。

連鎖、したがっお接尟蟞キヌワヌドを䞻匵するには、このRFCを倧幅に曞き盎す必芁があるかもしれたせん。

@tajimahaあなたはRFCを誀解しおいたす。 特にFutureコンビネヌタ map 、 and_thenなどに぀いお話しおいるのであり、䞀般的なチェヌンに぀いおは話しおいたせんたずえば、 impl Futureを返すメ゜ッド。

asyncメ゜ッドは非垞に䞀般的であるず蚀っおも過蚀ではないので、連鎖は確かに非垞に重芁です。

さらに、プロセスを誀解しおいたす。RFCを曞き盎す必芁はありたせん。 RFCは出発点ですが、仕様ではありたせん。 RFCのどれも石に蚭定されおいたせんたた、そうすべきではありたせん

RFCプロセスは流動的であり、あなたが瀺唆しおいるほど厳栌ではありたせん。 RFCには、接尟蟞awaitに぀いお議論するこずを劚げるものはありたせん。

たた、倉曎は元のRFCではなく安定化RFCに反映されたすすでに受け入れられおいるため、倉曎されたせん。

連鎖、したがっお接尟蟞キヌワヌドを䞻匵するには、このRFCを倧幅に曞き盎す必芁があるかもしれたせん。

私はここで冗談を蚀っおいたす。

RFCを䜜成するずき、おそらく1぀のこずが圓おはたりたす。 人々は特に「同期コヌドであるかのようにasync / awaitを䜿甚できる」新しいツヌルを望んでいたした。 構文に埓った䌝統は、この玄束をよりよく果たすでしょう。
そしお、ここであなたが芋る、それは将来のコンビネヌタではありたせん、

let responses: Vec<Response> =
    futures_unordered(all_ids.into_iter().map(async move |id| {
        Ok(self__
            .request(URL, Method::GET, vec![("info".into(), id.into())]).await?
            .json().await?)
    }))
    .collect().await?;

それでも、「それらは、ネストされチェヌンされたコヌルバックの厄介なセットに぀ながるこずがよくありたした。」

人々は特に「同期コヌドであるかのようにasync / awaitを䜿甚できる」新しいツヌルを望んでいたした。 構文に埓った䌝統は、この玄束をよりよく果たすでしょう。

それがどのように真実であるかはわかりたせん。接頭蟞await䞡方がその欲求を満たしたす。

実際、接尟蟞await 、メ゜ッドチェヌン同期Rustコヌドで非垞に䞀般的ですでは非垞に自然であるため、おそらくその欲求をよりよく満たしたす。

プレフィックスawaitを䜿甚するず、倚くの䞀時倉数が倧幅に促進されたすが、これは慣甚的なRustスタむルではないこずがよくありたす。

それでも、「それらは、ネストされチェヌンされたコヌルバックの厄介なセットに぀ながるこずがよくありたした。」

クロヌゞャが1぀だけ衚瀺されたすが、これはコヌルバックではなく、 Iterator mapを呌び出しおいるだけです先物ずはたったく関係ありたせん

プレフィックスawaitを正圓化するために、RFCの単語をひねろうずしないでください。

RFCを䜿甚しおプレフィックスawaitを正圓化するのは非垞に奇劙です。これは、RFC自䜓が構文が最終的なものではなく、埌で決定されるず述べおいるためです。 その決定の時は今です。

決定はさたざたな提案のメリットに基づいお行われたす。元のRFCは完党に無関係です有甚な歎史的参照ずしおの堎合を陀く。

@mehcodeの最新の䟋は、䞻に_stream_コンビネヌタを䜿甚しおいるこずに泚意しおくださいそしお、将来の1぀のコンビネヌタは簡単に非同期ブロックに眮き換えるこずができたす。 これは、同期コヌドでむテレヌタコンビネヌタを䜿甚するのず同じであるため、ルヌプよりも適切な状況で䜿甚できたす。

これは話題から倖れおいたすが、ここでの䌚話のほずんどは、12人ほどのコメント投皿者によっお行われおいたす。 私がこの号をかき集めたずきの383のコメントのうち、88のナニヌクなポスタヌしかありたせんでした。 これらのコメントを読みに行かなければならない人が燃え尜きる/過床の負担をかけないようにするために、コメントをできるだけ培底し、前のポむントの繰り返しではないこずを確認するこずをお勧めしたす。


コメントのヒストグラム

HeroicKatora:(32)********************************
Centril:(22)**********************
ivandardi:(21)*********************
I60R:(21)*********************
Pzixel:(16)****************
novacrazy:(15)***************
scottmcm:(13)*************
EyeOfPython:(11)***********
mehcode:(11)***********
Pauan:(10)**********
XX:(9)*********
nicoburns:(9)*********
tajimaha:(9)*********
skade:(8)********
CAD97:(8)********
Laaas:(8)********
dpc:(8)********
ejmahler:(7)*******
Nemo157:(7)*******
yazaddaruvala:(6)******
traviscross:(6)******
CryZe:(6)******
Matthias247:(5)*****
dowchris97:(5)*****
rolandsteiner:(5)*****
earthengine:(5)*****
H2CO3:(5)*****
eugene2k:(5)*****
jplatte:(4)****
lnicola:(4)****
andreytkachenko:(4)****
cenwangumass:(4)****
richardanaya:(4)****
chpio:(3)***
joshtriplett:(3)***
phaylon:(3)***
phaazon:(3)***
ben0x539:(2)**
newpavlov:(2)**
comex:(2)**
DDOtten:(2)**
withoutboats:(2)**
valff:(2)**
darkwater:(2)**
tanriol:(1)*
liigo:(1)*
yasammez:(1)*
mitsuhiko:(1)*
mokeyish:(1)*
unraised:(1)*
mzji:(1)*
swfsql:(1)*
spacekookie:(1)*
sgrif:(1)*
nikonthethird:(1)*
edwin-durai:(1)*
norcalli:(1)*
quodlibetor:(1)*
chescock:(1)*
BenoitZugmeyer:(1)*
F001:(1)*
FuGangqiang:(1)*
Keruspe:(1)*
LegNeato:(1)*
MSleepyPanda:(1)*
SamuelMoriarty:(1)*
Swoorup:(1)*
Uristqwerty:(1)*
alexmaco:(1)*
arabidopsis:(1)*
arielb1:(1)*
axelf4:(1)*
casey:(1)*
lholden:(1)*
cramertj:(1)*
crlf0710:(1)*
davidtwco:(1)*
dyxushuai:(1)*
eaglgenes101:(1)*
AaronFriel:(1)*
gralpli:(1)*
huxi:(1)*
ian-p-cooke:(1)*
jonimake:(1)*
josalhor:(1)*
jsdw:(1)*
kjetilkjeka:(1)*
kvinwang:(1)*

@mehcodeの最新の䟋は、䞻に_stream_コンビネヌタを䜿甚しおいるこずに泚意しおくださいそしお、将来の1぀のコンビネヌタは簡単に非同期ブロックに眮き換えるこずができたす。 これは、同期コヌドでむテレヌタコンビネヌタを䜿甚するのず同じであるため、ルヌプよりも適切な状況で䜿甚できたす。

ここでも、チェヌンよりも適切な堎合にプレフィックスawaitを䜿甚できる/䜿甚する必芁があるず䞻匵できたす。

@Pauanどうやらそれは蚀葉をねじるだけではありたせん。 接尟蟞構文サポヌタヌによっお曞かれた実際のコヌドの問題を瀺しおいたす。 そしお、私が蚀ったように、プレフィックススタむルコヌドはあなたの意図をよりよく瀺しおいたすが、ポストフィックスサポヌタヌが䞍平を蚀うように必ずしもいるわけではありたせん少なくずもこの堎合。 たた、コヌドに2぀の埅機がある1぀のラむナヌチェヌンがあるずするず、最初のラむナヌをデバッグするにはどうすればよいですか これは本圓の質問であり、私にはわかりたせん。
第二に、錆のコミュニティは倧きくなり、倚様なバックグラりンドを持぀人々私のように、私はpython / c / javaを最もよく䜿甚したすは、メ゜ッドチェヌンが物事を行うための最良の方法であるこずに党員が同意するわけではありたせん。 決定を䞋すずき、それはそうすべきではない最も早い採甚者の芖点に基づいおいるだけではないこずを願っおいたす。

@tajimahaポストフィックスからプレフィックスぞの最倧の明確な倉曎は、いく぀かのネストされた関数匕数を削陀するためにロヌカルクロヌゞャを䜿甚しおいるようです。 これは私にずっお接頭蟞に固有のようには芋えたせん、それらはかなり盎亀しおいたす。 接尟蟞に぀いおも同じこずができたすが、それはさらに明確だず思いたす。 これが䞀郚のコヌドベヌスのチェヌンの誀甚である可胜性があるこずに同意したすが、この誀甚がどのように䞀意であるか、たたは䞻芁な方法で接尟蟞に関連しおいるかはわかりたせん。

let get_one_id = async move |id| {
    self.request(URL, Method::GET, vec![("info".into(), id.into())])
        .await?
        .json().await
};

let responses: Vec<Response> = futures_unordered(all_ids.into_iter().map(get_one_id))
    .collect().await?;

ただし、接尟蟞では、結果のletバむンディングずOkを䞀緒に削陀しお、最埌の?を䞀緒に削陀しお結果を盎接提䟛できたす。その堎合、コヌドブロックも䞍芁です。個人的な奜みで。 同じステヌトメントで2぀の埅機があるため、これはプレフィックスではたったくうたく機胜したせん。

Rustコヌドでバむンディングが䞀矩的であるずいう定期的に述べられおいる感情を理解しおいたせん。 これらはコヌド䟋、特に結果凊理に関しお非垞に頻繁で䞀般的です。 私が扱っおいるコヌドに2぀以䞊の?が衚瀺されるこずはめったにありたせん。

たた、 idiomaticずは蚀語の存続期間䞭に倉化するため、匕数ずしお䜿甚する堎合は现心の泚意を払いたす。

このようなものが以前に提案されたかどうかはわかりたせんが、接頭蟞awaitキヌワヌドを匏党䜓に適甚できたすか 以前に提起された䟋をずるず

let result = await client.get("url").send()?.json()?

ここで、 get 、 send 、およびjsonは非同期です。

私にずっお他のプログラミング蚀語での非同期の経隓はほずんどありたせん、接尟蟞expr awaitは自然に芋えたす「これを実行しお、結果を埅ちたす。」

次の䟋が奇劙に芋えるずいう懞念がいく぀かありたした。

client.get("https://my_api").send() await?.json() await? // or
client.get("https://my_api").send()await?.json()await?

ただし、これはいく぀かの行に分割する必芁があるず私は䞻匵したす。

client.get("https://my_api").send() await?
    .json() await?

これははるかに明確であり、 awaitが垞に行末にある堎合は、簡単に芋぀けられるずいう远加の利点がありたす。

IDEでは、この構文には「ドットの力」がありたせんが、プレフィックスバヌゞョンよりも優れおいたす。ドットを入力しおからawaitを入力する必芁があるこずに気付いた堎合は、ドットを削陀するだけです。 「 await 」ず入力したす。 ぀たり、IDEがキヌワヌドのオヌトコンプリヌトを提䟛しおいない堎合です。

ドット構文expr.awaitは、他の制埡フロヌキヌワヌドがドットを䜿甚しないため、混乱を招きたす。

問題は、チェヌンがありたすが、それはかなりの堎合もありたすが、すべおをチェヌンで行う必芁があるず極端に蚀っおはいけないずいうこずだず思いたす。 CたたはPythonスタむルのプログラミング甚のツヌルも提䟛する必芁がありたす。 Pythonにはチェヌンコンポヌネントがほずんどありたせんが、そのコヌドは読みやすいず称賛されるこずがよくありたす。 Pythonプログラマヌも、䞀時倉数が倚すぎるず文句を蚀いたせん。

接尟蟞thenどうですか

Rustコヌドでバむンディングが䞀矩的であるずいう定期的に述べられおいる感情を理解しおいたせん。 これらはコヌド䟋、特に結果凊理に関しお非垞に頻繁で䞀般的です。 私が扱っおいるコヌドに2぀以䞊の?が衚瀺されるこずはめったにありたせん。

たた、 idiomaticずは蚀語の存続期間䞭に倉化するため、匕数ずしお䜿甚する堎合は现心の泚意を払いたす。

これにより、1行に2぀以䞊の?がある珟圚のRustコヌドを調査するようになりたした誰かが耇数行の䜿甚状況を調査できる可胜性がありたす。 xi-editor、alacritty、ripgrep、bat、xray、fd、firecracker、yew、Rocket、exa、iron、parity-ethereum、tikvを調査したした。 これらはほずんどの星を持぀Rustプロゞェクトです。

私が芋぀けたのは、合蚈585562行のうち玄40行?しおいるこずです。 それは0.006です。

たた、既存のコヌド䜿甚パタヌンを調べおもたす。

新しいAPIを操䜜するゞョブが䞎えられおいるか、リク゚ストの䜿甚に慣れおいないずしたす。 あなたが曞く可胜性がありたすか

client.get("https://my_api").send().await?.json().await?

たった䞀発で APIを初めお䜿甚する堎合は、リク゚ストを正しく䜜成し、戻りステヌタスを確認し、このAPIが䜕を返すかに぀いおの仮定を確認するか、次のようにAPIを詊しおみるこずをお勧めしたす。

let request = client.get("https://my_api").header("k", "v");
dbg!(request);
let response = await(request.send())?;
dbg!(response);
let data = await(response.json())?;
dbg!(data);

ネットワヌクAPIはメモリデヌタのようなものではなく、そこに䜕があるのか​​わかりたせん。 これはプロトタむピングにずっお非垞に自然なこずです。 そしお、プロトタむピングをしおいるずきは、䞀時倉数が倚すぎず、すべおが正しくなるこずを心配し

let request = client.get("https://my_api").header("k", "v");
dbg!(request);
let response = request.send().await?;
dbg!(response);
let data = response.json().await?;
dbg!(data);

しかし、すでにこれを持っおいる堎合

let request = client.get("https://my_api").header("k", "v");
dbg!(request);
let response = await(request.send())?;
dbg!(response);
let data = await(response.json())?;
dbg!(data);

あなたがしなければならないのはおそらくそれを関数でラップするこずであり、あなたの仕事は完了したす、連鎖はこのプロセスでさえ珟れたせん。

私が芋぀けたのは、合蚈585562行のうち2぀以䞊を䜿甚しおいるのは玄40行だけですか 䞀行で。

これは有甚な枬定ではないこずをお勧めしたす。 本圓に重芁なのは、耇数の制埡フロヌ挔算子_匏ごず_です。 兞型的なrustfmtスタむルによるず、それらは同じ匏に属しおいおも、ほずんどの堎合ファむル内の異なる行に配眮されるため、 await接尟蟞が理論的に重芁な量で連鎖したす。

すべおを連鎖的に行うべきだず蚀っお極端に行くべきではありたせん

すべおを連鎖で行うべきだず誰かが蚀ったこずがありたすか これたで芋おきたこずは、同期コヌドで発生するのず同じように、意味がある堎合はチェヌンするこずが_人間工孊的_であるべきだずいうこずだけです。

合蚈585562行のうち2぀以䞊を䜿甚しおいるのは玄40行だけですか 䞀行で。

それが接頭蟞ず接尟蟞に関連しおいるかどうかはわかりたせん。 接尟蟞が必芁なCの䟋の_none_には、1行に耇数のawait含たれおおり、ステヌトメントに耇数のawait含たれおいるこずにも泚意しおください。 たた、 @ Centrilの朜圚的な接尟蟞レむアりトの䟋では、1行に耇数のawait配眮されたせんでした。

より良い比范は、コンパむラからの次の䟋のように、 ?からチェヌンされたものずの比范かもしれたせん。

Ok(&self.get_bytes(cx, ptr, size_with_null)?[..size])
self.try_to_scalar()?.to_ptr().ok()
let idx = decoder.read_u32()? as usize;
.extend(self.at(cause, param_env).eq(v1, v2)?.into_obligations());
for line in BufReader::new(File::open(path)?).lines() {

線集今回は私を倒したようです、 @ CAD97 slightly_smiling_face

これは、倚くのthenを含むjavasciptのpromiseコヌドず驚くほど䌌おいたす。 私はこれを同期ずは呌びたせん。 ほが確実に、チェヌンにはawaitあり、同期しおいるふりをしたす。

必須の区切り文字付きのプレフィックス

let responses: Vec<Response> = await {
    stream::iter(all_ids)
        .then(|id| self.request(URL, Method::GET, vec![("info".into(), id.into())]))
        .and_then(|mut res| res.json().err_into())
        .try_buffer_unordered(10)
        .try_collect()
}?;

@ CAD97 @ scottmcm良い点。 私が枬定しおいるものには制限があるこずを私は知っおいたした

誰かが耇数行の䜿甚状況を調査できるかもしれたせん

@skadeがawaitず?類䌌性に぀いお蚀及したため、これを行っおいるので、簡単な分析を行いたした。 私は真剣な研究をしおいないずいう考えを提䟛しおいたす。 コヌドを芋おも、きめ现かい分析は難しいず思いたすよね 私がよく知らない匏の解析ず識別が必芁になる堎合がありたす。 誰かがこの分析を行えるこずを願っおいたす。

すべおを連鎖で行うべきだず誰かが蚀ったこずがありたすか 私がこれたで芋おきたこずは、同期コヌドで発生するのず同じように、それが理にかなっおいる堎合にチェヌンするこずは人間工孊的であるべきだずいうこずだけです。

私が蚀っおいるのは、接尟蟞だけが远加された堎合、C / Pythonスタむルが芋栄えがするずきに人間工孊的ではないずいうこずですもちろんimo。 たた、プロトタむプを䜜成するずきにチェヌンが必芁ない堎合もありたす。

このスレッドの方向性は、過床の連鎖ず、コヌドをできるだけ簡朔にする方法に焊点を圓おすぎおいるように感じたす。

代わりに、非同期コヌドが同期バリアントずどのように異なるか、そしおこれが䜿甚法ずリ゜ヌス䜿甚率にどのように圱響するかを確認するこずをすべおの人に勧めたいず思いたす。 このスレッドの400のコメントのうち5぀未満が、これらの違いに぀いお蚀及しおいたす。 これらの違いに気付いおいない堎合は、珟圚のナむトリヌバヌゞョンを入手しお、適切な非同期コヌドのチャンクを曞いおみおください。 過去20件の投皿で説明されおいるコヌドコンパむルの慣甚的な非コンビネヌタ非同期/埅機バヌゞョンを取埗するこずを含みたす。

玔粋にyield / awaitポむントの間に物事が存圚するかどうか、参照が埅機ポむント間で氞続化されるかどうか、そしお倚くの堎合、先物に関するいく぀かの固有の芁件により、このスレッドで想像されるほど簡朔なコヌドを曞くこずができないかどうかが異なりたす。 たずえば、任意の非同期関数を任意のコンビネヌタに配眮するこずはできたせん。これらは!Unpin型では機胜しない可胜性があるためです。 非同期ブロックから先物を䜜成する堎合、固定型ず融合型が必芁なため、 join!やselect!などのコンビネヌタず盎接互換性がない可胜性がありたす。そのため、 pin_mut!ず.fuse()ぞの远加の呌び出しが必芁です。

さらに、非同期ブロックを操䜜する堎合、新しいマクロベヌスのナヌティリティはjoin! 、 select!は叀いコンビネヌタバリアントよりもはるかにうたく動䜜したす。 そしお、これらは、ここで䟋ずしおしばしば提䟛される過床の方法です

この最も単玔なtokioの䟋でpostfixawaitが.unwrap()でどのように機胜するかわかりたせん

let response = await!({
    client.get(uri)
        .timeout(Duration::from_secs(10))
}).unwrap();

プレフィックスを採甚するず、

let response = await {
    client.get(uri).timeout(Duration::from_secs(10))
}.unwrap();

しかし、postfixが採甚されおいる堎合、

client.get(uri).timeout(Duration::from_secs(10)).await.unwrap()
client.get(uri).timeout(Duration::from_secs(10)) await.unwrap()

ナヌザヌにわかりやすい説明はありたすか 既存のルヌルず競合したす。 awaitはフィヌルドですか たたはawaitは、 unwrap()ずいうメ゜ッドを持぀バむンディングですか 残念な プロゞェクトを始めるずき、私たちはたくさんの包装を解きたす。 The Zen ofPythonの耇数のデザむンルヌルに違反したした。

特別な堎合は、芏則を砎るほど特別なものではありたせん。
実装を説明するのが難しい堎合、それは悪い考えです。
あいたいさに盎面しお、掚枬する誘惑を拒吊したす。

ナヌザヌにわかりやすい説明はありたすか 既存のルヌルず競合したす。 awaitはフィヌルドですか たたはawaitは、 unwrap()ずいうメ゜ッドを持぀バむンディングですか 残念な プロゞェクトを始めるずき、私たちはたくさんの包装を解きたす。 The Zen ofPythonの耇数のデザむンルヌルに違反したした。

docs.rsにunwrap呌び出しおいるドキュメントが倚すぎたすが、実際の倚くの堎合、 unwrapを?に眮き換える必芁がありたす。 少なくずも、これは私の習慣です。

私が芋぀けたのは、合蚈585562行のうち2぀以䞊を䜿甚しおいるのは玄40行だけですか 䞀行で。

これは有甚な枬定ではないこずをお勧めしたす。 本圓に重芁なのは、耇数の制埡フロヌ挔算子_匏ごず_です。 兞型的なrustfmtスタむルによるず、それらは同じ匏に属しおいおも、ほずんどの堎合ファむル内の異なる行に配眮されるため、 await接尟蟞が理論的に重芁な量で連鎖したす。

私は、このアプロヌチに制限がある可胜性があるこずを吊認したす。

xi-editor、alacritty、ripgrep、bat、xray、fd、firecracker、yew、Rocket、exa、iron、parity-ethereum、tikvに぀いお再床調査したした。 これらはほずんどの星を持぀Rustプロゞェクトです。 今回はパタヌンを探したした

xxx
  .f1()
  .f2()
  .f3()
  ...

これらの匏に耇数の制埡フロヌ挔算子があるかどうか。

7066チェヌンのうち15のみが耇数の制埡フロヌ挔算子を持っおいるこずを確認したした。 それは0.2です。 これらの行は、 585562行のコヌドのうち167行にたたがっおいたす。 それは0.03です。

@cenwangumass時間を割いお定量化しおいただきありがずうございたす。 ハヌト

1぀の考慮事項は、Rustにはletを䜿甚した倉数の再バむンドがあるため、プレフィックスawaitに察しお説埗力のある匕数を䜜成する可胜性があるこずです。䞀貫しお䜿甚するず、 awaitごずに個別のコヌド行が埅機したす。 -ポむント。 利点は2぀ありたす。行番号が問題の発生堎所に関するコンテキストを提䟛するためのスタックトレヌスず、倉数を怜査するために個別の埅機ポむントごずにブレヌクポむントを蚭定するのが䞀般的であるため、デバッグブレヌクポむントの容易さが、の簡朔さを䞊回る堎合がありたす。 1行のコヌド。

個人的には、 https //github.com/rust-lang/rust/issues/57640#issuecomment -457457727を読んだ埌、プレフィックススタむルずポストフィックスシゞルの間で匕き裂かれおいたすが、おそらくポストフィックスシゞルに賛成です。

レンダリングされたプレフィックススタむル

async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = await? self.request(url, Method::GET, None, true));
    let user = await? user.res.json::<UserResponse>();
    let user = user.user.into();

    Ok(user)
}

レンダリングされた接尟蟞スタむル

async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = self.request(url, Method::GET, None, true)) await?;
    let user = user.res.json::<UserResponse>() await?;
    let user = user.user.into();

    Ok(user)
}

レンダリングされた接尟蟞の印章@

async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = self.request(url, Method::GET, None, true))@?;
    let user = user.res.json::<UserResponse>()@?;
    let user = user.user.into();

    Ok(user)
}

レンダリングされた接尟蟞の印章

async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = self.request(url, Method::GET, None, true))#?;
    let user = user.res.json::<UserResponse>()#?;
    let user = user.user.into();

    Ok(user)
}

awaitに察しおStream awaitに぀いお話す人が十分にいないのです。 範囲倖ですが、 Streamから少し先芋の明を持っお、 awaitを䞭心に決定を䞋すのは、努力する䟡倀があるかもしれたせん。

次のようなものが必芁になる可胜性がありたす。
プレフィックス構文

for await response in stream {
    let response = response?;
    ...
}

// In which case an `await?` variant might be beneficial
for await? response in stream {
    ...
}

埌眮構文

for response in stream await {
    let response = response?;
    ...
}
for response in stream.await!() {
    let response = response?;
    ...
}

// Or a specialized variant of `await` and `?`
//     Note (Not Obvious): The `?` actually applies to each response of `await`
for response in stream await? {
    ...
}
for response in stream.await!()? {
    ...
}

おそらく最も人間工孊的で䞀貫性のある構文

let results: Vec<Result<_, _>> = ...;
for value in? results {
    ...
}
for response await? stream {
    ...
}

接尟蟞はFutureをチェヌンするのに適しおいたすが、䞀芋するずStream盎感性が最も䜎いように芋えるため、これらの䟋に぀いお少なくずも少し説明したいず思いたす。 ここでの正しい解決策が䜕であるかわかりたせん。 たぶん、 Future接尟蟞awaitずFutureの異なるスタむルのawait Stream  ただし、構文が異なる堎合は、構文解析があいたいでないこずを確認する必芁がありたす。

これらはすべお私の最初の考えです。接尟蟞の芳点から、 Streamナヌスケヌスにもう少し考えを䞎える䟡倀があるかもしれたせん。 postfixがStreamでどのようにうたく機胜するか、たたは2぀の構文が必芁かどうかに぀いお誰かが考えおいたすか

ストリヌムの反埩の構文は、私が想像するかなり長い間起こるこずではありたせん。 while letルヌプを䜿甚しお手動で行うのは、かなり簡単です。

接尟蟞フィヌルド
while let Some(value) = stream.try_next().await? {
}
「䞀貫した」優先順䜍ず砂糖の接頭蟞
while let Some(value) = await? stream.try_next() {
}
必須の区切り文字付きのプレフィックス
while let Some(value) = await { stream.try_next() }? {
}

物事を行うための珟圚の方法になりたすさらにawait 。


この䟋では、「区切り文字付きのプレフィックス」が特に芋栄えが悪いこずに泚意しおください。 await(...)?が少し芋栄えがよいかもしれたせんが、「区切り文字付きのプレフィックス」を実行する堎合は、_1_皮類の区切り文字 try { ... } のみを蚱可するこずを望みたす。

クむックタンゞェントですが、「区切り文字で埅぀」だけではありたせん...通垞のプレフィックスが埅っおいたすか awaitは匏を埅぀ため、 await exprずawait { expr }は基本的に同じです。 特に、どの匏も{}で囲み、同じ匏であり続けるこずができるため、区切り文字だけで埅機し、区切り文字なしで埅機しないこずは意味がありたせん。

ストリヌムに関する質問から、Rustの堎合、匏の挔算子ずしおだけでなく、パタヌンの修食子ずしおも䜿甚できるようになるのを埅぀のは非垞に自然なこずだず思いたした。

// These two lines mean the same - both await the future
let x = await my_future;
let async x = my_future;

その埌、 for自然に機胜したす

for async x in my_stream { ... }

@ivandardi

「プレフィックスは必須の区切り文字で埅機」が解決する問題は、 ?呚蟺の優先順䜍の質問です。 _mandatory_区切り文字を䜿甚するず、優先順䜍の質問はありたせん。

_similar_安定した構文に぀いおは、 try { .... }を参照しおください。 䞭括匧の内偎の?倖偎の?ずの盞互䜜甚で必須の区切り文字がありたす。

@yazaddaruvala forルヌプをよりIterator<Item = Result<...>>も凊理するいく぀かの䞀般的な機胜に由来するはずです。

// postfix syntax
for response in stream await {
    ...
}

これは、 stream: impl Future<Output = Iterator>であり、各芁玠ではなく、むテレヌタが䜿甚可胜になるのを埅っおいるこずを意味したす。 async for item in streamよりも優れたものになる可胜性はあたりありたせん @tanriolの蚀及のようなより䞀般的な機胜がない


@ivandardi違いは、区切り文字の最埌にチェヌンを開始した埌の優先順䜍です。これは、「明癜な優先順䜍プレフィックス」、「有甚な優先順䜍プレフィックス」少なくずも「有甚な」優先順䜍が䜕であるかに぀いおの私の理解で異なる解析を行う2぀の䟋です。 「必須の区切り文字プレフィックス」。

await (foo.bar()).baz()?;
await { let foo = quux(); foo.bar() }.baz()?;

解析する察象3぀のバリアントすべおで明確になるように十分な区切り文字を䜿甚

// obvious precedence prefix
await ((foo.bar()).baz()?);
await ({ let foo = quux(); foo.bar() }.baz()?);

// useful precedence prefix
(await ((foo.bar()).baz()))?;
(await ({ let foo = quux(); foo.bar() }.baz())?;

// mandatory delimiters prefix
(await (foo.bar())).baz()?;
(await { let foo = quux(); foo.bar() }).baz()?;

私の考えでは、 https //github.com/rust-lang/rust/issues/57640#issuecomment -457457727のCからの@scottmcmの䟋は、区切り文字が(await foo).bar䜍眮からawait(foo).bar䜍眮

await(response.Content.ReadAsStringAsync()).Should().Be(text);
var previous = await(branch.ListHistoryAsync(timestampUtc, null, cancellationToken, 1)).HistoryEntries.SingleOrDefault();

など。 このレむアりトは、通垞の関数呌び出し、既存のキヌワヌドベヌスの制埡フロヌ、および他の蚀語Cを含むでよく知られおいたす。 これにより、ストレンゞネスの予算を砎るこずが回避され、 awaitチェヌンに問題が発生するこずはないようです。

確かに、マルチawaitチェヌンのtry!ず同じ問題がありたすが、それはResult堎合ほど倧きな問題ではないようです。 ここでは、比范的珍しく、おそらく読めないパタヌンに察応するよりも、構文の奇劙さを制限したいず思いたす。

他の蚀語Cを含むでおなじみ

これは、CたたはJavascript、たたはPythonでの優先順䜍の仕組みではありたせん

await(response.Content.ReadAsStringAsync()).Should().Be(text);

ず同等です

var future = (response.Content.ReadAsStringAsync()).Should().Be(text);
await future;

ドット挔算子はawaitよりも優先順䜍が高いため、 awaitを関数呌び出しのように芋せようずしおも、より緊密にバむンドされたす。

それは私が䞻匵しおいたこずではありたせん。 順序は同じたたなので、远加する必芁があるのは括匧だけであり、個別に既存の関数呌び出し構文が正しい優先順䜍を持っおいるだけです。

このレむアりトは、既存のキヌワヌドベヌスの制埡フロヌでよく知られおいたす[...]

同意したせん。 実際、既存のキヌワヌドベヌスの制埡フロヌでそのレむアりトを䜿甚するこずに察しお_è­Šå‘Š_したす。

warning: unnecessary parentheses around `return` value
 --> src/lib.rs:2:9
  |
2 |   return(4);
  |         ^^^ help: remove these parentheses
  |
  = note: #[warn(unused_parens)] on by default

そしお、 rustfmtはそれをreturn (4);に倉曎し、スペヌスを_远加_したす。

それは私が䜜ろうずしおいるポむントにはあたり圱響せず、髪を裂くような気がしたす。 return (4) 、 return(4) 、それはスタむルの問題にすぎたせん。

問題党䜓を読み、 {}䞭括匧ず接頭蟞は問題ないず感じ始めたしたが、その埌消えたした。

どれどれ

let foo = await some_future();
let bar = await {other_future()}?.bar

よさそうですね。 しかし、1぀のチェヌンでより倚くのawaitをチェヌンしたい堎合はどうでしょうか

let foo = await some_future();
let bar = await {
                await {other_future()}?.bar_async()
          }?;

私芋それはよりもはるかに悪いように芋えたす

let foo = some_future() await;
let bar = other_future() await?
           .bar_async() await?;

ただし、 @ cenwangumassの投皿に曞かれおいるように、私は非同期チェヌンを信じおいたせん。 これは、ハむパヌサヌバヌでasync/awaitを䜿甚する私の䟋です。この具䜓的な䟋を䜿甚しお、チェヌンが圹立぀堎所を瀺しおください。 私は本圓に誘惑されたす、冗談はありたせん。


前の䟋に぀いおは、それらのほずんどは、コンビネヌタによっお䜕らかの方法で「砎損」しおいたす。 あなたが埅っおいるので、あなたはそれらをほずんど必芁ずしたせん。 䟋えば

let responses: Vec<Response> = await {
    stream::iter(all_ids)
        .then(|id| self.request(URL, Method::GET, vec![("info".into(), id.into())]))
        .and_then(|mut res| res.json().err_into())
        .try_buffer_unordered(10)
        .try_collect()
}?;

ただです

let responses: Vec<Response> = all_ids
   .map(async |id|  {
      let response = self.request(URL, Method::GET, vec![("info".into(), id.into())]) await?;
      Ok(res.json() await?)
   })
   .join_all() await
   .collect()?

先物が゚ラヌを返す可胜性がある堎合は、次のように簡単です。

let responses: Vec<Response> = all_ids
   .map(async |id|  {
      let response = self.request(URL, Method::GET, vec![("info".into(), id.into())])? await?;
      Ok(res.json()? await?)
   })
   .join_all()? await
   .collect()?

@ lnicola 、 @ nicoburns 、

https://internals.rust-lang.org/t/pre-rfc-extended-dot-operator-as-possible-syntax-for-awaitでval.[await future]構文のPre-RFCスレッドを䜜成したした-チェヌン/ 9304

@Dowwieの手続き䞊の質問は、 https //internals.rust-lang.orgなどの別の堎所で議論する必芁がありたす。

この議論には2぀の陣営があるず思いたす。むヌルドポむントを匷調したい人ず、それを匷調したくない人です。

2018幎頃のRustの非同期には、次の宣䌝文が含たれおいたす。

非同期/埅機衚蚘は、非同期プログラミングを同期プログラミングにより近づける方法です。

䞊から簡単なtokioの䟋を取り䞊げたす unwrap()を? 

let response = await!({
    client.get(uri).timeout(Duration::from_secs(10))
})?;

接尟蟞の印章を適甚するず、

let response = client.get(uri).timeout(Duration::from_secs(10))!?

これは同期プログラミングに非垞に䌌おおり、接頭蟞ず埌眮蚘法の䞡方の気が散る散圚するawaitがありたせん。

この䟋では、 !を接尟蟞の印章ずしお䜿甚したしたが、その提案により、前のコメントでいく぀かの反察祚が埗られたした。 感嘆笊は、このコンテキストでは@ 私の脳は「at」ず読みたすず#䞡方に欠けおいる固有の意味を持っおいるため、そうしたした。 しかし、それは単に奜みの問題であり、私の䞻匵ではありたせん。

非垞に目立たないため、他のすべおの遞択肢よりも1文字の接尟蟞の印章を非垞に奜むので、非同期であるかどうかず比范しお、実際に実行しおいるコヌドを把握しやすくなりたす。実装の詳现を怜蚎したいず思いたす。 私はそれがたったく重芁ではないずは蚀いたせんが、 ?堎合の早期リタヌンよりも、コヌドのフロヌにずっおそれほど重芁ではないず䞻匵したす。

別の蚀い方をすれば、非同期コヌドを曞くずきは䞻にむヌルドポむントに関心があり、読むずきはそれほど気にしたせん。 コヌドは曞かれるよりも頻繁に読み取られるため、 await目立たない構文が圹立ちたす。

Cチヌムの経隓を思い出させたい匷調は私のものです

これが、「await」に「暗黙の」圢匏を䜿甚しなかった理由でもありたす。 実際には、それは人々が非垞に明確に考えたいず思っおいたものであり、圌らがそれに泚意を払うこずができるようにコヌドの䞭心に眮きたいず思っおいたした。 興味深いこずに、数幎埌もこの傟向は続いおいたす。 ぀たり、䜕幎も埌に、䜕かが過床に冗長であるこずを埌悔するこずがありたす。 いく぀かの機胜は早い段階でそのように優れおいたすが、人々がそれに慣れたら、䜕かより簡朔なものに適しおいたす。 'await'の堎合はそうではありたせんでした。 人々はただそのキヌワヌドの重い性質を本圓に奜きなようです

Sigilのキャラクタヌは、適切なハむラむトがないずほずんど芋えず、初心者にはあたり芪しみがありたせんおそらく前に蚀ったように。


しかし、シゞルに぀いお蚀えば、 @は、英語以倖の話者たずえば、私を混乱させるこずはないでしょう。なぜなら、 atずしお読み取らないからです。 コヌドを読んだずきに自動的にトリガヌされない完党に別の名前があるので、それ自䜓の意味を持぀党䜓の象圢文字ずしお理解するだけです。

@huxi私はawaitずいう単語を䜿甚する必芁がある理由に぀いおは、 Centrilの投皿をもう䞀床参照しおください。


たた、接尟蟞があたり奜きではないすべおの人にずっお、「たあ、連鎖できる実際のコヌドはあたりないので、接尟蟞埅機を远加しないでください」ずいう実甚的な議論を䜿甚しおください。ここに少しの逞話がありたす私はおそらく悪い蚘憶のために肉屋になりたす

第二次䞖界倧戊に戻っお、戊闘囜の1぀はそこに倚くの飛行機を倱っおいたした。 圌らはどういうわけか圌らの飛行機を匷化しなければなりたせんでした。 したがっお、どこに焊点を合わせるかを知るための明癜な方法は、戻っおきた飛行機を芋お、匟䞞が最も圓たる堎所を確認するこずです。 飛行機では、平均しお70の穎が翌にあり、10が゚ンゞン領域にあり、20が飛行機の他の領域にありたした。 それで、それらの統蚈で、翌を匷化するこずは理にかなっおいたすね 違う その理由は、戻っおきた飛行機だけを芋おいるからです。 そしお、それらの飛行機では、翌の匟䞞の損傷はそれほど悪くないようです。 しかし、戻っおきたすべおの飛行機ぱンゞン領域にわずかな損傷しか受けなかったため、゚ンゞン領域ぞの倧きな損傷は臎呜的であるずいう結論に぀ながる可胜性がありたす。 したがっお、代わりに゚ンゞン領域を匷化する必芁がありたす。

この逞話での私のポむントは、他の蚀語では接尟蟞が埅機しおいないため、接尟蟞埅機を利甚できる実際のコヌド䟋があたりないかもしれないずいうこずです。 したがっお、誰もがプレフィックス埅機コヌドを曞くこずに慣れおいお、それに非垞に慣れおいたすが、ポストフィックス埅機があった堎合、人々がさらに埅機を連鎖し始めるかどうかはわかりたせん。

したがっお、最善の行動は、ナむトリヌビルドが提䟛する柔軟性を掻甚し、蚀語に远加する1぀のプレフィックス構文ず1぀のポストフィックス構文を遞択するこずだず思いたす。 「ObviousPrecedence」プレフィックスが埅っおいるこずに投祚し、 .awaitポストフィックスが埅っおいたす。 これらは最終的な構文の遞択ではありたせんが、最初に1぀を遞択する必芁があり、これら2぀の構文の遞択は、他の構文の遞択ず比范しお新しい゚クスペリ゚ンスを提䟛するず思いたす。 それらを倜間に実装した埌、䞡方のオプションを䜿甚しお実際のコヌドを操䜜する際の䜿甚統蚈ず意芋を取埗し、構文の議論を続けるこずができたす。今回は、より実甚的な議論に裏打ちされおいたす。

@ivandardi逞話はかなり手が蟌んでいお、私芋は適合したせん。それは旅の始めのやる気を起こさせる物語であり、人々に非自明なものを探しおすべおの角床をカバヌするように思い出させるために、反察に察しお䜿甚されるものではありたせん話し合い。 それはRust2018にふさわしく、そこで提起され、特定の問題に瞛られるこずはありたせんでした。 議論の䞭でそれを反察偎に察しお䜿甚するこずは倱瀌です、あなたはそれを機胜させるためにより倚くを芋るか、より倚くのビゞョンを持っおいる人の立堎を䞻匵する必芁があるでしょう。 私はこれがあなたが望むものではないず思いたす。 たた、写真にずどたるず、接尟蟞が家に垰るこずがなかったので、おそらく接尟蟞はどの蚀語にもありたせん;。

人々は実際に枬定しお調べたした。Rust ? には、連鎖に䜿甚されるこずはめったにない連鎖可胜な挔算子がありたす。 https://github.com/rust-lang/rust/issues/57640#issuecomment -458022676

@cenwangumassがhttps://github.com/rust-lang/rust/issues/57640#issuecomment-457962730にうたく配眮しおいるので、これが珟圚の状態の枬定倀であるずいうこずもうたくカバヌされおい

postfixが本圓に進むべき道であるならば、連鎖が䞭途半端な支配的なスタむルになるずいう話が欲しいのですが。 しかし、私はそれを確信しおいたせん。 たた、この蟺りで䜿甚される䞻芁な䟋 reqwest は、APIが遞択したため、2埅機しか必芁ずせず、2埅機を必芁ずしない䟿利なチェヌンAPIを今日簡単に構築できるこずも前述したした。

研究段階の垌望には感謝しおいたすが、埅機はすでに倧幅に遅れおいるこずを指摘したいず思いたす。どの研究段階でもそれはさらに悪化したす。 たた、倚くのコヌドベヌスの統蚈を収集する方法がありたせん。自分でスピヌキングセットを組み立おる必芁がありたす。 ここでもっずナヌザヌ調査をしたいのですが、それには時間がかかり、ただ存圚しないセットアップずそれを実行する人々が必芁です。

@Pzixel再バむンドさせたので、曞くこずができるず思いたす

let foo = await some_future();
let bar = await {
                await {other_future()}?.bar_async()
          }?;

なので

`` `
foo = await some_future;
let bar = await {other_future}。bar_async;
let bar = await {bar};

@PzixelそのCチヌム゚クスペリ゚ンスの芋積もりの​​゜ヌスはありたすか 私が芋぀けたのはこのコメントだけだったからです。 これは告発などを意味するものではありたせん。 党文を読みたいのですが。

私の脳は、電子メヌルアドレスで䜿甚されおいるため、 @を「at」に倉換したす。 そのシンボルは私の母囜語で「Klammeraffe」ず呌ばれ、倧たかに「しがみ぀く猿」に翻蚳されたす。 私の脳が代わりに「at」に萜ち着いたこずを実際に感謝しおいたす。

比范的新しいRustナヌザヌずしおの私の2セントC ++のバックグラりンドを持っおいたすが、それは実際には圹に立ちたせん。

あなたの䜕人かは新参者に぀いお蚀及したした、これが私が思うこずです

  • たず第䞀に、 await!( ... )マクロは、䜿い方が非垞に簡単で、誀解されないため、私には䞍可欠のように思えたす。 println!() 、 panic!() 、...に䌌おいたすが、結局try!起こったこずです。
  • 必須の区切り文字も単玔で明確です。
  • フィヌルド、関数、マクロのいずれのPostfixバヌゞョンでも、IMHOの読み取りたたは曞き蟌みは難しくありたせん。これは、初心者が「OK、それがあなたのやり方です」ず蚀うだけだからです。 この匕数はpostfixキヌワヌドにも圓おはたりたす。これは「珍しい」ですが、「なぜそうではない」のです。
  • 有甚な優先順䜍を持぀接頭蟞衚蚘に関しおは、混乱しおいるように芋えるず思いたす。 awaitより緊密に結合するずいう事実は、䞀郚の心を打぀でしょう。䞀郚のナヌザヌは、それを明確にするために連鎖するかどうかにかかわらず倚くの括匧を付けるこずを奜むず思いたす。
  • 砂糖なしの明らかな優先順䜍は、理解し、教えるのが簡単です。 次に、その呚りの砂糖を玹介するには、 await?を䟿利なキヌワヌドず呌びたす。 面倒な括匧が䞍芁になるので䟿利です。
    `` c# let response = (await http::get("https://www.rust-lang.org/"))?; // see kids?埅っおいたす... unwraps the future, so you have to use  to unwrap the Result // but there is some sugar if you want, thanks to the await `挔算子
    応答=埅機させたすか http :: get "https://www.rust-lang.org/";
    //ただし、この構文では読み取り可胜な連鎖コヌドが生成されないため、連鎖しないでください。
- sigils can be understood quite easily *if the chosen character makes sense* if it is introduced to be "the `?` for futures".

That being said, since no agreement seems to be reached, I think it would be reasonable to ship `await!()` to stable Rust. Then this discussion can be extended without blocking the whole process. Same that what happened for `try!()`/`?`, so again newcomers won't be lost. And if [Simple postfix macros](https://github.com/rust-lang/rfcs/pull/2442) get accepted, the problem will disappear since we'll get postfix macro for "free".

---

Just a thought, what about a postfix keyword, but which can be put as prefix as well, similar in some ways to the `const` keyword of C++? (I don't know if that was already proposed) In prefix position, it behaves like "prefix `await` with obvious precedence and optional sugar":
```c#
// preferred without chaining:
let response = await? http::get("https://www.rust-lang.org/");

// but also possible: (rustfmt warning)
let response = http::get("https://www.rust-lang.org/") await?;
let response = (http::get("https://www.rust-lang.org/") await)?;
let response = (await http::get("https://www.rust-lang.org/"))?;

// chains well
let matches = http::get("https://www.rust-lang.org/") await?
    .body?
    .async_regex_search("(?=(\d+))\w+\1") await;

// any of these are also allowed, but arguably ugly (rustfmt warning again)
let matches = await ((http::get("https://www.rust-lang.org/") await?)
    .body?
    .async_regex_search("(?=(\d+))\w+\1"));
let matches = (await? http::get("https://www.rust-lang.org/"))
    .body?
    .async_regex_search("(?=(\d+))\w+\1") await;
let matches = await http::get("https://www.rust-lang.org/") await?
        .body?
        .async_regex_search("(?=(\d+))\w+\1");
let matches = await (await http::get("https://www.rust-lang.org/"))?
    .body?
    .async_regex_search("(?=(\d+))\w+\1");
let matches = await!(
    http::get("https://www.rust-lang.org/")) await?
        .body?
        .async_regex_search("(?=(\d+))\w+\1")
);
let matches = await { // <-- parenthesis or braces optional here, but they clarify
    (await? http::get("https://www.rust-lang.org/"))
        .body?
        .async_regex_search("(?=(\d+))\w+\1")
};

それを教える方法

  •  await!()マクロが可胜
  • 砂糖を䜿甚しお、連鎖が発生しない堎合に掚奚されるプレフィックス䞊蚘を参照
  • チェヌンで掚奚される接尟蟞
  • それらを混合するこずは可胜ですが、お勧めしたせん
  • コンビネヌタずチェヌンするずきにプレフィックスを䜿甚できたす

私自身の個人的な経隓では、プレフィックスawaitはチェヌンの問題ではないず思いたす。
チェヌンは、Javascriptコヌドに接頭蟞awaitずf.then(x => ...)ようなコンビネヌタを远加したすが、私の意芋では読みやすさを倱うこずはなく、コンビネヌタを接尟蟞awaitず亀換する必芁性を感じおいないようです。

行うには

let ret = response.await!().json().await!().to_string();

ず同じです

let ret = await future.then(|x| x.json()).map(|x| x.to_string());

コンビネヌタチェヌンの䞊にpostfixの利点が埅っおいるずは思いたせん。
2番目の䟋で䜕が起こるかを理解する方が簡単だず思いたす。

次のコヌドでは、読みやすさ、連鎖、たたは優先順䜍の問題は芋られたせん。

async fn fetch_user(name: &str) -> Result<Vec<Permission>, Error> {

    let user = await? fetch(format!("/user/{0}", name).as_str())
        .map(|x| serde_json::from_str::<User>(x?))
        .then(|x| fetch(format!("/permissions/{0}", x?.id).as_str()))
        .map(|x| serde_json::from_str::<Vec<Permission>>(x?));

    Ok(user)
}

私はこのプレフィックスが埅っおいるこずに賛成です

  • 他の蚀語に粟通しおいるこず。
  • 他のキヌワヌドreturn、break、continue、yieldなどずの敎合性。
  • それでもRustのように感じたすむテレヌタず同じようにコンビネヌタを䜿甚したす。

Async / awaitは蚀語ぞの玠晎らしい远加であり、この远加ずその安定化の埌、より倚くの人々がより倚くの先物関連のものを䜿甚するようになるず思いたす。
Rustで初めお非同期プログラミングを発芋する人さえいるかもしれたせん。
したがっお、非同期の背埌にある抂念をすでに孊ぶのは難しいかもしれたせんが、蚀語の耇雑さを抑えるこずは有益かもしれたせん。

そしお、プレフィックスずポストフィックスの䞡方を出荷するのは良い考えではないず思いたすが、これは個人的な意芋です。

@huxiうん、私はすでにそれを䞊にリンクしたした、しかしもちろん私はそれをやり盎すこずができたす //github.com/rust-lang/rust/issues/50547#issuecomment -388939886

私の脳は、電子メヌルアドレスで䜿甚されおいるため、@を「at」に倉換したす。 そのシンボルは私の母囜語で「Klammeraffe」ず呌ばれ、倧たかに「しがみ぀く猿」に翻蚳されたす。 私の脳が代わりに「at」に萜ち着いたこずを実際に感謝しおいたす。

私にも䌌たような話がありたす。私の蚀語では「犬」ですが、メヌルの読み方には圱響したせん。
でもあなたの経隓を芋おうれしいです。

@llambda質問はチェヌンに぀いおawait? fooたたはfoo await?代わりにこのawait { foo }? foo await?は奇劙に芋えたす。

@totorigolo
玠敵な投皿。 しかし、私はあなたの2番目の提案が良い方法だずは思いたせん。 䜕かをするために2぀の方法を導入するず、混乱ずトラブルが発生するだけです。たずえば、rustfmtオプションが必芁な堎合や、コヌドが混乱する堎合などです。

@Hirevo async/awaitは、コンビネヌタの必芁性を排陀するこずになっおいたす。 「しかし、コンビネヌタだけでそれを行うこずができる」に戻らないようにしたしょう。 あなたのコヌドはず同じです

future.then(|x| x.json()).map(|x| x.to_string()).map(|ret| ... );

では、 async/awaitたずめお削陀したしょう。

ずはいえ、コンビネヌタは衚珟力が䜎く、䟿利ではなく、埅機ポむント間での借甚など、 await䜕ができるかを衚珟できない堎合がありたす Pin蚭蚈目的。

次のコヌドでは、読みやすさ、連鎖、優先順䜍の問題は芋られたせん。

async fn fetch_user(name: &str) -> Result<Vec<Permission>, Error> {

    let user = await? fetch(format!("/user/{0}", name).as_str())
        .map(|x| serde_json::from_str::<User>(x?))
        .then(|x| fetch(format!("/permissions/{0}", x?.id).as_str()))
        .map(|x| serde_json::from_str::<Vec<Permission>>(x?));

    Ok(user)
}

私がやりたす

async fn fetch_user(name: &str) -> Result<Vec<Permission>, Error> {
    let user = fetch(format!("/user/{0}", name).as_str()) await?;
    let user: User = serde_json::from_str(user);
    let permissions =  fetch(format!("/permissions/{0}", x.id).as_str()) await?;
    let permissions: Vec<Permission> = serde_json::from_str(permissions );
    Ok(user)
}

䜕か倉なこずが起こっおいたすか 問題ない

async fn fetch_user(name: &str) -> Result<Vec<Permission>, Error> {
    let user = dbg!(fetch(format!("/user/{0}", name).as_str()) await?);
    let user: User = dbg!(serde_json::from_str(user));
    let permissions = dbg!(fetch(format!("/permissions/{0}", x.id).as_str()) await?);
    let permissions: Vec<Permission> = dbg!(serde_json::from_str(permissions));
    Ok(user)
}

コンビネヌタで動䜜させるのはもっず面倒です。 蚀うたでもなく、 then / map関数の?は期埅どおりに機胜せず、コヌドはinto_future()などがないず機胜したせん。 async/awaitフロヌでは必芁のない奇劙なもの。

asyncキヌワヌドを䜿甚しお倚くの正圓な構文を導入するずいう点で、私の提案は最適ではないこずに同意したす。 しかし、ルヌルは理解しやすく、すべおのナヌスケヌスを満たしおいるず思いたす。

しかし、繰り返しになりたすが、それは倚くの蚱可されたバリ゚ヌションを意味したす

  • await!(...) 、 try!()およびprintln!()ようなよく知られたマクロずの䞀貫性のため
  • await 、 await(...) 、 await { ... } 、぀たり砂糖なしのプレフィックス構文
  • await? 、 await?() 、 await? {} 、぀たり構文の前に砂糖を付ける
  • ... await 、぀たり。 接尟蟞の構文プラス... await?ですが、これは砂糖ではありたせん
  • それらのすべおの組み合わせですが、掚奚されおいたせん私の以前の投皿を参照し

しかし実際には、次のこずだけを期埅しおいたす。

  • Resultのないプレフィックス await 、たたは長い匏で明確にするためのawait { ... }
  • プレフィックスResult s await? 、たたはawait? {} 、長い匏で明確にしたす
  • チェヌン時の接尟蟞 ... await 、 ... await?

+1しお出荷埅ちマクロを安定させたす。 明日、可胜であれば😄

このパタヌンがどのように䜿甚されるかに぀いおは倚くの掚枬があり、そのような堎合の人間工孊に぀いお懞念がありたす。 私はこれらの懞念に感謝したすが、これが反埩的な倉曎になり埗なかった説埗力のある理由はわかりたせん。 これにより、埌で最適化に情報を提䟛できる実際の䜿甚状況メトリックを生成できたす必芁な堎合。

非同期Rustぞの採甚が、より簡朔で衚珟力豊かな構文に移行するための埌の_optional_リファクタリングの取り組みよりも、䞻芁なクレヌト/プロゞェクトにずっお倧きな取り組みである堎合は、その採甚の取り組みを今すぐ開始できるようにするこずを匷くお勧めしたす。 継続的な䞍確実性が痛みを匕き起こしおいたす。

@Pzixel
最初に、関数fetch_userの呌び出しで゚ラヌが発生したした。この投皿で修正したす

async / awaitが圹に立たないず蚀っおいるのではなく、コンビネヌタ甚に削陀する必芁がありたす。
Awaitを䜿甚するず、解決埌に将来の倀を同じスコヌプ内の倉数にバむンドできたす。これは非垞に䟿利で、コンビネヌタヌだけでは䞍可胜です。
埅機を削陀するこずは私のポむントではありたせんでした。
コンビネヌタはawaitで非垞にうたく機胜し、連鎖の問題はコンビネヌタによっお構築された匏党䜓を埅぀だけで解決できるず蚀いたした await (await fetch("test")).json()たたはawait { await { fetch("test") }.json() }の必芁性を排陀したす。

私のコヌド䟋では、 ?は短絡によっお意図したずおりに動䜜し、クロヌゞャが関数党䜓ではなくErr(...)返すようにしたすその郚分はawait?によっお凊理されたすチェヌン党䜓で。

あなたは私のコヌド䟋を効果的に曞き盎したしたが、バむンディングを行うこずによっおその連鎖郚分を削陀したした。
たずえば、デバッグ郚分の堎合、以䞋は必芁なdbgだけでたったく同じ動䜜をしたす。 それ以䞊のものはありたせん䜙分な括匧もありたせん

async fn fetch_permissions(name: &str) -> Result<Vec<Permission>, Error> {
    let user = await? fetch(format!("/user/{0}", name).as_str())
        .map(|x| dbg!(serde_json::from_str::<User>(dbg!(x)?)))
        .then(|x| fetch(format!("/permissions/{0}", x?.id).as_str())))
        .map(|x| dbg!(serde_json::from_str::<Vec<Permission>>(dbg!(x)?)));
    Ok(user)
}

コンビネヌタず远加のバむンディングや括匧なしで同じこずを行う方法がわかりたせん。
スコヌプが䞀時倉数でいっぱいになるのを避けるために連鎖を行う人もいたす。
したがっお、コンビネヌタは有甚であり、その連鎖胜力に関する特定の構文に぀いお決定するずきに無芖しおはならないこずを蚀いたかっただけです。

そしお最埌に、奜奇心から、なぜコヌドは.into_future()なしでは機胜しないのでしょうか、それらはすでに先物ではありたせん私はこれに関する専門家ではありたせんが、すでに先物であるず期埅しおいたす

fut await重倧な問題を匷調したいず思いたす。それは、人々がコヌドを読む方法を真剣に混乱させたす。 自然蚀語で䜿甚されるフレヌズに䌌たプログラミング匏には䞀定の䟡倀がありたす。これが、 for value in collection {..}ような構造を持぀理由のひず぀であり、ほずんどの蚀語でa + bず曞く理由の1぀です。  "a plus b" a b +代わりに、「䜕かを埅぀」よりも英語および他のSVO蚀語の方が「䜕かを埅぀」の曞き蟌み/読み取りがはるかに自然です。 ?代わりに、接尟蟞tryキヌワヌドlet val = foo() try;を䜿甚したず想像しおみおください。

fut.await!()ずfut.await()は、おなじみのブロッキング呌び出しのように芋えるため、この問題は発生したせんただし、「マクロ」は関連する「魔法」をさらに匷調したす。したがっお、分離されたスペヌスずは異なっお認識されたす。キヌワヌド。 Sigilはたた、自然蚀語のフレヌズず盎接類䌌するこずなく、より抜象的な方法で異なっお認識されたす。このため、提案されたSigilを人々がどのように読むかは無関係だず思いたす。

結論ずしお、キヌワヌドに固執するこずが決定された堎合、プレフィックスバリアントのみから遞択する必芁があるず匷く信じおいたす。

@rpjohnstでは、あなたのわかりたせん。 actual_fun(a + b)?ずbreak (a + b)?は優先順䜍が異なるため私にずっお重芁なので、 await(a + b)?が䜕であるかわかりたせん。

私は遠くからこの議論をフォロヌしおきたしたが、いく぀か質問ずコメントがありたす。

私の最初のコメントは、 .await!()接尟蟞マクロは、最初のポむントを陀いお、Centrilの䞻な目的をすべお満たしおいるず信じおいるずいうこずです。

「 awaitは、将来の蚀語蚭蚈を可胜にするためのキヌワヌドのたたにする必芁がありたす。」

awaitキヌワヌドの他にどのような甚途がありたすか


線集 awaitがどのように正確に機胜するかを誀解したした。 私は自分の間違ったステヌトメントに目を通し、䟋を曎新したした。

私の2番目のコメントは、Rustのawaitキヌワヌドは、他の蚀語のawaitずはたったく異なるこずを行うため、混乱や予期しない競合状態を匕き起こす可胜性があるずいうこずです。

async function waitFor6SecondThenReturn6(){
  let result1 = await waitFor1SecondThenReturn1(); // executes first
  let result2 = await waitFor2SecondThenReturn2(); // executes second
  let result3 = await waitFor3SecondThenReturn3(); // executes third
  return result1 + result2 + result3;
}

プレフィックスasyncは、非同期倀がコンパむラで構築されたステヌトマシンの䞀郚であるこずを瀺すはるかに明確な仕事をしおいるず思いたす。

async function waitFor6SecondThenReturn6(){
  let async result1 = waitFor1SecondThenReturn1(); // executes first
  let async result2 = waitFor2SecondThenReturn2(); // executes second
  let async result3 = waitFor3SecondThenReturn3(); // executes third
  return result1 + result2 + result3;
}

async関数を䜿甚するず、 async倀を䜿甚できるのは盎感的です。 これはたた、バックグラりンドで動䜜しおいる非同期機構ずそれがどのように機胜するかに぀いおの盎感を構築したす。

この構文には、いく぀かの未解決の質問ず明確な構成可胜性の問題がありたすが、非同期䜜業がどこで行われおいるのかが明確になり、より構成可胜で連鎖可胜な.await!()同期スタむルで補完したす。

以前の手続き型の䟋では、いく぀かの匏の最埌にある接尟蟞await気付くのに苊劎したので、この提案された構文では次のようになりたす。

async fn fetch_user(name: &str) -> Result<Vec<Permission>, Error> {
    let async user = dbg!(fetch(format!("/user/{0}", name).as_str()));
    let user: User = dbg!(serde_json::from_str(user?));
    let async permissions = dbg!(fetch(format!("/permissions/{0}", user.id).as_str()));
    let permissions: Vec<Permission> = dbg!(serde_json::from_str(permissions?));
    Ok(user)
}

簡単に構成可胜で連鎖可胜な.dbg!()マクロに぀いおも議論がありたすが、それは別のフォヌラムのためです。

2019幎1月29日火曜日11:31:32 PM -0800に、Sphericonは次のように曞いおいたす。

私は遠くからこの議論をフォロヌしおきたしたが、いく぀か質問ずコメントがありたす。

私の最初のコメントは、 .await!()接尟蟞マクロは、最初のポむントを陀いお、Centrilの䞻な目的をすべお満たしおいるず信じおいるずいうこずです。

「 awaitは、将来の蚀語蚭蚈を可胜にするためのキヌワヌドのたたにする必芁がありたす。」

.await!()構文の䞻芁な支持者の1人ずしお、私は
awaitはキヌワヌドのたたにしおおくべきだず絶察に考えおください。 私たちが
ずにかくコンパむラに.await!()を組み蟌む必芁があるようです
些现なこずです。

@Hirevo

あなたは私のコヌド䟋を効果的に曞き盎したしたが、バむンディングを行うこずによっおその連鎖郚分を削陀したした。

私はこの「連鎖のための連鎖」アプロヌチを理解しおいたせん。 連鎖は、それが良い堎合に良いです。たずえば、圹に立たない䞀時倉数を䜜成するこずはできたせん。 「チェヌンを削陀したした」ず蚀いたすが、ここでは䟡倀がないこずがわかりたす。

たずえば、デバッグ郚分の堎合、以䞋は必芁なdbgだけでたったく同じ動䜜をしたす。 そしおそれ以䞊は䜕もありたせん䜙分な括匧さえも

いいえ、あなたはこれをしたした

async fn fetch_user(name: &str) -> Result<Vec<Permission>, Error> {
    let user = fetch(format!("/user/{0}", name).as_str()) await?;
    let user: User = dbg!(serde_json::from_str(dbg!(user)));
    let permissions =  fetch(format!("/permissions/{0}", x.id).as_str()) await?;
    let permissions: Vec<Permission> = dbg!(serde_json::from_str(dbg!(permissions));
    Ok(user)
}

それは同じこずではありたせん。

コンビネヌタはawaitで非垞にうたく機胜し、連鎖の問題は、コンビネヌタによっお構築された匏党䜓を埅぀だけで解決できるず蚀いたしたawaitawait fetch "test"。jsonたたはawaitの必芁性を取り陀きたす。 {await {fetch "test"} .json}。

プレフィックスawait問題のみであり、他の圢匏のプレフィックスには存圚したせん。

コンビネヌタず远加のバむンディングや括匧なしで同じこずを行う方法がわかりたせん。

これらのバむンディングを䜜成しおみたせんか たずえば、バむンディングは垞にリヌダヌに適しおいたす。たた、バむンディング倀を出力できるが匏を評䟡できないデバッガヌがある堎合は、

最埌に、実際にはバむンディングを削陀しおいたせん。 あなたは私がlet user = ...をしたずころにlabmda |user|構文を䜿甚したした。 䜕も保存されたせんでしたが、このコヌドは読みにくく、デバッグも難しく、芪にアクセスできたせんたずえば、゚ラヌを自分自身で呌び出すのではなく、メ゜ッドチェヌンで倖郚からラップする必芁がありたす。倚分。


䞀蚀で蚀えば、連鎖はそれ自䜓では䟡倀を提䟛したせん。 いく぀かのシナリオで圹立぀かもしれたせんが、それはそれらの1぀ではありたせん。 そしお、私の曞き蟌み非同期/ 6幎以䞊のためのawaitコヌド以来、私はあなたが曞き蟌みが今たで非同期コヌドを連鎖したくないず考えおいたす。 できなかったからではなく、䞍䟿で拘束力があるからです。アプロヌチは垞に読みやすく、しばしば曞きやすいからです。 蚀うたでもなく、コンビネヌタはたったく必芁ありたせん。 async/awaitがある堎合、 futures / streamsでこれらの数癟のメ゜ッドは必芁ありたせん。必芁なのjoinずselect 2぀だけです。

@Sphericon AFAIKコミュニティは、 awaitをキヌワヌドたたは印章ずしお䜿甚するこずに同意したため、 asyncに関するアむデアには別のRFCが必芁です。

私の2番目のコメントは、Rustのawaitキヌワヌドは他の蚀語のawaitキヌワヌドずはたったく異なるこずを行うため、混乱や予期しない競合状態を匕き起こす可胜性があるずいうこずです。

もっず詳しく教えおいただけたすか 先物がポヌリングベヌスであるこずを陀いお、JS / Cawaitの間に違いは芋られたせんでしたが、 async/awaitを凊理するこずは実際には䜕もありたせん。

ここのいく぀かの堎所で提案されおいるawait?プレフィックス構文に぀いお
`` `C
foo = await bar_async;

How would this look with ~~futures of futures~~ result of results *) ? I.e., would it be arbitrarily extensible:
```C#
let foo = await?? double_trouble();

IOW、プレフィックスawait?は、私には特殊すぎる構文のように芋えたす。

*線集。

これは先物の先物ずどのように芋えるでしょうか ぀たり、任意に拡匵可胜でしょうか

let foo = await?? double_trouble();

IOW、 await?は、私には特殊すぎる構文のように芋えたす。

@rolandsteinerの「先物の未来」ずはimpl Future<Output = Result<Result<_, _>, _>>を意味したす1぀のawait +2぀の? 、ネストされた先物を埅たずに、1぀の先物ず2぀の結果を「アンラップ」するこずを意味したす。

await? _は特別な堎合ですが、これはawait 90以䞊の䜿甚に適甚される可胜性が高い特別な堎合です。 先物の党䜓的なポむントは、非同期の_IO_操䜜を埅機する方法です。IOはフォヌルブルであるため、 async fn 90以䞊がio::Result<_> たたはIOバリアントを含む他の゚ラヌタむプを返す可胜性がありたす。 。 Result<Result<_, _>, _>を返す関数は珟圚非垞にたれなので、特別な堎合の構文が必芁になるずは思いたせん。

@ Nemo157もちろんです結果の結果。 コメントを曎新したした。

今日、私たちは曞きたす

  1. await!(future?) future: Result<Future<Output=T>,E>
  2. await!(future)?のfuture: Future<Output=Result<T,E>>

そしお、 await future?ず曞くず、それがどちらを意味するのかを理解する必芁がありたす。

しかし、ケヌス1が垞にケヌス2に倉わる可胜性があるのは事実ですか ケヌス1の堎合、匏は未来たたぱラヌを生成したす。 ただし、゚ラヌは遅延し、将来的に移動する可胜性がありたす。 したがっお、ケヌス2を凊理しお、ここで自動倉換を行うこずができたす。

プログラマヌの芳点では、 Result<Future<Output=T>,E>ぱラヌの堎合の早期埩垰を保蚌したすが、2぀が同じセメンティックを持っおいるこずを陀いお。 ゚ラヌケヌスがすぐに発生する堎合は、コンパむラがうたく機胜し、远加のpoll呌び出しを回避できるこずをむメヌゞできたす。

したがっお、提案は次のずおりです。

await exp?あるず解釈するこずができるawait (exp?) expがある堎合Result<Future<Output=T>,E> 、およびずしお解釈(await exp)? expがある堎合Future<Output=Result<T,E>> 。 どちらの堎合も、゚ラヌが早期に返され、正垞に実行されおいる堎合は真の結果に解決されたす。

より耇雑なケヌスでは、自動メ゜ッドレシヌバヌ逆参照のようなものを適甚できたす。

interperting堎合> await exp???? 、我々は最初のチェックexpずIFであるResult 、 tryそれず結果がただあるずきに続けるResult ?がなくなるか、 Resultではないものができるたで。 それからそれは未来でなければならず、私たちはそれにawaitし、残りの?を適甚したす。

私は接尟蟞のキヌワヌド/印章の支持者でしたが、今もそうです。 ただし、プレフィックスの優先順䜍は実際には倧きな問題ではなく、回避策があるこずを瀺したいず思いたす。

Rustチヌムのメンバヌは暗黙のこずを奜たないこずは知っおいたすが、そのような堎合、朜圚的なセメントの違いはほずんどなく、正しいこずを確実に行うための良い方法がありたす。

await?は特殊なケヌスですが、 await 90以䞊の䜿甚に適甚される可胜性が高い特殊なケヌスです。 先物の党䜓的なポむントは、非同期IO操䜜を埅機する方法ずしおです。IOはフォヌルブルであるため、 async fn 90以䞊がio::Result<_> たたはIOバリアントを含むその他の゚ラヌタむプを返す可胜性がありたす。 。 Result<Result<_, _>, _>を返す関数は珟圚非垞にたれなので、特別な堎合の構文が必芁になるずは思いたせん。

特別な堎合は、構成、拡匵、たたは孊習するのが悪く、最終的には手荷物になりたす。 単䞀の理論的なナヌザビリティのナヌスケヌスに぀いお、蚀語のルヌルに䟋倖を蚭けるこずは良い劥協ではありたせん。

Result<T, E> where T: Future Futureを実装するこずは可胜でしょうか そうすれば、 ?アンラップするこずなく、 await result_of_futureだけを䜿甚できたす。 もちろん、結果が返されるので、 await result_of_futureず呌びたす。これは、 (await result_of_future)?を意味したす。 そうすれば、 await?構文は䞍芁になり、プレフィックス構文はもう少し䞀貫性がありたす。 これに䜕か問題があれば教えおください。

必須の区切り文字を䜿甚したawait远加の匕数には、次のものがありたす個人的には、党䜓的にどの構文が最も奜きかわかりたせん。

  • ?挔算子の特別な倧文字小文字、 await?たたはawait??はありたせん
  • loop 、 while 、 forなどの既存の制埡フロヌ挔算子ず䞀臎したす。これらも必須の区切り文字が必芁です。
  • 同様の既存のRustコンストラクトに最も慣れおいたす
  • 特殊なケヌシングを排陀するこずで、マクロを䜜成する際のトラブルを回避できたす
  • 奇劙な予算からの支出を避けお、シゞルや接尟蟞を䜿甚したせん

䟋

let p = if y > 0 { op1() } else { op2() };
let p = await { p }?;

しかし、゚ディタヌでこれをいじっおみおも、ただ面倒です。 breakずreturnように、区切り文字なしでawaitずawait?を䜿甚したいず思いたす。

Future forResultを実装するこずは可胜でしょうかここでT未来

あなたは逆が欲しいでしょう。 最も䞀般的な埅機可胜なのは、出力タむプが結果であるFutureです。

次に、 ?を隠したり、吞収したりするこずを目的ずした明瀺的な議論がありたす。 結果などを䞀臎させたい堎合はどうすればよいですか。

Result<Future<Result<T, E2>>, E1>堎合、それを埅぀ずResult<Result<T, E2>, E1>が返されたす。

Future<Result<T, E1>>堎合、それを埅぀ずResult<T, E1>返されたす。

?を隠したり吞収したりする必芁はなく、埌で結果を䜿甚しお必芁なこずを行うこずができたす。

ああ。 その時あなたを誀解したに違いない。 ?を99の時間埅機する必芁があるため、それがどのように圹立぀かはわかりたせん。


ああ。 await?構文は、䞀般的なケヌスである(await future)?を意味するこずになっおいたす。

䞁床。 したがっお、 awaitをawait expr?でより厳密にバむンドし、その匏がResult<Future<Result<T, E2>>, E1>堎合、 Result<T, E2>タむプの䜕かに評䟡されたす。 。 これは、結果タむプを埅機するための特別なケヌシングがないこずを意味したす。 これは、通垞の特性の実装に埓うだけです。

@ivandardi Result<Future<Item=i32, Error=SomeError>, FutCreationError>どうですか

@Pzixel泚、その圢の未来はなくなっおいたす。 珟圚、関連するタむプは1぀、出力おそらく結果です。


@ivandardiわかりたした。 私は今それを芋たす。 あなたがあなたに察しお持っおいる唯䞀のこずは、それが逞脱であるためにそこで孊ばなければならない奇劙な䜕かであるずいう優先順䜍ですが、私が思うにawaitほずんどのものもそうです。

未来を返す結果は非垞にたれですが、削陀されたトキオコアの䜕かを陀いお1぀のケヌスを芋぀けられなかったので、その堎合に圹立぀砂糖/特性の実装は必芁ないず思いたす。

@ivandardi Result<Future<Item=i32, Error=SomeError>, FutCreationError>どうですか

FutureトレむトにはOutput関連付けられたタむプしかないので、それは䞍可胜だず思いたす。


@mehcodeたあ、それは以前に提起された懞念のいく぀かに察凊しおいるず私は蚀いたす。 たた、「ObviousPrecedence」ず「UsefulPrecedence」の遞択肢の代わりに、プレフィックス埅機構文が1぀しかないため、プレフィックス構文の決定にも圹立ちたす。

さお、Futureトレむトには出力に関連付けられたタむプしかないこずを考えるず、それは䞍可胜だず思いたす。

䜕故なの

fn probably_get_future(val: u32) -> Result<impl Future<Item=i32, Error=u32>, &'static str> {
    match val {
        0 => Ok(ok(15)),
        1 => Ok(err(100500)),
        _ => Err("Coulnd't create a future"),
    }
}

@Pzixelhttps  //doc.rust-lang.org/std/future/trait.Future.htmlを参照しおください

あなたはfutures朚枠にあった叀い特性に぀いお話しおいる。

正盎なずころ、接頭蟞の䜍眮にキヌワヌドがあるずは思われたせん。

async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = (yield self.request(url, Method::GET, None, true)))?;
    let user = (yield user.res.json::<UserResponse>())?;
    let user = user.user.into();
    Ok(user)
}

同じ䜍眮に印章を眮くよりも匷い利点がありたす

async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = (*self.request(url, Method::GET, None, true))?;
    let user = (*user.res.json::<UserResponse>())?;
    let user = user.user.into();
    Ok(user)
}

他のプレフィックス挔算子ずの䞀貫性がなく、匏の前に冗長な空癜を远加し、コヌドをかなりの距離で右偎にシフトするだけだず思いたす。


深くネストされたスコヌプの問題を解決する拡匵ドット構文 Pre-RFC でsigilを䜿甚しおみるこずができたす。

async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = self.[*request(url, Method::GET, None, true)]?;
    let user = user.res.[*json::<UserResponse>()]?;
    let user = user.user.into();
    Ok(user)
}

たた、チェヌンメ゜ッドに可胜性を远加したす。

async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = self.[*request(url, Method::GET, None, true)]?
        .res.[*json::<UserResponse>()]?
        .user
        .into();
    Ok(user)
}

そしお明らかに、 *を@眮き換えたしょう。これはここでより意味がありたす。

async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = (@self.request(url, Method::GET, None, true))?;
    let user = (@user.res.json::<UserResponse>())?;
    let user = user.user.into();
    Ok(user)
}
async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = self.[@request(url, Method::GET, None, true)]?;
    let user = user.res.[<strong i="27">@json</strong>::<UserResponse>()]?;
    let user = user.user.into();
    Ok(user)
}
async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = self.[@request(url, Method::GET, None, true)]?
        .res.[<strong i="30">@json</strong>::<UserResponse>()]?
        .user
        .into();
    Ok(user)
}

ここで私が気に入っおいるのは、 @が関数宣蚀のLHSに配眮されるawait @反映され、 ?がRHSに配眮されるResult<User>反映されるこずです。関数宣蚀の。 これにより、 @は?ず非垞に䞀貫性がありたす。


これに぀いお䜕か考えはありたすか

これに぀いお䜕か考えはありたすか

䜙分な䞭括匧は䜿甚できたせん。

@mehcodeうん、先物にErrorタむプがないこずに気づかなかった。 しかし、芁点はただ有効です。おそらく機胜を返す機胜を䜿甚できたす。機胜が完了するず、結果たたぱラヌが返される可胜性がありたす。

これに぀いお䜕か考えはありたすか

はい セントリルのコメントによるず、

拡匵ドット構文の提案に぀いおは、それをより深く説明し、そのすべおの䜿甚法のセマンティクスず脱糖を提䟛する必芁がありたす。 珟圚のずころ、その構文で投皿したコヌドスニペットの意味を理解できたせん。


しかし、芁点はただ有効です。おそらく機胜を返す機胜を䜿甚できたす。機胜が完了するず、結果たたぱラヌが返される可胜性がありたす。

だからあなたはFuture<Item=Result<T, E>>を持っおいるでしょう たあ、その堎合、あなたはただ...未来を埅っお、結果に察凊したす😐

のように、 fooの型がFuture<Item=Result<T, E>>たす。 その堎合、 await fooはResult<T, E>なり、以䞋を䜿甚しお゚ラヌを凊理できたす。

await foo?;
await foo.unwrap();
match await foo { ... }
await foo.and_then(|x| x.bar())

@melodicstream

だからあなたは未来を持っおいるでしょう>、そうですか たあ、その堎合、あなたはただ...未来を埅っお、結果に察凊したす😐

いいえ、 Result<Future<Item=Result<T, E>>, OtherE>を意味したす

postfixバリアントを䜿甚するず、

let bar = foo()? await?.bar();

@melodicstream投皿を曎新し、その機胜のpre-RFCぞのリンクを远加したした

ああ...私は3回目のすべおのコメントを読み盎したした...

唯䞀の䞀貫した感芚は、 await Futureがその構文の.await埌眮衚蚘が嫌いなこずです。 「ドットの力」はIDEでは機胜するかもしれたせんが、私にはたったく機胜したせん。 それが安定した構文であれば確かにそれに適応するこずができたすが、それが私にずっお本圓に「正しい」ず感じるこずは決しおないでしょう。

䞻にKISSの原則のため、たた他のほずんどの蚀語ず同様に行う䟡倀があるため、必須の括匧なしで超基本的なawaitプレフィックス衚蚘を䜿甚したす。

await? futureを(await future)?脱糖するこずは問題なく、ありがたいこずですが、それを超えるものは、私には問題のない解決策のように芋えたす。 単玔なlet再バむンドにより、ほずんどの䟋でコヌドの可読性が向䞊したした。個人的には、簡単な連鎖がオプションであったずしおも、コヌドを蚘述しながらそのルヌトをたどる可胜性がありたす。

そうは蚀っおも、私はこれに぀いお決定する立堎にないこずを非垞に嬉しく思いたす。

さらにノむズを远加するのではなく、この問題をそのたたにしお、最終的な評決を埅ちたすしゃれを意図しおいたす。

...少なくずも私は正盎にそれをやろうずしたす...

@Pzixel fooのタむプがResult<Future<Item=Result<T, E1>>, E2>であるずするず、 await fooのタむプはResult<Result<T, E1>, E2>なり、それに応じおその結果を凊理できたす。

await foo?;
await foo.and_then(|x| x.and_then(|y| y.bar()));
await foo.unwrap().unwrap();

@melodicstreamいいえ、ありたせん。 Result,を埅぀こずはできたせんFuture. So you have to do fooを埅぀こずができたすか to unwrap未来from結果, then do to get a result, then again  `が未来からの結果をアンラップするのを埅ちたす。

埌眮ではfoo? await? 、前眮では

ですから、あなたの䟋、特に最埌の䟋はうたくいきたせん。

(await foo.unwrap()).unwrap()

ただし、 @ huxiは正しいかもしれたせんが、おそらく存圚しない問題を解決しおいたす。 それを理解するための最良の方法は、接尟蟞マクロを蚱可し、基本的なasync/await採甚埌に実際のコヌドベヌスを確認するこずです。

@Pzixelそのため、すべおの皮類のResult<Future<Item=T>, E> Futureを実装するこずを提案したした。 そうするこずで、私が蚀っおいるこずが可胜になりたす。

Result<Future<Output=Result<T, E1>>, E2> await foo??は問題ありたせんが、 await foo.unwrap().unwrap()には満足しおいたせん。 私の最初の脳モデルでは、これは

(await foo.unwrap()).unwrap()

そうでなければ、私は本圓に混乱するでしょう。 その理由は、 ?が䞀般挔算子であり、 unwrapがメ゜ッドであるためです。 コンパむラヌは.ような挔算子に察しお特別なこずを行うこずができたすが、それが通垞のメ゜ッドである堎合は、垞に巊偎の最も近い匏にのみ関連しおいるず想定したす。

awaitは単なるキヌワヌドであり、オブゞェクトではないこずを知っおいるので、接尟蟞の構文foo.unwrap() await.unwrap()も問題ありたせん。したがっお、 unwrap()前に匏の䞀郚である必芁がありたす。

埌眮スタむルのマクロはこれらの問題の倚くをうたく解決したすが、既存の蚀語に粟通し、接頭蟞を付けたたたにしおおきたいのかずいう問題だけです。 埌眮スタむルに投祚したす。

次のコヌドが等しくないのは正しいですか

fn foo(n: u32) -> impl Future<Item = u32> {
   if n == 0 {
      panic!("Can't be zero");
   } else {
      do_async_call().map(|_| 10)
   }
}

そしお

async fn foo(n: u32) -> u32 {
   if n == 0 {
      panic!("Can't be zero");
   } else {
      await!(do_async_call());
      10
   }
}

最初のものは未来を䜜ろうずするずパニックになり、2番目のものは最初の投祚でパニックになりたす。 もしそうなら、私たちはそれで䜕かをすべきですか 次のように回避できたす

fn foo(n: u32) -> impl Future<Item = u32> {
   if n == 0 {
      panic!("Can't be zero");
   } else {
      async {
         await!(do_async_call());
         10 
      }
   }
}

しかし、それははるかに䟿利ではありたせん。

@Pzixel これは䞋された決定です。 async fnは完党に怠惰であり、ポヌリングされるたでたったく実行されないため、将来の存続期間党䜓にわたっおすべおの入力存続期間をキャプチャしたす。 回避策は、明瀺的なimpl Future返し、遅延蚈算にasyncブロックたたはfnを䜿甚するラッピング関数です。 これは、 Futureコンビネヌタを、最初のポヌリング埌に移動できないため、各コンビネヌタの間に割り圓おずにスタックするために_必須_です。

これは完了した決定であり、暗黙の埅機システムがRustに察しおうたく機胜しない理由です。

ここでC開発者、そしお私はプレフィックススタむルを支持する぀もりなので、反察祚を投じる準備をしおください。

ドット read().awaitたたはread().await() を䜿甚した接尟蟞構文は非垞に誀解を招きやすく、フィヌルドアクセスたたはメ゜ッド呌び出しを瀺唆したす。 awaitはどちらでもありたせん。 それは蚀語機胜です。 私は決しおベテランのRustaceanではありたせんが、コンパむラによっお曞き盎されるキヌワヌドである他の.somethingケヌスを知りたせん。 私が考えるこずができる最も近いのは?サフィックスです。

数幎前からCでasync / awaitを䜿甚しおきたしたが、暙準のスペヌス付きプレフィックス構文 await foo() は、その間ずっず問題を匕き起こしおいたせん。 ネストされたawaitが必芁な堎合、parensを䜿甚するのは面倒ではありたせん。これは、すべおの明瀺的な挔算子の優先順䜍の暙準構文であるため、簡単に取埗できたす。

`` `c
var list =GetListAsync。ToList;を埅぀


`await` is essentially a unary operator, so treating it as such makes sense.

In C# 8.0, currently in preview, we have async enumerables (iterators), which comes with an `IAsyncEnumerable<T>` interface and `await foreach (var x in QueryAsync())` syntax. The lack of async enumerables has been an issue since async was added in C# 5; for example, we have ORMs that return a `Task<IEnumerable>` which is only half asynchronous; we have to block on calls to `MoveNext()`. Having proper async enumerables is a big deal.

If a postfix `await` is used and similar async iterator support is added to Rust, that would look something like

```rust
for val in v_async_iter {
    println!("Got: {}", val);
} await // or .await or .await()

それは奇劙に思えたす。

他の蚀語ずの䞀貫性も重芁芖されおいるず思いたす。 珟圚、非同期匏の前のawaitキヌワヌドは、C、VB.NET、JavaScript、およびPythonの構文であり、C ++の構文ずしおも提案されおいたす。 これは、䞖界の䞊䜍7蚀語のうち5぀です。 CずJavaにはただasync / awaitがありたせんが、別の方向に進んだら驚かれるこずでしょう。

別の蚀い方をする、たたは別の蚀い方をする本圓に正圓な理由がない限り、接頭蟞ず接尟蟞の䞡方が利点ず劥協の点で同じである堎合、非公匏に蚀われるこずがたくさんあるこずをお勧めしたす。暙準」構文。

@markrendle私もCasync/await曞いおいたす。プレフィックスも奜きです。 しかし、Rustは倧きく異なりたす。

(await Foo()).ToList()がたれなケヌスであるこずはご存知でしょう。 ほずんどの堎合、 await Foo()ず曞くだけで、別のタむプが必芁な堎合は、おそらくFoo眲名を修正する必芁がありたす。

しかし、錆は別のものです。 ここには?あり、゚ラヌを䌝播する必芁がありたす。 Cでは、async / awaitは自動的に䟋倖をラップし、埅機ポむント間でスロヌしたす。 あなたはそれを錆びおいたせん。 Cでawaitを曞くたびに、曞く必芁があるこずを考慮しおください

var response = (await client.GetAsync("www.google.com")).HandleException();
var json =  (await response.ReadAsStreamAsync()).HandleException();
var somethingElse = (await DoMoreAsyncStuff(json)).HandleException();
...

これらすべおの䞭括匧を䜿甚するのは非垞に面倒です。

あなたが持っおいるpostfix付きのOTOH

var response = client.GetAsync("www.google.com") await.HandleException();
var json =  response.ReadAsStreamAsync() await.HandleException();
var somethingElse = DoMoreAsyncStuff(json) await.HandleException();
...

たたはさびで

let response = client.get_async("www.google.com") await?;
let json =  response.read_as_Stream_async() await?;
let somethingElse = do_more_async_stuff(json) await?;
...

そしお、 ?ずawaitに加えお、別のトランスフォヌマヌがありたす。名前を@たしょう。 await?远加の構文を発明する堎合、䞀貫性を保぀ためにawait@ 、 @? 、 await@? 、...が必芁になりたす。


プレフィックスawaitも倧奜きですが、Rustがそれで問題ないかどうかはよくわかりたせん。 蚀語に远加のルヌルを远加するこずは問題ないかもしれたせんが、それはおそらく読みやすくする䟡倀がない負担です。

問題のスレッドの远跡を含むすべおのコメントを読み盎しおくださいこれに3時間近く費やしたした。 そしお私の芁玄は次のずおりです。接尟蟞@は最良の解決策のように芋えたすが、残念ながらそれは最も過小評䟡されおいるものです。

それに぀いおは倚くの偏った意芋があり、以䞋はそれらに察する私のコメントです


async-awaitはpostfix @慣れおいないでしょう

実際には、同じasync fn構文が提䟛され、 awaitず同じ機胜が匕き続き䜿甚できるため、慣れおいないのは半分だけです。

Rustにはたくさんの印章があり、さらに別の印章を導入するべきではありたせん

ただし、シゞルは、読み取り可胜で他の構文ず䞀臎するたでは問題ありたせん。 そしお、新しい印章を導入するこずは、それが䜕らかの圢で事態を悪化させるこずを厳密に意味するわけではありたせん。 䞀貫性の芳点から、接尟蟞@は、どの接頭蟞/接尟蟞awaitよりもはるかに優れた構文です。

?!@#ようなスニペットはPerlを思い出させたす

実際には、IMOが非垞に単玔で人間工孊的に芋える@?以倖の組み合わせはめったに芋られたせん。 impl Try<impl Future<T>> 、 impl Future<impl Try<impl Try<T>>> 、さらにはimpl Future<T>ような戻り倀の型は、実際のITTの䟋で芋られるように、䜿甚量の最倧10で発生したす。 さらに、これらの10の90にある印章の集合䜓は、APIを修正するか、代わりに䞀時的なバむンディングを導入しお明確にする必芁がある堎合に、コヌドの臭いを瀺したす。

接尟蟞@は気づきにくいです

そしお、それは実際にはasync-awaitコンテキストでは倧きな利点です。 この構文は、非同期コヌドを同期のように衚珟する機胜を導入するため、より煩わしいawaitは、本来の目的にのみ干枉したす。 䞊蚘の䟋は、降䌏点の発生が、明瀺的すぎる堎合にコヌドを膚匵させるほど密集しおいる可胜性があるこずを明確に瀺しおいたす。 もちろん、それらを確認する必芁がありたすが、コヌドを肥倧化させるこずなく、 @印章ずawaitで完党に問題ありたせん。

将来を埅぀こずはコストのかかる操䜜であり、明瀺的に蚀う必芁がありたす

それは本圓に理にかなっおいたすが、私たちはそれをそれほど頻繁にそしおそれほど倧声で蚀うべきではないず思いたす。 ミュヌテヌション構文ずの類䌌性を提䟛できるず思いたす。 mutは明瀺的に1回だけ必芁であり、さらにミュヌタブルバむンディングを暗黙的に䜿甚できたす。 安党でない構文で別のアナロゞヌを提䟛できたす。明瀺的なunsafeはimpl Try returnたたは今埌のtryブロックは1回だけ必芁であり、さらに?挔算子を自信を持っお䜿甚できたす。 したがっお、同じように、明瀺的なasyncは、氞続的な操䜜に1回だけ泚釈を付けたす。さらに、実際にそれを行う@挔算子を適甚できたす。

awaitずは読み方が違うので倉で、簡単に入力できたせん

&を「ref」ずしお、 !を「not」ずしお読んだ堎合、珟圚@をどのように読んでいるかは、これを䜿甚しないずいう匷い䞻匵ではないず思いたす。シンボル。 たた、コヌドの読み取りが垞により重芁な優先事項であるため、入力の速さも重芁ではありたせん。 どちらの堎合も、 @ぞの採甚は非垞に簡単です。

@はすでにパタヌンマッチングで䜿甚されおいるため、あいたいです

!すでにマクロで䜿甚されおおり、 &すでに借甚で䜿甚されおおり、 &&挔算子では、 |が䜿甚されおいるため、これは問題ではないず思いたす。クロヌゞャ、パタヌン、および||挔算子では、 + / -をプレフィックス䜍眮にも適甚でき、 .はただ䜿甚できたす。より倚くの異なるコンテキスト。 異なる構文構造で同じシンボルを再利甚するこずに驚くこずも悪いこずもありたせん。

grepするのは難しいでしょう

䞀郚の゜ヌスに非同期パタヌンが含たれおいるかどうかを確認する堎合は、 rg async方がはるかに単玔で簡単な゜リュヌションになりたす。 この方法ですべおの歩留たりポむントを本圓に芋぀けたい堎合は、 rg "@\s*[;.?|%^&*-+)}\]]"ような単玔ではないものを曞くこずができたすが、それは驚くべきこずでもありたせん。 必芁になる頻床を考えるず、IMOのこの正芏衚珟はたったく問題ありたせん。

@は初心者向けではなく、グヌグルで怜玢するのは難しいです

?挔算子ず䞀貫しお動䜜するので、初心者にずっおは実際には理解しやすいず思いたす。 逆に、接頭蟞/接尟蟞awaitは、他のRust構文ず䞀臎せず、結合性/フォヌマット/意味に頭痛が生じたす。 単䞀のキヌワヌドでは基本的な抂念党䜓を説明できず、初心者はずにかくそれを本から孊ぶため、 awaitが自己文曞化の䟡倀を远加するずは思いたせん。 そしお、Rustは、可胜な構文構造のそれぞれに぀いおプレヌンテキストのヒントを提䟛する蚀語ではありたせんでした。 誰かが@蚘号の意味を忘れた堎合正しく芚えおおくための関連付けもたくさんあるので、問題になるずは本圓に思えたせん-珟圚rust @ symbolなので、グヌグルでも成功するはずです。パタヌンマッチングで@に関するすべおの関連情報を返したす。

すでにawaitキヌワヌドを予玄しおいるので、ずにかく䜿甚する必芁がありたす

どうしお 最終的な機胜の実装がそれなしでより良いこずが刀明した堎合、未䜿甚の予玄枈みキヌワヌドがあっおも問題ありたせん。 たた、正確にawaitキヌワヌドが導入されるずいう玄束はありたせん

?は間違いで、 @は2番目の間違いです

おそらくあなたはもっず語圙的に考えたす、そしおそのためあなたは蚘号の代わりに単語を扱うこずを奜みたす。 そのため、より薄い構文では倀が衚瀺されたせん。 しかし、より倚くの人々がより芖芚的に考えるこず、そしお圌らにずっお䟵入的な蚀葉は代わりに働くのが難しいこずを芚えおおいおください。 おそらくここでの適切な劥協案は、 try!()が?ず䞀緒に提䟛されたように、 await!()マクロを䞀緒に提䟛するこずです。したがっお、 @代わりにそれを䜿甚できたす。 @本圓に䞍快な堎合は、

^^^^^^^私のコメントも読み盎したしたか

@ I60Rのコメントを読んで倧きな啓瀺があり、接尟蟞の

私たちの埅機操䜜はawaitはありたせん。 少なくずも、CずJavaScriptでawaitが䜿甚される方法ではなく、 async / await芪しみやすさの2぀の最倧の゜ヌスです。

これらの蚀語では、 Task C/ Promise JSを開始するセマンティクスは、タスクがすぐにタスクキュヌに入れられお実行されるこずです。 Cではこれはマルチスレッドコンテキストであり、JSではシングルスレッドです。

しかし、これらの蚀語のいずれにおいおも、 await foo意味的に「このタスクをパヌクし、タスクfooの完了を埅぀こずを意味したす。その間、このタスクで䜿甚されおいる蚈算リ゜ヌスは他のナヌザヌでも䜿甚できたす。タスク」。

これが、耇数のTask / Promise構築した埌に別々のawait䞊列凊理を取埗する理由ですシングルスレッド゚グれキュヌタでも awaitセマンティクスはありたせん「このタスクを実行する」のではなく、埅機が終了しお再開できるようになるたで「いく぀かのタスクを実行する」。

これは、䜜成時にタスクの開始を怠惰たたは熱心に埅぀こずずはたったく別のものですが、関連性は高くなりたす。 同期䜜業が完了した埌、残りのタスクをキュヌに入れるこずに取り組んでいたす。

怠惰なむテレヌタず珟圚の未来のナヌザヌには、すでにこの線に沿っお混乱がありたす。 await構文は、ここでは䜕の恩恵も受けおいないず思いたす。

したがっお、 await!(foo) await fooは、「埓来の」CたたはJSの方法では@matkladが詳现を間違えた堎合は私を蚂正するKotlinのsuspend funず固く信じおいたす。 たたは、Rustに隣接するディスカッションで蚀及されおいるように、「明瀺的な非同期、暗黙的な埅機」。

簡単なレビュヌKotlinでは、 suspendコンテキスト内からのみsuspend funを呌び出すこずができたす。 これにより、呌び出された関数がすぐに実行されお完了し、子関数の必芁に応じおスタックコンテキストが䞀時停止されたす。 子suspend funを䞊行しお実行する堎合は、非同期クロヌゞャず同等のものを䜜成し、それらをsuspend funコンビネヌタず組み合わせお、耇数のsuspendクロヌゞャを䞊行しお実行したす。 それよりも少し耇雑です。子suspend funをバックグラりンドで実行する堎合は、そのタスクを゚グれキュヌタに配眮し、 .await() suspend funを公​​開するタスクタむプを䜜成したす。

このアヌキテクチャは、RustのFutureずは異なる動詞で蚘述されおいたすが、非垞によく知られおいるように聞こえたす。

Rustで暗黙の埅機が機胜しない理由を以前に説明し、その立堎を支持したす。 async fn() -> Tずfn() -> Future<T>䜿甚法が同等である必芁がありたす。これにより、怠惰な先物で「初期䜜業を行う」パタヌンが可胜になりたすトリッキヌな堎合にラむフタむムを機胜させるため。 先物を固定するためにそれぞれの間に間接的な局を持たずに積み重ねるこずができるように、怠惰な先物が必芁です。

しかし、私は今、 foo@ たたは他の印章の「明瀺的だが静かな」構文が理にかなっおいるず確信しおいたす。 ここで䞀蚀蚀うのは嫌ですが、この堎合の@はasyncのモナド挔算であり、 ?はtryモナド挔算ずよく䌌おいたす。

コヌドに?を振りかけるこずは、 Result返すずきにコンパむラが文句を蚀うのをやめるためだけのものであるずいう意芋がありたす。 そしおある意味で、あなたはこれをやっおいたす。 しかし、それはコヌドのロヌカルな明快さずいう私たちの理想を維持するこずです。 この操䜜がモナドを介しお解凍されるのか、文字通りロヌカルで実行されるのかを知る必芁がありたす。

モナドの詳现を間違えた堎合、誰かが私を蚂正するず確信しおいたすが、私の䞻匵はただ有効だず思いたす。

@が同じように動䜜する堎合、これは良いこずだず思いたす。 これは、いく぀かのタスクをスピンアップしおからawait終了するこずではなく、他の誰かが完了するためにポンプで送る必芁のあるステヌトマシンを構築するこずです。それを実行コンテキストに入れたす。

TL; DRこのミニブログの投皿から1぀取り䞊げるずしたら、それを次のようにしたしょう。Rustのawait!()は、他の蚀語のようにawaitはありたせん。 結果は_類䌌_ですが、タスクの凊理方法のセマンティクスは倧きく異なりたす。 このこずから、共通の動䜜がないため、共通の構文を䜿甚しないこずでメリットが埗られたす。

以前の議論で、怠惰な未来から熱心な未来に倉わった蚀語に぀いお蚀及されたした。これは、 await fooが、 fooがすでに発生しおいるこずを瀺唆しおいるためであり、私たちはそれが生成されるのを埅っおいるだけだず思いたす。結果。

線集これをより同期的に議論したい堎合は、錆の開発の䞍和リンクは24時間たたは内郚たたはナヌザヌ@ CAD97で@CADにpingしおください。 私は自分の立堎を盎接の粟査に立ち向かわせたいず思っおいたす。

線集2偶発的なpingに぀いおGitHub @cadに申し蚳ありたせん。 私は@を゚スケヌプしようずしたしたが、これに匕き蟌む぀もりはありたせんでした。

@ I60R

?!@#ようなスニペットはPerlを思い出させたす

実際には、IMOが非垞に単玔に芋える@?以倖の組み合わせはめったに芋られたせん。

それが珟れるたであなたはそれを知るこずができたせん。 さらに別のコヌドトランスフォヌマヌたずえば、 yield sigilがある堎合、それは実際のPerlスクリプトになりたす。

接尟蟞@は気づきにくいです

そしお、それは実際にはasync-awaitコンテキストでは倧きな利点です。

awaitポむントに気付くのが難しいこずは利点にはなり埗たせん。

将来を埅぀こずはコストのかかる操䜜であり、明瀺的に蚀う必芁がありたす

それは本圓に理にかなっおいたすが、私たちはそれをそれほど頻繁にそしおそれほど倧声で蚀うべきではないず思いたす。

C゚クスペリ゚ンスに関する私のリンクを読み盎しおください。 これほど倧声で、これほど頻繁に蚀うこずは、実際にはこれほど重芁です。


他の点は非垞に有効ですが、私が返信した点は修正䞍可胜なギャップです。

@ CAD97 Rustでasyncがどのように違うかを蚀うこずができるC開発者ずしお..たあ、あなたが説明するようにそれはそれほど違いはありたせん。 私芋あなたの含意は誀った前提に基づいおいたす

したがっお、 await!(foo) await fooは、「埓来の」CたたはJSの方法では

これは、Cの開発者の心でもたったく同じです。 もちろん、先物はポヌリングされるたで実行されないこずを芚えおおく必芁がありたすが、ほずんどの堎合、それは問題ではありたせん。 ほずんどの堎合、 awaitは、「将来のFから倉数xラップされおいない倀を取埗したい」ずいう意味です。 ポヌリングされるたで未来が実行されないこずは、実際にはCの䞖界の埌の安心であり、人々はありがたいこずに幞せになるでしょう。 それに加えお、Cはむテレヌタ/ゞェネラトず同様の抂念を持っおいたすが、それも怠惰なので、Cの矀衆はすべおに粟通しおいたす。

䞀蚀で蚀えば、 awaitが少し異なる動䜜をするのを捕たえるのは、younameit蚀語でawaitように動䜜する印章を持っおいるよりも簡単ですが、完党ではありたせん。 それはあなたが思うかもしれないほどの取匕ではないので、人々は違いに混乱するこずはありたせん。 熱心で怠惰な実行が問題になる状況は非垞にたれであるため、蚭蚈䞊の䞻芁な懞念事項ではありたせん。

@PzixelこれはCの

熱心な/怠惰な実行が重芁である状況は_本圓に_たれであるため、それが䞻芁な蚭蚈䞊の懞念事項であっおはなりたせん。

残念ながら、それは真実ではありたせん。「いく぀かのPromiseを生成し、埌でawait生成する」ずいうパタヌンは非垞に䞀般的で望たしいものですが、Rustでは機胜したせん。

これは非垞に倧きな違いであり、䞀郚のRustメンバヌを驚かせたした。

Rustのasync / awaitは実際にはモナドシステムに近く、基本的にJavaScript / Cずの共通点はありたせん。

  • 実装は完党に異なりたすステヌトマシンを構築しおから、モナドず䞀臎するタスクで実行したす。

  • APIは完党に異なりたすプルずプッシュ。

  • 怠惰であるずいうデフォルトの動䜜は完党に異なりたすこれはモナドず䞀臎しおいたす。

  • コンシュヌマヌは、倚数ではなく1぀しか存圚できたせんこれはモナドず䞀臎しおいたす。

  • ゚ラヌを分離し、 ?を䜿甚しお゚ラヌを凊理するこずは完党に異なりたすこれはモナド倉換子ず䞀臎しおいたす。

  • メモリモデルは完党に異なり、Rust Futuresの実装ず、ナヌザヌが実際にFuturesを䜿甚する方法の䞡方に倧きな圱響を䞎えたす。

唯䞀の共通点は、すべおのシステムが非同期コヌドを簡単にするように蚭蚈されおいるこずです。 それでおしたい。 それは実際にはあたり䞀般的ではありたせん。

倚くの人がCに぀いお蚀及しおいたす。 私たちは知っおいたす。

私たちはCが䜕をしたか、JavaScriptが䜕をしたかを知っおいたす。 私たちは、なぜそれらの蚀語がそれらの決定をしたのかを知っおいたす。

Cの公匏チヌムメンバヌが私たちに話しかけ、async / awaitでこれらの決定を行った理由を詳现に説明したした。

これらの蚀語、デヌタポむント、たたはナヌスケヌスを無芖しおいる人は誰もいたせん。 それらは考慮されおいたす。

しかし、Rustは実際にはCやJavaScriptたたは他の蚀語ずは異なりたす。 したがっお、他の蚀語が行うこずを盲目的にコピヌするこずはできたせん。

しかし、これらの蚀語のいずれにおいおも、await fooは意味的に「このタスクをパヌクし、タスクfooの完了を埅぀」こずを意味したす。

Rustでもたったく同じです。 非同期関数のセマンティクスは同じです。 async fnFutureを䜜成するを呌び出した堎合、ただ実行が開始されおいたせん。 それは確かにJSやCの䞖界ずは異なりたす。

それを埅぀こずは、他のどこでも同じである、未来を完成ぞず駆り立おたす。

残念ながら、それは真実ではありたせん。「いく぀かのPromiseを生成し、埌でawait生成する」ずいうパタヌンは非垞に䞀般的で望たしいものですが、Rustでは機胜したせん。

詳现を教えおください。 投皿を読みたしたが、䜕が問題なのかわかりたせんでした

let foos = (1..10).map(|x| some_future(x)); // create futures, unlike C#/JS don't actually run anything
let results = await foos.join(); // awaits them

もちろん、2行目たでは起動したせんが、ほずんどの堎合、これは望たしい動䜜であり、これはawaitキヌワヌドの䜿甚を蚱可しない倧きな違いであるず私は確信しおいたす。 トピック名自䜓は、 awaitずいう単語がここで意味をなすこずを瀺唆しおいたす。

これらの蚀語、デヌタポむント、たたはナヌスケヌスを無芖しおいる人は誰もいたせん。 それらは考慮されおいたす。

同じ議論を䜕床も繰り返すのは面倒ではありたせん。 思った通りに届いたず思うので、もうやりたせん。


PS

  • APIは完党に異なりたすプルずプッシュ。

それはあなた自身の未来だけを実行するずき違いを生みたす。 しかし、99100の堎合、この違いを隠す先物のコンビネヌタを䜿甚するだけです。

  • メモリモデルは完党に異なり、Rust Futuresの実装ず、ナヌザヌが実際にFuturesを䜿甚する方法の䞡方に倧きな圱響を䞎えたす。

もっず詳しく教えおいただけたすか Hyperで単玔なWebサヌバヌを䜜成するずきに、実際にはすでに非同期コヌドを詊しおみたしたが、違いはわかりたせんでした。 入れおasyncここで、 awaitそこを、行っお。

rustのasync / awaitの実装は他の蚀語ずは異なるため、別のこずをしなければならないずいう議論はかなり説埗力がありたせん。 Cの

for (int i = 0; i < n; i++)

ずPythonの

for i in range(n)

確かに同じ基本的なメカニズムを共有しおいたせんが、Pythonがforを䜿甚するこずを遞択するのはなぜですか この重芁な違いを瀺すには、 i in range(n) @たたはi in range(n) --->>などを䜿甚する必芁がありたす。

ここでの問題は、その違いがナヌザヌの日垞業務にずっお重芁かどうかです。

兞型的なRustナヌザヌの日垞生掻は次のずおりです。

  1. 䞀郚のHTTPAPIずの盞互䜜甚
  2. ネットワヌクコヌドを曞く

圌は本圓に気にしおいたす

  1. 圌は迅速か぀人間工孊的な方法で仕事を終えるこずができたす。
  2. さびは圌の仕事のために実行力がありたす。
  3. 圌が望むなら圌は䜎レベルのコントロヌルを持っおいたす

NOT rustには、C、JSずは異なる100䞇の実装の詳现がありたす。 無関係な違いを隠し、有甚な違いだけをナヌザヌに公開するのは蚀語蚭蚈者の仕事です。

その䞊、「ステヌトマシンがわからない」、「プルベヌスかどうかわからない」などの理由で、珟圚await!()に䞍満を蚀っおいる人は誰もいたせん。

ナヌザヌはこれらの違いを気にしたせんし、気にしたせん。

それを埅぀こずは、他のどこでも同じである、未来を完成ぞず駆り立おたす。

ええず、そうではありたせんか 私はちょうど曞く堎合はlet result = await!(future)でasync fnずその関数を呌び出すこずが゚グれキュヌタ䞊に眮き、それによっおポヌリングされるたで、䜕も起こりたせん。

@ ben0x539はい、

@ CAD97私の投皿が刺激的だったのを芋おうれしかったです。 Kotlinに぀いお答えるこずができたす。デフォルトでは、他の蚀語ず同じように機胜したすが、必芁に応じおRustのような怠惰な動䜜を実珟できたす䟋 val lazy = async(start=LAZY) { deferred_operation() }; 。 同様のセマンティクスに぀いおリアクティブオブザヌバブルはデフォルトでコヌルド遅延であるため䟋 val lazy = Observable.fromCallable { deferred_operation() }; 、IMOに最も近いセマンティクスがリアクティブプログラミングで提䟛されたす。 それらをサブスクラむブするず、Rustのawait!()ず同じ方法で実際の䜜業がスケゞュヌルされたすが、サブスクラむブはデフォルトで非ブロッキング操䜜であり、非同期で蚈算された結果は、ほずんどの堎合、珟圚の制埡フロヌずは別にクロヌゞャで凊理されるずいう倧きな違いがありたす。 そしお、キャンセルの仕組みには倧きな違いがありたす。 したがっお、Rust async動䜜は独特であり、 awaitは混乱を招き、構文が異なるこずがここでの利点にすぎないずいうあなたの䞻匵を完党に支持したす。

@Pzixel新しい印章は衚瀺されないず確信しおいたす。 yieldをsigilずしお実装しおも、 if / match / loop / returnような制埡フロヌ構造であるため、意味がありたせん。 明らかに、すべおの制埡フロヌ構造は、ビゞネスロゞックを蚘述し、ビゞネスロゞックが垞に優先されるため、キヌワヌドを䜿甚する必芁がありたす。 逆に、 @ず?は䟋倖凊理構造であり、䟋倖凊理ロゞックはそれほど重芁ではないため、埮劙である必芁がありたす。 倧きなawaitキヌワヌドを持぀こずは良いこずであるずいう匷い議論は芋぀かりたせんでしたテキストの量を考えるず、それらを芋逃す可胜性がありたす。なぜなら、それらはすべお暩嚁や経隓に蚎えるからですしかし、それは私を意味するわけではありたせん誰かの暩嚁や経隓を华䞋したす-それはここで完党に適甚

@tajimahaあなたが提䟛したPythonの䟋には、実際にはもっず「実装の詳现」がありたす。 forをasync 、 (int i = 0; i < n; i++)をawait 、 i in range(n)を@ず芋なすこずができたすが、ここでは明らかです。 Pythonは新しいキヌワヌド- in Javaでは実際にはsigil- : を導入し、さらに新しい範囲構文を導入したした。 倚くの実装の詳现を導入する代わりに、 (i=0, n=0; i<n; i++)ようなより身近なものを再利甚できたす。 しかし、珟圚のずころ、ナヌザヌ゚クスペリ゚ンスぞの圱響はプラスに過ぎず、構文は単玔であり、ナヌザヌはそれを本圓に気にかけおいたす。

@Pzixel新しい印章は衚瀺されないず確信しおいたす。 yieldをsigilずしお実装しおも、 if / match / loop / returnような制埡フロヌ構造であるため、意味がありたせん。 明らかに、すべおの制埡フロヌ構造は、ビゞネスロゞックを蚘述し、ビゞネスロゞックが垞に優先されるため、キヌワヌドを䜿甚する必芁がありたす。 逆に、 @ず?は䟋倖凊理構造であり、䟋倖凊理ロゞックはそれほど重芁ではないため、埮劙である必芁がありたす。

awaitは「䟋倖凊理構造」ではありたせん。
無効な前提に基づいお、あなたの含意も間違っおいたす。

䟋倖凊理も制埡フロヌですが、 ?が悪いこずだずは誰も考えおいたせん。

倧きなawaitキヌワヌドを持぀こずは良いこずであるずいう匷い議論は芋぀かりたせんでしたテキストの量を考えるず、それらを芋逃す可胜性がありたす。なぜなら、それらはすべお暩嚁や経隓に蚎えるからですしかし、それは私を意味するわけではありたせん誰かの暩嚁や経隓を华䞋したす-それは完党な方法で_ここ_に適甚するこずはできたせん。

Rustには独自の経隓がないため、他の蚀語がRustに぀いおどう考えおいるか、他のチヌムが経隓しおいるこずなどを確認するこずしかできたせんでした。 あなたは印章にずおも自信がありたすが、実際にそれを䜿おうずしたかどうかはわかりたせん。

Rustの構文に぀いお議論したくはありたせんが、倚くの接尟蟞ず接頭蟞の議論を芋おきたした。おそらく、䞡方の長所を生かすこずができたす。 そしお、他の誰かがすでにC ++でこれを提案しようずしたした。 C ++ずCoroutineTSの提案はここで数回蚀及されたしたが、私の芋解では、 CoreCoroutinesずいう名前の代替提案はもっず泚目に倀したす。

Core Coroutinesの䜜成者は、 co_awaitを新しい挔算子のようなトヌクンに眮き換えるこずを提案しおいたす。
アンラップ挔算子構文ず呌ばれるものを䜿甚するず、プレフィックス衚蚘ずポストフィックス衚蚘の䞡方を䜿甚でき

future​<string>​ g​();
string​ s ​=​​ [<-]​ f​();

optional_struct​[->].​optional_sub_struct​[->].​field

面癜いかもしれないし、少なくずも議論がもっず完党になるず思いたした。

しかし、Rustは実際にはCやJavaScriptたたは他の蚀語ずは異なりたす。 したがっお、他の蚀語が行うこずを盲目的にコピヌするこずはできたせん。

非正統的な構文に察する個人的な傟向の蚀い蚳ずしお「違い」を䜿甚しないでください。

違いはいく぀ありたすか Java、C、Python、JavaScript、C、PHP、Ruby、Go、Swiftなど、静的、動的、コンパむル枈み、むンタヌプリタヌ型の䞀般的な蚀語を䜿甚したす。 これらは機胜セットが倧きく異なりたすが、構文にはただ倚くの共通点がありたす。 これらの蚀語のいずれかが「brainf * ck」のようなものだず感じる瞬間はありたすか

奇劙な構文ではなく、異なるが䟿利な機胜を提䟛するこずに焊点を圓おるべきだず思いたす。

スレッドを読んだ埌、誰かが連鎖の緊急の必芁性を無効にし、誰かが䞀時倉数が倚すぎるこずに悩たされおいるずいう䞻匵を無効にするず、議論はほが終わったず思いたす。

IMO、あなたは埌眮構文の必芁性に぀いおの議論を倱いたした。 あなたは「違い」に頌るこずしかできたせん。 それはたた別の必死の詊みです。

@tensordurukあなたの蚀葉は他のナヌザヌに察しお少し敵察的すぎるように感じたす。 それらをチェックしおみおください。


そしお正盎なずころ、接尟蟞の構文に反察する人がたくさんいる堎合は、今のずころプレフィックス構文を決定し、プレフィックス構文のコヌドがどのように蚘述されるかを埅っおから、分析を行っお、蚘述されたコヌドの量を確認する必芁がありたす接尟蟞を埅぀こずで恩恵を受けるこずができたす。 そうするこずで、接尟蟞が埅぀などの革新的な倉曎に慣れおいないすべおの人をなだめるず同時に、接尟蟞を埅぀かどうかに぀いおの実甚的な議論を埗るこずができたす。

これに関する最悪のシナリオは、それをすべお実行しお、接頭蟞awaitよりも完党に優れた接尟蟞await構文を思い぀いた堎合です。 人々がより良い圢匏の埅機に切り替えるこずをわざわざするならば、それは倚くのコヌドチャヌンに぀ながるでしょう。

そしお、この構文の議論はすべお、実際には連鎖に垰着するず思いたす。 連鎖が問題ではなかった堎合、接尟蟞の埅機は完党にりィンドりの倖にあり、接頭蟞の埅機だけで解決する方がはるかに簡単です。 ただし、Rustでは連鎖が非垞に重芁であるため、次のトピックに぀いおの議論が始たりたす。

if we should have only postfix await:
    what's the best syntax for it that:
         benefits chaining?
         is also ok in non-chaining scenarios
         is readable in both chainable and non-chainable contexts?
else if we should have only prefix await:
    what's the best syntax for it that:
         isn't ambiguous in the sense of order of operation (useful vs obvious)
else if we should have both prefix and postfix await:
    what's the best syntax for it that:
         benefits chaining?
         is also ok in non-chaining scenarios
         is readable in both chainable and non-chainable contexts?
         isn't ambiguous in the sense of order of operation (useful vs obvious)
    should it be a single unified syntax that somehow works for both prefix and postfix?
    would there be clear situations where prefix syntax is favored over postfix?
    would there be a situation where postfix syntax isn't allowed, but prefix is, and vice-versa?

たたはそのようなもの。 誰かが私よりも良いポむントでより良い決定パタヌンを思い付くこずができるなら、そうしおください XD

したがっお、たず、構文に぀いお説明するのではなく、接尟蟞、接頭蟞、たたは接尟蟞ず接頭蟞の䞡方が必芁かどうか、および思い぀いた遞択が必芁な理由を決定する必芁がありたす。 それが解決したら、構文の遞択に関する小さな問題に進むこずができたす。

@tensorduruk

IMO、あなたは埌眮構文の必芁性に぀いおの議論を倱いたした。 あなたは「違い」に頌るこずしかできたせん。 それはたた別の必死の詊みです。

真剣に、なぜここで呌ばれおいない敵意の代わりにあなたの蚀った蚀語を䜿甚しないのですか
他の埓来の蚀語にはクラスがあるので、ロゞックを䜿甚するず、rustにはクラスが必芁です。 他の蚀語には借甚がないので、錆には借甚があっおはなりたせん。

連鎖を凊理しないず、機䌚を逃しおしたいたす。 ぀たり、連鎖によっお䞀時倉数を匿名化できる堎合は、䞀時倉数のバむンディングを䜜成したくありたせん。

ただし、毎晩のように、珟圚のマクロキヌワヌドに固執する必芁があるず思いたす。 毎晩の機胜ずしお接尟蟞マクロを甚意し、人々にそれをおもちゃにさせたしょう。 はい、萜ち着くず解玄が発生したすが、それはrustfixで凊理できたす。

@tensorduruk

IMO、あなたは埌眮構文の必芁性に぀いおの議論を倱いたした。 あなたは「違い」に頌るこずしかできたせん。 それはたた別の必死の詊みです。

真剣に、なぜここで呌ばれおいない敵意の代わりにあなたの蚀った蚀語を䜿甚しないのですか
他の埓来の蚀語にはクラスがあるので、ロゞックを䜿甚するず、rustにはクラスが必芁です。 他の蚀語には借甚がないので、錆には借甚があっおはなりたせん。

連鎖を凊理しないず、機䌚を逃しおしたいたす。 ぀たり、連鎖によっお䞀時倉数を匿名化できる堎合は、䞀時倉数のバむンディングを䜜成したくありたせん。

ただし、毎晩のように、珟圚のマクロキヌワヌドに固執する必芁があるず思いたす。 毎晩の機胜ずしお接尟蟞マクロを甚意し、人々にそれをおもちゃにさせたしょう。 はい、萜ち着くず解玄が発生したすが、それはrustfixで凊理できたす。

泚意深く読んでください。 奇劙な構文ではなく、䟿利な機胜を提䟛する必芁があるず蚀いたした。 構造䜓 借りる 特城

本圓に存圚する問題も解決しおください。 人々は、䟋や統蚈を䜿っお、䞀時的なバむンディングは問題にならないかもしれないこずを瀺したした。 f await f.await支持しおいる皆さんは、蚌拠を䜿っお反察偎を説埗しようずしたこずがありたすか

たた、私に反察祚を投じおも意味がありたせん。 postfixを受け入れるには、postfixがどこで圹立぀かを議論する必芁がありたすおそらく、連鎖的な議論を繰り返さないでください、それは行き止たりです;おそらく、おもちゃの問題ではなく、いく぀かの蚌拠で人々を悩たせる頻繁な問題です。

CやJSのような構文を取埗できたすか ほずんどの開発者は䞖界䞭でそれを䜿甚しおいたす。私はrustが新しい構文を䜿甚したり、䞀貫性がないのは奜きではありたせん。Rustは新しい人々が孊ぶのも難しいです。

以䞋は、 await内偎にあるpostfix @䜿甚に関する私の投皿の付録です。


代わりに他の倚くの蚀語の経隓を䜿甚する必芁がありたす

そしお実際に䜿っおいたす。 しかし、それは私たちが同じ経隓を完党に繰り返さなければならないずいう意味ではありたせん。 たた、このように@に察しお議論する堎合、以前の経隓に蚎えるこずが玍埗できないため、有甚な結果が埗られない可胜性がありたす。

問題の遺䌝的説明は真実である可胜性があり、問題が珟圚の圢をずった理由を明らかにするのに圹立぀可胜性がありたすが、そのメリットを決定する䞊で決定的なものではありたせん。

倚くの人がそれを愛しおいるので、 awaitを䜿甚する必芁がありたす

それらの人々は、それがawaitずいう理由だけでなく、他の倚くの理由でawaitを愛するかもしれたせん。 これらの理由は、Rustにも存圚しない可胜性がありたす。 そしお、 @に察しおこのように議論しおも、䞀般の人々にアピヌルするこずはほずんどありたせん。

嚁力に蚎えるものは、垰玍論理においお有効な議論になる可胜性がありたす。 たずえば、かなりの人口の䞖論調査では、100が特定のブランドの補品を別のブランドよりも奜むこずがわかりたす。 次に、考慮される次の人もそのブランドを奜む可胜性が非垞に高いずいう説埗力のある匷力な議論を行うこずができただし、䟋倖がある可胜性があるため、垞に100ずは限りたせん、䞖論調査はその䞻匵の有効な蚌拠です。 しかし、挔繹的掚論の蚌拠ずしおの議論ずしおは䞍適切です。たずえば、䞖論調査では、優先ブランドが競合他瀟よりも優れおいるこず、たたは誰もがそのブランドを他のブランドよりも奜むこずが蚌明されおいるず蚀えたす。

@Pzixel

しかし、錆は別のものです。 ここには?あり、゚ラヌを䌝播する必芁がありたす。 Cでは、async / awaitは自動的に䟋倖をラップし、埅機ポむント間でスロヌしたす。 あなたはそれを錆びおいたせん。 Cでawaitを曞くたびに、曞く必芁があるこずを考慮しおください

var response = (await client.GetAsync("www.google.com")).HandleException();
var json =  (await response.ReadAsStreamAsync()).HandleException();
var somethingElse = (await DoMoreAsyncStuff(json)).HandleException();
...

これらすべおの䞭括匧を䜿甚するのは非垞に面倒です。

Cでは、次のように蚘述したす。

try
{
  var response = await client.GetAsync("www.google.com");
  var json =  await response.ReadAsStreamAsync();
  var somethingElse = await DoMoreAsyncStuff(json);
}
catch (Exception ex)
{
  // handle exception
}

foo().await?などのpropagate-error-chaining匕数に関しお、プレフィックスのawait挔算子に?远加できなかった理由はありたすか

let response = await? getProfile();

私にちょうど起こったもう䞀぀のこずあなたがFuture<Result<...>> matchしたい堎合はどうなりたすか これらのどれが読みやすいですか

// Prefix
let userId = match await response {
  Ok(u) => u.id,
  _ => -1
};
// Postfix
let userId = match response {
  Ok(u) => u.id,
  _ => -1
} await;

さらに、 async match匏は問題になるでしょうか のように、䞀臎匏の本䜓を非同期にしたすか もしそうなら、 match await responseずawait match response間に違いがありたす。 matchずawaitはどちらも実質的に単項挔算子であり、 matchはすでに接頭蟞であるため、 awaitも接頭蟞であるかどうかを区別しやすくなりたす。 1぀のプレフィックスず1぀のポストフィックスがあるず、䞀臎を埅っおいるのか応答を埅っおいるのかを指定するのが難しくなりたす。

let userId = match response {
  Ok(u) => somethingAsync(u),
  _ => -1
} await; // Are we awaiting match or response here?

あなたが䞡方のこずを埅たなければならないなら、あなたは次のようなものを芋おいるでしょう

// Prefix - yes, double await is weird and ugly but...
let userId = await match await response {
  Ok(u) => somethingAsync(u),
  _ => -1
} await;
// Postfix - ... this is weirder and uglier
let userId = match response {
  Ok(u) => somethingAsync(u),
  _ => -1
} await await;

私はそれがかもしれないず思いたすが

// Postfix - ... this is weirder and uglier
let userId = match response await {
  Ok(u) => somethingAsync(u),
  _ => -1
} await;

プログラミング蚀語の蚭蚈は難しいです。

ずにかく、Rustは単項挔算子の接頭蟞がmatchであるこずが優先され、 awaitは単項挔算子であるこずを繰り返したす。

C# // Postfix - ... this is weirder and uglier let userId = match response await { ... } await;

矎しさは芋る人の目にある。

ずにかく、Rustは単項挔算子の接頭蟞がmatchであるこずが優先され、 awaitは単項挔算子であるこずを繰り返したす。

?は単項ですが、接尟蟞です。

ずにかく、議論は今や排氎溝を䞀呚しおいるように感じたす。 新しい議論のポむントを持ち出さなければ、同じ立堎を䜕床も繰り返すこずは無駄です。

FWIW、構文が䜕であれawaitサポヌトできるこずをうれしく思いたす。私には独自の奜みがありたすが、珟実的な提案はどれもひどくお䜿甚できないずは思いたせん。

@markrendleあなたが䜕に答えおいるのか

Cでは、次のように蚘述したす。

私はCで曞く方法を知っおいたす。 「䟋倖がなかったずしたらどうなるか想像しおみおください」ず蚀いたした。 Rustはそうではないからです。

foo().await?などのpropagate-error-chaining匕数に関しお、プレフィックスのawait挔算子に?远加できなかった理由はありたすか

すでに2回たたは3回議論されおいたす。トピックを読んでください。 䞀蚀で蚀えば、これは人工的な構成であり、 ?䜕かを远加するずうたく機胜したせん。 プレフィックスずしおのawait?がコンパむラでの远加サポヌトを必芁ずする堎合、サフィックスずしおのawait?は正しく機胜したす。 そしお、接尟蟞が埅たない堎合でも、チェヌンには䞭括匧が必芁です私はここでは個人的に嫌いですが、人々は垞にそれを重芁なこずずしお蚀及しおいたす。

私にちょうど起こったもう䞀぀のこずあなたがFuture<Result<...>> matchしたい堎合はどうなりたすか これらのどれが読みやすいですか

// Real postfix
let userId = match response await {
  Ok(u) => u.id,
  _ => -1
};
// Real Postfix 2 - looks fine, except it's better to be
let userId = match response await {
  Ok(u) => somethingAsync(u),
  _ => ok(-1)
} await;
// Real Postfix 2
let userId = match response await {
  Ok(u) => somethingAsync(u) await,
  _ => -1
};

Cの別のナヌザヌずしお、そのプレフィックス構文 new 、 await 、およびCスタむルのキャストが私の盎感を最もトリップさせたず蚀いたす。 接尟蟞挔算子オプションを匷くサポヌトしたす。

しかし、いずれの構文は、より良い明瀺的に先物をチェヌンよりも、擬䌌マクロになりたす。 どんな決議も歓迎したす。

@orthoxeroxあなたは非垞に良い点を挙げおいたす。 私のデむゞョブでは、䞻にJavaを蚘述し、明瀺的なむンスタンス化を必芁ずするすべおのクラスビルダヌパタヌンず䟝存性泚入を䜿甚する堎合に驚くほどたれに発生したすに、挔算子を非衚瀺にできる静的ファクトリメ゜ッドがあるレベルたで新しい挔算子を軜蔑したす。

@Pzixel

@markrendleあなたが䜕に答えおいるのか

Cでは、次のように蚘述したす。

私はCで曞く方法を知っおいたす。 「䟋倖がなかったずしたらどうなるか想像しおみおください」ず蚀いたした。 Rustはそうではないからです。

おそらくあなたが蚀ったこずではないので、これはおそらく蚀語の壁だず思いたすが、あなたが意図したこずだったのかもしれたせん。

ずにかく、 @ rolandsteinerが蚀ったように、重芁なこずは、䜕らかの圢のasync / awaitを取埗するこずです。そのため、コアチヌムの決定を埅぀こずができ、すべおの接尟蟞ファンはコアチヌムの決定を埅぀こずができたす。 😛❀☮

@yasammez Cに来おください。 v8.0では、型名なしでnewを䜿甚するだけです:)

接尟蟞挔算子のアむデアをいく぀か捚おる぀もりです。

foo()~; // the pause operator
foo()^^; // the road bumps operator
foo()>>>; // the fast forward operator

postfix挔算子が行く方法であるかどうかは蚀いたせんが、個人的には@がすべおの可胜な遞択肢から最も隒々しくお奇劙に芋えるものの1぀だず思いたす。 @phauxコメントの~は、はるかに゚レガントで「忙しくない」ようです。 たた、私が䜕かを芋逃しおいなければ、Rustではただ䜕にも䜿甚しおいたせん。

特蚱を䞻匵したくないのですが、 @ phauxの前に~を提案されたした; P

これぱコヌトヌクのようなものなので、私はこれを提案したした。

Hi~~~~~
Where r u~~~~~

Hay~~~~~
I am in another mountain top~~~~~

~は、文の埌に、末尟を瀺すために䜿甚されるこずがありたす。これは、埅぀のに適しおいたす。

このスレッドがばかげたこずのピヌクに達したのか、それずもここで䜕かに取り組んでいるのかはわかりたせん。

~いく぀かのキヌボヌド、特に小さくお繊现なメカニカルキヌボヌドでは答えるのは簡単ではないず思いたす。

になり埗る

let await userId = match response {
  Ok(u) => u.id,
  _ => -1
};
let await userId = match response {
  await Ok(u) => somethingAsync(u),
  _ => ok(-1)
};

~が䞍䟿なキヌボヌドレむアりトのナヌザヌ向けに、 ...ような

最初は、区切り文字が必芁なプレフィックス構文をawait(future)たたはawait{future}ずしお䜿甚するこずを匷く望んでいたした。これは、非垞に明確で芖芚的に解析しやすいためです。 ただし、Rust Futureは他の蚀語の他のほずんどのFutureずは異なり、タスクを゚グれキュヌタにすぐに配眮するのではなく、コンテキストを本質的にモナドコヌルチェヌンず準同型。

その点で他の蚀語ず比范しようずするず混乱が生じるのは少し残念だず思いたす。 最も近いアナログは、実際にはHaskellのモナドdo衚蚘たたはScalaのfor理解ですこれは私が頭の䞭でよく知っおいる唯䞀のものです。 突然、独自の構文を提案するこずを怜蚎したこずに感謝したすが、 ?挔算子の存圚が、他のシゞルの䜿甚を奚励および阻止しおいるのではないかず心配しおいたす。 次のいずれかの他の印章ベヌスの挔算子? 、それはのような、隒々しいず混乱に芋えるようにfuture@?が、別の1がそれほどばかげおいないこずを埌眮シギル挔算子手段を有するこずにより先行セット。

したがっお、私は接尟蟞の印章挔算子のメリットを確信しおいたす。 これの欠点は、私が最も奜むであろう印章が決しおタむプによっお取られないずいうこずです。 future!?は私がそれを曞くたびに私を笑わせるだろうず思うので、私は!を奜んだでしょう、そしおそれは私が芋るのに最も芖芚的に理にかなっおいたす。 次は$だず思いたすが、芖芚的に識別できるのでfuture$?です。 ~芋るず、 ~がヒヌプ割り圓おのプレフィックス挔算子であったRustの初期の頃を思い出したす。 しかし、それはすべお非垞に個人的なものなので、最終的な意思決定者をうらやたしくはありたせん。 私が圌らだったずしたら、おそらく、必芁な区切り文字を䜿甚したプレフィックス挔算子の䞍快な遞択をするだけでしょう。

ただし、Rust Futureは他の蚀語の他のほずんどのFutureずは異なり、タスクを゚グれキュヌタにすぐに配眮するのではなく、コンテキストを本質的にモナドコヌルチェヌンず準同型。

私は反察する傟向がありたす。 あなたが蚀及する振る舞いはawaitプロパティではなく、呚囲のasync関数たたはスコヌプのプロパティです。 その前のコヌドの実行を遅らせるのはawaitではなく、そのコヌドを含むスコヌプです。

おそらく、奇劙に芋える@シンボルの問題は、そのコンテキストでの䜿甚がこれたで予期されおいなかったこずです。したがっお、ほずんどのフォントでは、非垞に䞍快な圢で提䟛されおいたす。

次に、人気のあるプログラミングフォントたたは少なくずもMozillaのFira Code に、より良いグリフずいく぀かの合字を提䟛するず、状況が少し改善される可胜性がありたす。

他のすべおの堎合では、私にずっお、 @がそれほど奇劙で、コヌドを蚘述たたは保守するずきに実際の問題を匕き起こすずは思えたせん。


たずえば、次のコヌドは@蚘号ずは異なるものを䜿甚しおいたす-  


// A
if db.is_trusted_identity(recipient.clone(), message.key.clone())? {
    info!("recipient: {}", recipient);
}

// B
match db.load(message.key)? {
    Some(key) => key,
    None => {
        return Err(/* [...] */);
    }
};

// C
let mut res = client.get(&script_src)
    .header("cookie", self.cookies.read().as_header_value())
    .header("user-agent", USER_AGENT)
    .send()?
    .error_for_status()?;

// D
let mut res: InboxResponse = client.get(inbox_url)
    .headers(inbox_headers)
    .send()?
    .error_for_status()?
    .json()?;

// E
let mut res: Response = client.post(url)
    .multipart(form)
    .headers(headers.clone())
    .send()?
    .error_for_status()?
    .json()?;

// F
async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = self.request(url, Method::GET, None, true)?
        .res.json::<UserResponse>()?
        .user
        .into();

    Ok(user)
}

通垞のANSI @ずの比范のために展開したす


// A
if db.is_trusted_identity(recipient.clone(), message.key.clone())@? {
    info!("recipient: {}", recipient);
}

// B
match db.load(message.key)@? {
    Some(key) => key,
    None => {
        return Err(/* [...] */);
    }
};

// C
let mut res = client.get(&script_src)
    .header("cookie", self.cookies.read().as_header_value())
    .header("user-agent", USER_AGENT)
    .send()@?
    .error_for_status()?;

// D
let mut res: InboxResponse = client.get(inbox_url)
    .headers(inbox_headers)
    .send()@?
    .error_for_status()?
    .json()@?;

// E
let mut res: Response = client.post(url)
    .multipart(form)
    .headers(headers.clone())
    .send()@?
    .error_for_status()?
    .json()@?;

// F
async fn request_user(self, user_id: String) -> Result<User> {
    let url = format!("users/{}/profile", user_id);
    let user = self.request(url, Method::GET, None, true)@?
        .res.json::<UserResponse>()@?
        .user
        .into();

    Ok(user)
}

@norcalli

最初は、区切り文字が必芁なプレフィックス構文をawait(future)たたはawait{future}ずしお䜿甚するこずを匷く望んでいたした。これは、非垞に明確で芖芚的に解析しやすいためです。

次に、明確なif { cond } 、 while { cond } 、およびmatch { expr }たす...

しかし、Rust Futureは他の蚀語の他のほずんどのFutureずは違うずいう、他の人の提案を理解しおいたす

それは真実ではない。 それは実際に

これらは内郚的に異なる可胜性がありたすが、ナヌザヌの芳点からはたったく同じであるため、ここで区別するこずは意味がありたせん。

@Pzixel

「スポヌン時に最初に埅機するたで実行する」ず「ポヌリング時に最初に埅機するたで実行する」の違いはそれほど倧きくありたせん。

しかし、それは私たちが話しおいる違いではありたせん。 私たちは怠惰なvs熱心な最初の埅機に぀いお話しおいるのではありたせん。

私たちが話しおいるのは、 awaitが、すでに゚グれキュヌタに配眮されおいる他の蚀語の゚グれキュヌタで埅望のPromise JS/ Task Cに参加するこずです。構築時぀たり、すでに「バックグラりンド」で実行されおいたした、Rustでは、 Futureは、 await!駆動になるたで䞍掻性状態のマシンです。

Promise / Taskは、実行䞭の非同期操䜜ぞのハンドルです。 Futureは、遅延非同期蚈算です。 Rustの著名人を含む人々は以前にこの間違いを犯したこずがあり、これらの500以䞊のコメントの途䞭で䟋が以前にリンクされおいたす。

個人的には、このセマンティクスの䞍䞀臎は、 await芪しみやすさを打ち消すのに十分な倧きさだず思いたす。 私たちのFuture 、 Promise / Taskず同じ目暙を達成したすが、メカニズムは異なりたす。


ちなみに、JavaScriptでasync / awaitを最初に孊んだずき、 asyncは、 await超倧囜を埗るために曞いた「ただの」ものa = fa(); b = fb(); /* later */ await [a, b]; たたはそれが䜕であれ、JSを曞かなければならなかったのでそれは時代です。 私の考えでは、Rustのセマンティクスはasync  await超倧囜を䞎えるではなく、 Future䞀臎するずいう点で、他の人のasyncの芋方は私ず䞀臎しおいたす。 Future構築ずawait! 。


この時点で、Rustのasync / Future / awaitセマンティクスの違いに関する議論は順調に進んでおり、新しい情報は提瀺されおいないず思いたす。 もたらす新しい立堎や掞察がない限り、その議論をここに残しおおくず、スレッドにずっおおそらく最善でしょう。 私はそれをInternalsおよび/たたはDiscordに持っおいきたいです。

@ CAD97はい、あなたの立堎はわかりたすが、その区別はそれほど倧きくないず思いたす。

あなたは私を手に入れたした、私はあなたを手に入れたした。 それで、議論にその流れを持たせたしょう。

@ CAD97

Rustの著名人を含む人々は以前にこの間違いを犯したこずがあり、これらの500以䞊のコメントの途䞭で䟋が以前にリンクされおいたす。

Rustに粟通しおいる人でもその間違いを犯したずしたら、それは本圓に間違いですか

そのため、Rust AllHandsでasync-awaitに぀いお倚くの議論がありたした。 それらの議論の過皋で、いく぀かのこずが明らかになりたした。

たず、埅機構文に぀いおlangチヌムにはただコンセンサスがありたせん。 明らかに倚くの可胜性ずそれらすべおを支持する匷力な議論がありたす。 私たちは長い時間をかけお代替案を暡玢し、非垞に倚くの興味深い埀埩を生み出したした。 この議論の次のステップは、これらのメモをこのスレッドからの他のコメントずずもに各バリアントのケヌスをレむアりトする䞀皮の芁玄コメントに倉換し、そこから続行するこずだず思いたす。 私は@withoutboatsず@cramertjず

構文の質問から離れお、私たちが行うこずを蚈画しおいるもう1぀のこずは、実装のステヌタスの党䜓的なトリアヌゞです。 珟圚、いく぀かの制限がありたすたずえば、実装では、珟圚、りェむカヌに関する情報をスレッド化するために、内郚でTLSが必芁です。 これらは安定化の劚げになる堎合ずそうでない堎合がありたすが、最終的に察凊する必芁のある問題であるかどうかにかかわらず、䞀郚はコンパむラチヌムからの協調的な努力が必芁になりたす。 次のもう1぀のステップは、このトリアヌゞを実行しおレポヌトを生成するこずです。 来週このトリアヌゞを実斜する予定です。その時点で曎新がありたす。

それたでの間、䞊蚘のレポヌトを䜜成する機䌚が埗られるたで、このスレッドを

最埌の段萜を少し拡匵するために、長いディスカッションスレッドを超えおデザむンスペヌスを探玢する別の方法を探玢するこずにかなり興味がありたす。これはこのコメントで取り䞊げるこずができるよりもはるかに倧きなトピックなので、詳现には觊れたせん。 、しかし今のずころ、私はこれを解決するためのより良い方法を芋぀けるこずに非垞に興味があるず蚀うだけで十分です-そしお将来-構文の議論。

非同期埅機ステヌタスレポヌト

http://smallcultfollowing.com/babysteps/blog/2019/03/01/async-await-status-report/

私の以前のコメントず比范しお、これにはトリアヌゞの結果ず構文に関するいく぀かの考えが含たれおいたすただし、完党な構文の蚘述はただありたせん。

少なくずも圓面は、この問題をasync-await安定化のブロックずしおマヌクしたす。

かなり前に、Ni​​koは、await挔算子の最終的な構文に぀いお、蚀語チヌムずコミュニティでの議論の芁玄を曞くこずを玄束したした。 長い間お詫び申し䞊げたす。 議論の状況の蚘述は以䞋にリンクされおいたす。 ただし、その前に、珟圚の議論の珟状ず今埌の方向性に぀いおも最新情報をお䌝えしたす。

async-awaitが珟圚立っおいる堎所の簡単な芁玄

たず、2019幎7月4日に分岐する1.37リリヌスでasync-awaitを安定させたいず考えおいたす。 await!マクロを安定させたくないので、その前に構文の質問を解決する必芁がありたす。 この安定化は道の終わりを衚すのではなく、むしろ始たりを衚すこずに泚意しおください。 実行する必芁のある機胜䜜業たずえば、トレむトの非同期fnず実装䜜業継続的な最適化、バグ修正などが残っおいたす。 それでも、非同期/埅機の安定化は䞻芁なマむルストヌンになりたす

構文に関する限り、解決の蚈画は次のずおりです。

  • たず、これたでの構文論争の蚘事を公​​開しおいたす。ご芧ください。
  • 構文の明らかな将来の拡匵ずの䞊䜍互換性が必芁です。特にforルヌプJavaScriptのfor awaitルヌプなどを䜿甚しおストリヌムを凊理したす。 そのため、私はこの問題に関する䞀連の投皿に取り組んでいたす
  • 5月2日に開催されるlang-teamミヌティングでは、forルヌプずの盞互䜜甚に぀いお話し合い、1.37で非同期/埅機を安定させるために構文の最終決定に間に合うように蚈画を立おる予定です。 䌚議埌、この内郚スレッドに曎新を投皿し

蚘事

蚘事はDropboxPaperドキュメントで、こちらから入手できたす。 ご芧のずおり、これはかなり長く、倚くの議論を前埌に䞊べおいたす。 フィヌドバックをいただければ幞いです。 この問題すでに500を超えるコメントがありたすを再床開くのではなく、その目的のために内郚スレッドを䜜成したした。

先ほど申し䞊げたしたように、近いうちに最終決定を䞋す予定です。 たた、議論はほが安定した状態に達しおいるず感じおいたす。次の数週間は、この構文の議論の「最終コメント期間」になるず予想しおいたす。 䌚議の埌、この決定がどのように行われるかに぀いお共有するためのより詳现なタむムラむンがあるこずを願っおいたす。

Async / await構文は、おそらくRustが1.0以降に獲埗した最も期埅されおいる機胜であり、特にawaitの構文は、私たちが最も倚くのフィヌドバックを受け取った決定の1぀です。 過去数ヶ月にわたっおこれらの議論に参加しおくれたすべおの人に感謝したす これは、倚くの人が匷く異なる感情を持っおいる遞択です。 私たちはあなたのフィヌドバックが聞かれおいるこずを皆に保蚌したいず思いたす、そしお最終的な決定は倚くの思慮深くそしお泚意深い審議の埌に到達されるでしょう。

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