C vs C++ vs Rust Part.2

■ このスレッドは過去ログ倉庫に格納されています
1デフォルトの名無しさん
垢版 |
2021/12/15(水) 12:35:50.91ID:biBE4xC0
競え
※前スレ
C++ vs Rust
https://mevius.5ch.net/test/read.cgi/tech/1619219089/
2022/01/12(水) 23:16:19.38ID:DMKGOQqO
>>584
ファクトリメソッド経由でしかコンストラクタは呼び出せないようにするんだよ
2022/01/12(水) 23:43:13.07ID:DMKGOQqO
コンストラクタでエラーが発生しないようにするのはリークの問題じゃなくて使いやすさの問題
new Hoge()を呼べるなら個別にハンドリングが必要なエラーは発生しないと分かるのが重要
デストラクタと違ってコーディング規約的なもの
590デフォルトの名無しさん
垢版 |
2022/01/13(木) 00:32:37.82ID:RultHF/h
>>589
コーディング規約(w

コンストラクタ内で、動的配列のクラスやテンプレートを使ってると、例外が発生する
可能性は常にある。 他の言語は知らんが、C++の場合、コンストラクタ内で例外が
発生すると、デストラクタは呼ばれない。
591デフォルトの名無しさん
垢版 |
2022/01/13(木) 00:41:21.53ID:RultHF/h
例えば、ファイルハンドルをラップしたファイルクラスがあったとして、引数なしの
デフォルトコンストラクタと、引数でオープン済のファイルハンドルを渡すコンスト
ラクタを定義したとして、後者のコンストラクタが無効なファイルハンドルを引数
として呼ばれたら、例外をスローするように実装するだろ?

後者のコンストラクタは、dup()で複製したファイルハンドル等を扱う際に必要。
2022/01/13(木) 01:53:08.91ID:hGSK4csp
>>591
ファイルハンドルが無効な場合をエラーとして処理すべきならコンストラクタを直接使わせずファクトリー経由にする
panic相当の例外として処理すべきならコンストラクタ使って例外スローでかわまない
2022/01/13(木) 05:45:30.92ID:aa54J19o
>>587
それとコンストラクタで例外発生させないことは関係なくね?
2022/01/13(木) 07:16:55.50ID:QuitFgmw
コンストラクタも例外も存在しないRustでは問題自体が生じない
>>591のケースでもRustでは後者のビルダー関数がResultを返すだけで済む
595デフォルトの名無しさん
垢版 |
2022/01/13(木) 08:12:03.99ID:RultHF/h
Rustって、名前の通り錆付いてるようだな。 例外(Exception)がないって、要は
Panicって名前とtry〜catchと互換性のない俺仕様の記述を発明しただけじゃん。

ttps://news.ycombinator.com/item?id=11370841
ttps://www.reddit.com/r/rust/comments/bzaxf2/why_rust_doesnt_have_exception_handling/
ttp://joeduffyblog.com/2016/02/07/the-error-model/

返す型を限定するのは、C++でもコーディング規約で縛れば済むだけの話だし。

結局、Nullポインタ程度で騒いでいるのは、マニュアルフォーカスのカメラでピンボケ
するとか、マニュアルミッションの車でクラッチ繋ぐのミスると、エンストするって
言ってるのと変わらん気がするナァ。
2022/01/13(木) 08:32:43.99ID:pYL+3tES
>>595
開発人数が増えると規約を守らせるコストが大きくなるからね
2022/01/13(木) 08:53:54.36ID:QuitFgmw
>>595
panicと例外は全く異なる
議論に立ち入りたいならばせめて最小限の理解をしよう
完成した通常のプログラムにおいてpanicが発生するのはメモリ不足の時のみ

次に、例外はそもそも必要ないことに気付こう
エラーが発生する可能性があるならばエラーを返せばよいだけだ
これでプログラミングにおいて困ることはない
try〜catchの例外機構はそもそも必要のないものだったのだ
2022/01/13(木) 12:20:53.94ID:VLvCS3li
>>597
panicが発生したときの制御フローは通常のフローと同じなの?

もし違うのなら、通常フローへの復帰はどうやるの?
2022/01/13(木) 12:34:07.73ID:k/BdCeDW
>>598
unwindingされてキャッチされるまでスタックが巻き戻るよ
例外と同じ
2022/01/13(木) 13:04:20.54ID:nB26Onrd
その点も含めて、少なくとも >597 の「全く異なる」は嘘だね。
後段の「エラーが発生する可能性があるならばエラーを返せばよいだけだ」についても、
じゃぁ何で panic があるの?ってなるし、どういうわけか例外憎しで適当なこと言いたいだけみたい。
2022/01/13(木) 13:23:05.77ID:k/BdCeDW
rustのpanicとかエラーハンドリングの考え方はgolangの影響大きい気はする
Result型を使うか多値でエラーを返すかの違いはあるが、panicという名前と動作、戻り値との使い分けは同じ
2022/01/13(木) 13:24:11.54ID:k/BdCeDW
なので >>595 のrustは俺仕様を発明したという指摘も事実と異なると思う
2022/01/13(木) 14:47:56.89ID:ToUR5G3E
エラーモデルの理解が浅い人を寄ってたかって叩いたところで得るものはないぞ
604デフォルトの名無しさん
垢版 |
2022/01/13(木) 15:05:09.73ID:2BXAobev
>>598
panicはバグ発生かメモリ不足でのみ起きる。
だから通常フローへの復帰はせずにabortとなる。
abort前に後処理をしたい時やデバッグ情報を出したい時のためにstd::panic::catch_unwindがある。
それらの処理のためにスタックが巻き戻る。

>>600
一方でtry catch例外処理はpanicとは完全に異なるものである。
単なるエラー処理でも使われて通常フローへの復帰をする。
そのためtry catchが言語の構文となっている言語も多い。
GoやRustにはこの例外処理はなくtry catchも無い。

プログラミングにおいて、エラー処理のためのtry catch例外処理は本来不要なものである。
エラーは関数の戻り値で返せばよい。
このように本来のやり方でエラーを返すのがGoやRustであり、これで実際に動いている。
つまり、単なるエラー処理のための例外機構は必要ないものであることがわかる。
2022/01/13(木) 15:34:59.47ID:oax73caB
>>604
話が微妙に違うなぁ。

「エラー処理としての例外は不要(panicや例外みたいに制御フローが異なる機能は必要)」
という話と
「例外処理そのものが不要」
という話がごっちゃになっていない?
2022/01/13(木) 15:50:06.61ID:E5YlFTVp
>>604
> プログラミングにおいて、エラー処理のためのtry catch例外処理は本来不要なものである。
> エラーは関数の戻り値で返せばよい。

あらゆる関数/メソッド呼び出しのたびにエラーチェックをするのが煩雑だから、try-catchが生み出されたんだと思う。
例えば、データベースアクセスが発生する三つの関数を呼び出すとき、
try {
  foo();
  bar();
  baz();
  commit();
} catch () {
  rollback();
}
みたいな。
続行不能なエラーが発生したが、本流に戻る必要があるときは便利。
607デフォルトの名無しさん
垢版 |
2022/01/13(木) 15:52:35.91ID:2BXAobev
>>605
話がごっちゃになっているのはtry catchの例外処理。

Rustでpanicが起きるのはバグとメモリ不足であり、絶対に起きてはいけない状況。
だからpanicの標準動作はそのままabortとなっている。
一方でエラー処理は起き得ることだから関数の戻り値で返す。

一方でtry catchの例外処理は、それらをごっちゃにまとめて扱っている。
単なるエラー処理を、なぜ、try catchで扱ってしまうのか?
それは関数の仕様設計ミスである。
ちゃんとエラーを返せば、単なるエラー処理のための例外処理は不要となる。
2022/01/13(木) 15:56:44.41ID:wvcpI8iw
Rust擁護するあまり無理筋の論理展開だな
プログラミングに必須じゃない機能は不要と言い出したらキリないのでは
2022/01/13(木) 15:59:01.01ID:k/BdCeDW
>>607
rustのpanicだってabuseできるし
べき論の話で言ったらC++もエラー処理には戻り値を使うべき

現在のベストプラクティスは両者とも大差ないのでは
610デフォルトの名無しさん
垢版 |
2022/01/13(木) 16:20:05.76ID:2BXAobev
>>606
Rustなら色々やり方あろうけど、わかりやすい例にするとこうなる。

fn main() {
match sub() {
Ok(result) => { commit(); println!("OK: {}", result); },
Err(err) => { rollback(); println!("ERROR: {}", err); },
}
}

sub() -> Result<DataType, Error> {
let a = foo()?;
let b = bar()?;
baz(a, b)
}

foo(), bar(), baz()各々はResultでエラー値も同時に返しているが、エラーチェックはまとめて出来る。
ResultはOkとErrの2つを取るenumであり、matchは強力なswitch相当と思っていただければいい。
try catchといった例外処理がなくてもプログラミングで困ることはない。
2022/01/13(木) 16:27:12.94ID:E5YlFTVp
>>609
> べき論の話で言ったらC++もエラー処理には戻り値を使うべき

>>606 のコードをこんな感じで書くの?

int process()
{
  if (foo() != 0)
    return -1;
  if (bar() != 0)
    return -1;
  if (baz() != 0)
    return -1;
  return 0;
}

int hoge()
{
  if (begin() != 0)
    return -1;
  int ret = porcess();
  if (ret == 0) {
    if (commit() = 0)
      return 0;
  }
  (void)rollback();
  return -1;
}
2022/01/13(木) 16:28:29.38ID:E5YlFTVp
>>610
> foo(), bar(), baz()各々はResultでエラー値も同時に返しているが、エラーチェックはまとめて出来る。
できないよ。
失敗した段階で処理を中止する必要がある。
2022/01/13(木) 16:36:22.32ID:E5YlFTVp
あ、ひょっとして「?;」ってエラーが発生したらそこでsub()を抜けるってこと?
まあ、だとしても、C++でもエラーチェックベースで実装しろということにはならないけどね
2022/01/13(木) 16:42:23.86ID:E5YlFTVp
大抵の言語では、例外が発生したらスタックトレースが取れたり、例外オブジェクトそのものにエラー発生場所・エラーコード・エラーメッセージなんかが入ってたりするから、使わない手はないと思うよ
615デフォルトの名無しさん
垢版 |
2022/01/13(木) 16:57:19.52ID:2BXAobev
>>611
その場合でも、Rustならば戻り値をResultにしてこのように見やすくプログラミングしやすい。

fn process() -> Result<(), Error> {
 foo()?;
 bar()?;
 baz()
}

fn hoge() -> Result<(), Error> {
 begin()?;
 match process() {
  Ok(()) => {
   commit()?;
   Ok(())
  },
  Err(err) => {
   rollback();
   Err(err)
  },
 }
}

>>613
その通り
?オペレータは、ResultがErr(err)の時にreturn Err(err);する。
正確には便利に変換してくれるreturn Err(From::from(err));だが本筋でないので略。
2022/01/13(木) 17:01:12.46ID:E5YlFTVp
>>615
> ?オペレータは、ResultがErr(err)の時にreturn Err(err);する。

なるほど、勉強になった
ただ、前述したとおり、書き捨てのプログラムでない限りエラーが発生したときには詳細なエラーログを出力する必要もあるし、Rustの常識が多言語でもベストプラクティスとはならないと思うよ
2022/01/13(木) 17:09:11.61ID:k/BdCeDW
>>611
googleに聞いてくれ
https://ttsuki.github.io/styleguide/cppguide.ja.html#Exceptions
618デフォルトの名無しさん
垢版 |
2022/01/13(木) 17:24:20.34ID:2BXAobev
>>614
スタックトレースまで必要になるならば、それはエラーではなくプログラムのバグだろう。
その区別を付けたほうが好ましい。
そして、エラーではなくバグならば前述したようにpanicの対象なのでpanicさせることもできる。

>>616
Resultの正常値もエラー値も任意の情報を持たせられるので必要な時に必要な処理をすれば困ることはない。

>>617
そのGoogleのC++スタイルガイドに「C++の例外は使いません。」と明記されているのか。
これはGoogleが正しい。
もちろん、Googleが作ったGo言語に例外はない。
プログラミングにおいてtry catchの例外機構は不要である。
2022/01/13(木) 17:55:38.36ID:QuitFgmw
try/catchよりもRustの方法が良い点としては
let val = foo()?; とした時に
正常値valの時だけに専念できるだけでなく
foo()はエラーを返すこともあってその処理は上位に委譲していますよ!と
?オペレーターの存在で明瞭になる点

これは裏返せばtry/catch例外方式の致命的な欠点
どこで誰が例外を返すのかわからなかったり
多段呼び出しの途中の関数では例外が通過するのかどうか全てを追わないとわからなかったり
プログラミングにおいて例外は悪だと思う
グーグルはちゃんとわかっている
2022/01/13(木) 18:12:05.30ID:E5YlFTVp
>>618
> スタックトレースまで必要になるならば、それはエラーではなくプログラムのバグだろう。

エラーが発生した場所がどこであるのかが例外オブジェクトに含まれているなら、スタックトレースが不要な場合もあるかもしれませんが、あればどういう呼び出しのときにエラーが発生したのかわかるので便利です

> その区別を付けたほうが好ましい。

大抵の場合は例外の種別や例外オブジェクトの継承ツリーで区別をつけてると思います
LogicExeptionを継承する例外ととRuntimeExceptionを継承する例外とか

> >>617
> そのGoogleのC++スタイルガイドに「C++の例外は使いません。」と明記されているのか。
> これはGoogleが正しい。

Googleがそうやっているだけで、それがベストプラクティスとは限りません
>>611 のコードにエラーログ出力を追加しようとしたらひと苦労です
2022/01/13(木) 18:20:01.16ID:YmYunxX5
Googleのスタイルガイドでは、C++の例外は雑に扱えないぐらいには面倒だしメリットがそこまで大きくもない、って書いてるぐらいで、例外は不要だとは断じてないよね

面倒だからGoogleの巨大なレガシーコードには今更例外を導入できないし、それが依存する可能性のあるプロジェクトにも例外は使わせたくない、って感じでしょ
622デフォルトの名無しさん
垢版 |
2022/01/13(木) 18:27:00.76ID:2BXAobev
>>620 >>621
だからこそGoogleもMicrosoftもAmazonもFacebookも一緒になって共同でRust Foundationを設立。
それぞれ新規のものや既存のものの改善などを機会に、Rustへの移行を着実に進めている。
既存の枯れたものまで一気に置き換えるという無駄なことはしないが、今後もC++が使われ続けるのはそれだけになる。
2022/01/13(木) 18:31:49.09ID:E5YlFTVp
>>622
話がずれていってるけど、大本の話題はこれだからね

> プログラミングにおいて、エラー処理のためのtry catch例外処理は本来不要なものである。
> エラーは関数の戻り値で返せばよい。

あと、軽く調べたが、googleはSTLもboostも基本使えないみたいよ
もちろん、例外をthrowするサードパーティ製ライブラリも使えない
修行僧みたいw
2022/01/13(木) 18:33:20.28ID:E5YlFTVp
あと、Microsoftは違うスタンスみたいだよ

https://docs.microsoft.com/ja-jp/cpp/cpp/errors-and-exception-handling-modern-cpp?view=msvc-170

> 最新の C++ のほとんどのシナリオでは、論理エラーとランタイム エラーの両方を報告および処理する方法として、例外を使用することが推奨されます。 特に、エラーを検出する関数と、エラーを処理するコンテキストを持つ関数の間に複数の関数呼び出しがスタックに含まれている可能性がある場合に当てはまるとします。 例外は、エラーを検出して情報を呼び出し履歴に渡すコードに関する、正しく定義された正式な方法を提供します。
625デフォルトの名無しさん
垢版 |
2022/01/13(木) 18:52:55.65ID:2BXAobev
>>624
なるほど
プログラムのバグとエラー(=入出力や相手次第で発生)の両方を、ごっちゃに同じ例外で扱ってる自覚はあるわけだ。
>>615のRustのように書ければ例外を使わずともエラーを綺麗に明瞭に処理できるのだが、
C++では言語の機能不足のため、修行僧モードになるか例外を使うかの二択なのだろう。
いずれにせよMicrosoftもRustに積極的だから、時間をかけて脱C++へ進んでいることに変わりはない。
2022/01/13(木) 19:13:49.01ID:E5YlFTVp
>>625
> プログラムのバグとエラー(=入出力や相手次第で発生)の両方を、ごっちゃに同じ例外で扱ってる自覚はあるわけだ。

そもそも、アプリケーションプログラマバグによる例外のthrowはほぼ書かないと思いますけどね
バグ由来の「異常発生」には、ほぼ誰も気にしてないと思うよ(もちろん、最終的な処理が必要なら書くけど)

> いずれにせよMicrosoftもRustに積極的だから、時間をかけて脱C++へ進んでいることに変わりはない。

多分、30年は無理じゃないかな(個人の感想です)
Java, C++がでてきてからもう30年くらい?かな
COBOLやFORTRANの生き残り具合を鑑みるとそう思えます

https://www.tiobe.com/tiobe-index/
Fortran 19位
COBOL 25位
Rust 26位 ← 思ったより検討してた
2022/01/13(木) 19:25:42.66ID:DCVQhT4S
Rustの利点はわかったけど、?演算子とpanicは例外の発展形にしか見えないなぁ。
(?演算子でエラー移譲を受けた)呼び出し元は、エラーを無視してもpanicしなくて済むのかしらん?
エラーを処理しなきゃいけないんだったら例外と大して変わらん気がする。
628デフォルトの名無しさん
垢版 |
2022/01/13(木) 19:47:20.65ID:sBBuaSsw
例外は危険。
使うべからず。
629デフォルトの名無しさん
垢版 |
2022/01/13(木) 19:47:53.64ID:2BXAobev
>>626
単なる通信エラーにすぎなくてもtry catchの例外で受ける例はあるよね。
>>606のデータベースアクセスの例だと、DBサーバーとの通信時エラーが起きるとfoo()は例外を投げることになる。
しかも例外を投げるのはfoo()自身ではなく、そこから呼ぶDBサーバ通信部分だったり、そこから呼ぶ汎用通信ライブラリだったり、誰が例外を投げるかわからない。

>>627
今書いている関数で例外が発生するのかどうか、奥底まで追わないとはっきりしないデメリットが例外にはある。
?演算子を使えば、下からエラーが来ていて上へエラー処理を移譲していることが明確になる。
あと、質問に対する答えは、main()関数までもがさぼってResultを返せば、自分でエラー処理をせずともエラー表示される。
2022/01/13(木) 20:16:47.27ID:Pln9PLvq
>>629
実際にはこないのに来るかもしれないと思わせるだけかもしれないだろ
それならtry catchだって来ると思っとけばよい
2022/01/13(木) 21:01:12.03ID:QuitFgmw
>>627
エラー処理はそんな大変なことではなく例えば
if let Ok(value) = foo() {
 bar(value);
}
と正常値の時だけ処理したりも出来る
正常値を得るにはif letやmatchやその他にResult型のメソッドなどを必ず使わないと正常値を取り出せないので
Rustではエラー値なのにチェック忘れで突き進むバグが生じないのも利点
2022/01/13(木) 21:59:08.34ID:W/MOMDn7
Rust全くわかってないんだけどOkはマクロ?
2022/01/13(木) 22:10:33.52ID:7TJ/z3m3
>>632
EnumであるResult型がとりうる値の種類
パターンマッチさせてResultの中身がOkの場合だけ条件が真になる
2022/01/13(木) 22:14:53.71ID:7TJ/z3m3
>>627
メリットでもデメリットでもあるが例外との一番の違いは
関数の型でどういうエラーが発生するのかしないのか分かるという点
2022/01/13(木) 22:26:16.24ID:+PFReeTS
>>570
>大半のアプリケーションでは個別にハンドリングせず
>集約エラーハンドラに任せたいとエラーのほうが圧倒的多数だから

どこでなぜ起きたかわからないエラーをキャッチしてもなぁ。
erlangのlet it crashのようにエラーの種類は考慮しないってんならわからんでもないけど。
636デフォルトの名無しさん
垢版 |
2022/01/13(木) 22:36:17.73ID:2BXAobev
>>632
Okはenumの識別子。
Result型はenumでありOk(正常値)とErr(エラー値)のどちらかになる。
enumといってもRustは識別子に付随する値を持つこともできる。
つまりC/C++には無い新たな枠組みで、これがRustを強力にしている一つ。

>>630
try catchは関数呼び出しが多段になった時に、
途中の関数ではtry catchもthrowも出てこないから情報がなく気付けない。
Rustは途中の関数で?オペレータを必ず付けるから、
エラーが起きる可能性があることを必ず認識できる。

>>631
Resultに対して多数のメソッドがあって短くエラー処理できる点もいいね。
例えば以下の2つは同じで、エラー時にDEFAULT_VALUEとなる。
let a = foo().unwrap_or(DEFAULT_VALUE);
let a = if let Ok(value) = foo() { value } else { DEFAULT_VALUE };

以下の2つも同じで、エラー時にクロージャ |err| bar(err) の値となる。
let b = foo().unwrap_or_else(|err| bar(err));
let b = match foo() {
 Ok(value) => value,
 Err(err) => |err| bar(err),
};
637デフォルトの名無しさん
垢版 |
2022/01/13(木) 22:40:25.51ID:t/cn/0uo
>>588
bad_allocは絶対発生しないシステムなの?
2022/01/13(木) 22:56:39.62ID:FqgOTQou
>>635
集約エラーハンドラは汎用のエラー画面表示やログ出力のためだぞ
例外の中身を見ればどこでなぜ起きたかはわかるがユーザーには対処できないものを扱う
Erlangは軽量プロセス単位のリトライなので全然違う
2022/01/13(木) 23:29:52.77ID:+PFReeTS
>集約エラーハンドラは汎用のエラー画面表示やログ出力のためだぞ

例外マンセー軍全員こう思ってる?
参ったw
2022/01/14(金) 00:04:27.93ID:InXswW/0
>>631
戻り値無し(副作用目的)で失敗する可能性のある関数もチェック忘れ防げるようになってたっけ?
2022/01/14(金) 00:14:04.94ID:0aNzNV+4
例外が嫌いすぎて例外使ったことないエアプだから、頓珍漢なことしか言えない
議論する価値ないわ
2022/01/14(金) 00:14:49.01ID:Gws88Xz4
>>640
正常系の戻り値がない関数なら戻り値はResult<(),Error>になって、これを無視するとwarningが出るから気付く
2022/01/14(金) 00:19:25.76ID:fGcmjtxY
>>640
まず関数の戻り型はResult<(), Error>となる
()はRustで戻り値なしを意味しタプル0個と覚えれる
次にその関数を普通にfoo();と呼び出すコードを書く
すると「使われていないResult値がある」とコンパイラに警告される
したがってエラー値チェックを忘れていることに気付ける
2022/01/14(金) 00:20:04.51ID:InXswW/0
>>642
おー、ほんとだ。いいね。
https://doc.rust-lang.org/src/core/result.rs.html#71-75
> //! A common problem with using return values to indicate errors is
> //! that it is easy to ignore the return value, thus failing to handle
> //! the error. [`Result`] is annotated with the `#[must_use]` attribute,
> //! which will cause the compiler to issue a warning when a Result
> //! value is ignored. ...
2022/01/14(金) 13:50:52.20ID:CyyU39UP
>>629
> 今書いている関数で例外が発生するのかどうか、奥底まで追わないとはっきりしないデメリットが例外にはある。

今書いている関数では、ハンドリングする例外に着目するだけでいいんだが
(何を言ってるのかわからんかもしれんが)
2022/01/14(金) 13:52:22.52ID:CyyU39UP
>>639
> 参ったw

何が参ったなのかわからんが、例外オブジェクトがエラーの情報を持っているから汎用処理にできるんだが
2022/01/14(金) 13:55:14.01ID:CyyU39UP
Googleのコーディング規約が神だと思ってるみたいだが、発表された当時内容があまりにアレだったので界隈がざわついた記憶がある
組み込み関連は知らんが、それ以外でGoogleのコーディング規約を取り入れてるところはないんじゃないか
2022/01/14(金) 14:37:16.30ID:B7zHdTDq
参考にしてるのは業務でまともにC++を使ったことがない素人ばかりかもね
2022/01/14(金) 14:45:16.44ID:Ml4XYYXN
>>629
> 今書いている関数で例外が発生するのかどうか、奥底まで追わないとはっきりしないデメリットが例外にはある。
逆にRustだとなんかの理由で奥底の関数がエラーを返すように変更されたらその上の関数全てを変更するってこと?
2022/01/14(金) 15:08:09.78ID:CyyU39UP
Rust始めたばかりだからまだよくわかってないが、エラー処理周りのこと調べると、まだまだ迷走中な感じだな
少なくとも初手から言語仕様として完璧なエラー処理構造が入ってたわけではないことがわかった

Rust のエラーまわりの変遷
https://qiita.com/legokichi/items/d4819f7d464c0d2ce2b8
2022/01/14(金) 15:14:13.63ID:fGcmjtxY
>>649
まず一般的にどの言語であっても奥底の関数の仕様が変更されたらそれを吸収できるところは変更となる
次にエラーが起きない関数が突然にエラーが起きるようにはならないのでそんな仕様変更は起きない
入出力相手があるものは初めからエラーが起きうることがわかるしメモリ上の操作だけであってもsearchやmatchなど成否が起きうるものも最初からわかっている
2022/01/14(金) 15:21:48.16ID:/o+2ilkb
「そんな仕様変更は起きない」ということはなく、普通にAPIの設計ミスっててやっぱりエラーになる可能性あった、というのはありうる
その場合Rustならコンパイルエラーで気付くが、例外だとこれまで例外出さなかった関数が急に出すようになるわけで、なかなか厳しいね
2022/01/14(金) 15:24:49.44ID:Ml4XYYXN
>>651
> まず一般的にどの言語であっても奥底の関数の仕様が変更されたらそれを吸収できるところは変更となる
例外なら途中の関数の変更は不要だよ

> 次にエラーが起きない関数が突然にエラーが起きるようにはならないのでそんな仕様変更は起きない
お前さんの妄想は要らんよ

> 入出力相手があるものは初めからエラーが起きうることがわかるしメモリ上の操作だけであってもsearchやmatchなど成否が起きうるものも最初からわかっている
計算だけしかしない関数が外部に計算させるように変更されたらどうするの?
2022/01/14(金) 15:28:08.59ID:Ml4XYYXN
>>652
> 例外だとこれまで例外出さなかった関数が急に出すようになるわけで、なかなか厳しいね
例外出すように変更したら当然それを受けるように変更するでしょ?
例外なら発生と受けるところの変更だけで済むけど、Rustだと間の関数も全て変更が必要じゃね?
2022/01/14(金) 15:34:01.30ID:B7zHdTDq
try-catchは素人にはうまく使えないよなあ、とは思う
2022/01/14(金) 15:36:58.27ID:bXd4RL2X
てかエラー処理全般、本気でやるとしたら世の中でできるやつはかなり限られてる。
GAFAとか含めてもそう。
2022/01/14(金) 15:37:15.18ID:/o+2ilkb
>>654
自分で変更したとしても、それを使っている箇所を漏れなく変更できるか?という問題もあるし
ましてや依存ライブラリの仕様変更だったらどうするの?という話
誰もがCHANGELOGを正しく書いてくれるわけではないし、見落としだってある
2022/01/14(金) 15:44:57.54ID:fGcmjtxY
>>654
途中で低位層の仕様が変わるとか有り得ない机上の空論に対して
どこまで何を前提にしていいのか何もかも不明だから誰も何も答えられない
2022/01/14(金) 15:51:24.55ID:Ml4XYYXN
>>657
ああRustだと全部変更必要だけどサボるとコンパイルエラーになるってことか、了解
コールツリー作れれば例外でもチェックできそうな気もする

>>658
>>652 とか俺も例まで書いてあるのに理解できないアリエナイ君は出てこない方が良いかとw

> 計算だけしかしない関数が外部に計算させるように変更されたらどうするの?
2022/01/14(金) 16:03:30.57ID:/o+2ilkb
>>659
まぁ変更が面倒というのは全くその通り
個人的にはコーナーケースのデバッグコストを事前に払ってるだけだから面倒よりありがたいって思ってるけど、嫌いな人はいるだろうね
2022/01/14(金) 16:16:10.98ID:Ml4XYYXN
面倒というより本質的に途中の関数には関係ないはずなのに修正が必要になると言うのがちょっと嫌かな
まあ現状ではmore betterなんだろうけどなんとか洗練されないものかと
2022/01/14(金) 16:27:26.86ID:WRwvxAen
>>659
外部サーバーに計算させるよう変更するには
まずその外部のIPアドレスかホスト名かそれらを含むURIなどが新たなパラメタとして引数に入る
途中の関数があるとすれば全て影響を受けるだろう

さらにそのようなことが必要な規模の計算の場合
外部サーバーを使わずとも自分のところでも並列計算をしていたはずである
また計算以外も含めて今どきはマルチスレッド利用が前提とすると
スレッド間の例外は不可もしくは例外を使わず受け渡しをして投げ直すことになる
結局これは例外を使わない場合と同じことをせざるをえなくなる
2022/01/14(金) 16:39:58.04ID:Ml4XYYXN
>>662
> まずその外部のIPアドレスかホスト名かそれらを含むURIなどが新たなパラメタとして引数に入る
クラスとか使ったことないのかな?

> 外部サーバーを使わずとも自分のところでも並列計算をしていたはずである
はずはず君w
もう少し考えてからレスしないと恥の上塗りにしかなってないよ
664デフォルトの名無しさん
垢版 |
2022/01/14(金) 16:45:29.34ID:eFXg0S3t
>>662
計算じゃなく、データベースにクエリー投げるとか普通にあるだろ。 そういう場合、
いちいち関数の引数にIPアドレスやホスト名を渡すのではなく、オブジェクトメンバ
として持たせて、計算メソッドを呼ぶって実装にするのでは?

んで、サーバー応答がない場合だけでなく、IPアドレスやホスト名をセットせずに、
計算メソッドを呼んだりしたら、例外を投げるよな?
2022/01/14(金) 16:46:26.60ID:CyyU39UP
>>658
> 途中で低位層の仕様が変わるとか有り得ない机上の空論に対して
> どこまで何を前提にしていいのか何もかも不明だから誰も何も答えられない

やっぱり例外のことわかってないね
自作関数hoge()がサードパーティ製ライブラリの関数foo()を呼び出しているとき、hoge()ではfoo()が送出する例外をどうするかを実装するだけでいい
その後、foo()が更新されfoo()が依存するライブラリが例えばIoErrorをthrowするようになってfoo()はそれに対して何もしないとしても、hoge()は変更する必要がないし知る必要もない
2022/01/14(金) 16:48:22.67ID:fGcmjtxY
並行並列処理した時点で例外が破綻するのは事実だな
擬似的に例外を伝播させるにしても途中でエラー値渡しが必要
例外を使えば途中は何も考えなくていいはウソだな
2022/01/14(金) 16:55:06.25ID:CyyU39UP
そもそも、例えばJavaScriptでnpmパッケージを少しつかうと、数百個のnpmパッケージがインストールされて数千個のthrowが実装されてて、全貌を知るなんて無理んだんだよ
そんなこと知らなくても、JavaScriptでアプリコードは書ける
2022/01/14(金) 16:56:04.83ID:Ml4XYYXN
>>666
スレッド内では関数を多段に呼び出すことはないという主張なのかな?
2022/01/14(金) 16:57:10.80ID:CyyU39UP
やっぱこいつ例外のことなんもわかってねーわ
2022/01/14(金) 16:59:50.72ID:WRwvxAen
>>663 >>664
計算を与えるものと
サーバー情報を与えるものは
明らかに独立して扱うべきもの
内部で計算するなら前者だけで済む
なるべく依存関係を少なくモノリシックにならないように設計するのが常識

>>664
ホスト名がないとかサーバーが応答しないとか
そんな普通に起こりうることはエラーを返す
2022/01/14(金) 17:02:36.16ID:8BRe3wDd
>>665
知らなくていいメリットか知りようがないデメリットか
2022/01/14(金) 17:02:40.51ID:fGcmjtxY
>>668
並列計算スレッドの中で多段に呼ぶのはいいが何をしたいんだ?
ちゃんと頭の中が整理できていないだろw
コードを書いたことあるのかね?
2022/01/14(金) 17:03:04.21ID:CyyU39UP
例外がわかってないっつーか
プログラミングど素人だったわw
2022/01/14(金) 17:10:08.74ID:aHL9Oj90
>>654
そうだよ
Tで返してたところをOption<T>で返すように変更が入るとかは普通にある

型で表現できることのメリットの裏返しで
型で表現してるからこそそれに依存してるところは全部変更が必要
誰か書いてたけど検査例外と同じデメリットがある
2022/01/14(金) 17:13:19.40ID:aHL9Oj90
>>665
これはRustでも同じ
hoge()ではfoo()が返すResult<T, E>のErrorだけ気にすればいいように作る
(正確にはfooを含むmod Fooが定義するErrorのうちfooが返すものだけ気にする)
2022/01/14(金) 17:13:47.97ID:WRwvxAen
>>665
JavaScriptについてちゃんとわかっていないようだな
それらは大量にあっても自分のところに飛んで来ないthrowだ
自分のところに飛んでくるthrowはcatchしないとuncaughtExceptionで怒られる
だから下から例外が来るか否かは把握していないといけない
そもそも途中でライブラリの仕様が変わって例外を投げるようになること自体がナンセンスだが
2022/01/14(金) 17:26:27.30ID:fGcmjtxY
>>667
まずは例外の基本を理解しなさい
ライブラリ群のソースの中に何千個のthrowがあろうが各々のtry-catchで閉じ込められておりその外に対しては一切無関係
関係があるのは自分に向かって来る分のみ
2022/01/14(金) 17:43:36.82ID:UhvSPNNm
>>670
> 明らかに独立して扱うべきもの
機能が一緒なのに?
君のべき論ならそうなのかも知れないけど、それが一般的というわけではないよね
2022/01/14(金) 17:45:12.30ID:UhvSPNNm
>>672
整理できてないのは お・ま・え w
2022/01/14(金) 17:48:13.03ID:UhvSPNNm
>>674
そこは了解
まあ単純に上位に渡すだけならIDEで自動で修正とかできそう
2022/01/14(金) 18:00:55.12ID:fGcmjtxY
>>679
じゃあ並列計算スレッドの中で多段に呼ぶ関数があるとして
どういう仕様変更をせざるをえなくなるのか具体的に答えてみよ
無いと思うけどな
2022/01/14(金) 19:16:22.53ID:kUhlpB/h
そもそもrustで言うと Result<T, E> の E を変更するのは破壊的変更だから普通は依存crateのエラー型をそのまま外部に見せるようなことはしない
2022/01/14(金) 19:42:59.80ID:7uXlwHnS
>>681
スレッド内ではシングルスレッドと同じだろ
スレ読み直してこい
2022/01/14(金) 19:49:44.98ID:fGcmjtxY
>>683
で、並列計算スレッドの中で多段に呼ぶ関数があるとして
具体的にどういう仕様変更をせざるをえなくなるのか早く答えて欲しい
無いと思うけどな
2022/01/14(金) 20:30:51.27ID:TehXI+gA
コードの修正が必要になるって話な

> 逆にRustだとなんかの理由で奥底の関数がエラーを返すように変更されたらその上の関数全てを変更するってこと?
2022/01/14(金) 20:46:13.89ID:WRwvxAen
>>685
エラーに限らず一般的によくあることだね
返すべき値が増えたり
返すべき型が変わったり
あるいは逆に
引き渡す値が増えたり
引き渡す型が変わったり
それらは機能追加変更でも起きるけど
リファクタリングでも起きたりしてる
Rustでも他の言語でもその状況は変わらない
2022/01/14(金) 21:26:13.10ID:9EKaNxsm
話の流れ見えてる?

> 例外なら発生と受けるところの変更だけで済むけど、Rustだと間の関数も全て変更が必要じゃね?

> 面倒というより本質的に途中の関数には関係ないはずなのに修正が必要になると言うのがちょっと嫌かな
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況