[表示 : 全て 最新50 1-99 101- 201- 301- 401- 501- 601- 701- 801- 901- 1001- 2ch.scのread.cgiへ]
Update time : 02/27 05:30 / Filesize : 305 KB / Number-of Response : 1022
[このスレッドの書き込みを削除する]
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧] [類似スレッド一覧]


↑キャッシュ検索、類似スレ動作を修正しました、ご迷惑をお掛けしました

Rust part24



1 名前:デフォルトの名無しさん mailto:sage [2024/05/27(月) 06:41:26.82 ID:T4AFD1f4.net]
公式
https://www.rust-lang.org/
https://blog.rust-lang.org/
https://github.com/rust-lang/rust

公式ドキュメント
https://www.rust-lang.org/learn

Web上の実行環境
https://play.rust-lang.org

※Rustを学びたい人はまず最初に公式のThe Bookを読むこと
https://doc.rust-lang.org/book/

※Rustを学ぶ際に犯しがちな12の過ち
https://dystroy.org/blog/how-not-to-learn-rust

※Rustのasyncについて知りたければ「async-book」は必読
https://rust-lang.github.io/async-book/

※次スレは原則>>980が立てること

前スレ
Rust part23
https://mevius.5ch.net/test/read.cgi/tech/1708677472/

577 名前:デフォルトの名無しさん [2024/07/02(火) 17:51:34.66 ID:XMmeU2jA.net]
Slint ってなんなん? javascript ?
conrod とどう違うん?

578 名前:デフォルトの名無しさん [2024/07/02(火) 18:31:45.59 ID:W5A1QJhP.net]
conrodならもう死んだよ

579 名前:デフォルトの名無しさん mailto:sage [2024/07/02(火) 18:32:06.29 ID:0AnHLV8o.net]
>>559
Rustでそれらは全てmatchになるので置き換えて比較すれば理解は簡単
ちなみにmatchにすると記述が長くなるが同レベルで「?」オペレータ適用できるメリットがある

result.and_then(|val| f(val))
これはこう置き換えられる
match result {
 Ok(val) => f(val),
 Err(err) => Err(err),
}

result.map(|val| f(val))
これはこう置き換えられる
match result {
 Ok(val) => Ok(f(val)),
 Err(err) => Err(err),
}

つまり常にこれが成り立つ

>>534
> 以下の二つは同等
> result.map(|val| f(val))
> result.and_then(|val| Ok(f(val)))

580 名前:デフォルトの名無しさん mailto:sage [2024/07/02(火) 18:34:46.10 ID:0AnHLV8o.net]
>>565
SlintはGUI部分だけ専用スクリプトで宣言して
プログラムはRustでもC++でもJavaScriptでも記述できる

581 名前:デフォルトの名無しさん mailto:sage [2024/07/02(火) 22:09:25.08 ID:PHqzDXJL.net]
RustのGUIまわりは安定しない印象
conrodやdruidやorbtkのようにここ数年内に消えたものもあるし、いま人気のものも今後消えないとは言い切れない感じがする

582 名前:デフォルトの名無しさん mailto:sage [2024/07/02(火) 23:44:50.93 ID:sYgKhdog.net]
RustでGUIならこの5つ
https://iced.rs/
https://slint.dev/
https://tauri.app/
https://www.egui.rs/
https://dioxuslabs.com/
方向性がそれぞれ異なるので目的に合わせて選ぶ

583 名前:デフォルトの名無しさん [2024/07/03(水) 03:55:17.90 ID:aYT0CHki.net]
tauri遅いな
eguiはサクサク

584 名前:デフォルトの名無しさん mailto:sage [2024/07/03(水) 06:25:46.46 ID:uJMJjlOC.net]
>>570
tauriはその中に入れるべきじゃないだろ
あれはReact/JSだぞ

585 名前:デフォルトの名無しさん mailto:sage [2024/07/03(水) 07:06:30.59 ID:OX+N1U2y.net]
>>572
無知すぎ
Reactは全く関係ない
併用可能な一つに過ぎない

TauriではJavaScriptを一切書かなくても利用可能
Rustによるプログラミングのみでも使うことができる



586 名前:デフォルトの名無しさん [2024/07/03(水) 09:04:55.71 ID:TWMTGehv.net]
rstkはどうなの?

587 名前:デフォルトの名無しさん mailto:sage [2024/07/03(水) 20:03:02.84 ID:zo80GwO2.net]
しかしほんとにデスクトップアプリのライブラリってすぐ出ては消えていくな
自分で作ったほうが安定するんじゃないか

588 名前:デフォルトの名無しさん mailto:sage [2024/07/03(水) 22:16:18.13 ID:opT6Sw/L.net]
クロスプラットフォームでいくならwinitとwgpuぐらいは頼らないと無理じゃないかな。
しかしその2つもまだまだブレイキングチェンジ激しい発展途上だけどね。

589 名前:デフォルトの名無しさん mailto:sage [2024/07/03(水) 22:53:26.72 ID:cnEeYmV/.net]
>>574
*/Tkは30年以上の歴史と実績があるGUIライブラリ
rstkはそのRust版

590 名前:デフォルトの名無しさん mailto:sage [2024/07/03(水) 23:54:41.68 ID:nLMSU1jW.net]
>>573
Yewのこと?ならそう書けよYewなんてくっそマイナーでReact使うのが普通なのに

591 名前:デフォルトの名無しさん mailto:sage [2024/07/03(水) 23:56:15.32 ID:nLMSU1jW.net]
Yew使ったことあるけどゴミだぞまじで

592 名前:デフォルトの名無しさん mailto:sage [2024/07/04(木) 00:31:14.93 ID:gMzXB5nS.net]
30年くらい前にTcl/Tkを使ったわ。

593 名前:デフォルトの名無しさん mailto:sage [2024/07/04(木) 00:37:01.85 ID:0fbU9cKr.net]
>>575
利用者が集まらなきゃ結局のところ本番環境で使われないもんね
MAUIもだけど本番環境で使われなきゃ不具合修正すらされずにフェードアウトしていく

594 名前:デフォルトの名無しさん mailto:sage [2024/07/04(木) 04:07:16.49 ID:H+976rVP.net]
>>570
eguiの公式サイト、オサレね

595 名前:デフォルトの名無しさん mailto:sage [2024/07/04(木) 07:04:39.24 ID:pjeQ5Ua2.net]
サイト自体が見本なのな



596 名前:デフォルトの名無しさん [2024/07/04(木) 10:17:42.23 ID:HAZY/W56.net]
reactもこの10年でだいぶ変わったわな。
プレゼンテーション層はそういうもんかもなと思ってる。

597 名前:デフォルトの名無しさん [2024/07/05(金) 08:36:28.68 ID:GQkuHNKI.net]
銀河英雄伝説で考えるセキュリティ--将来の「帝国の双璧」が陥った罠とセキュリティ業界
https://japan.zdnet.com/article/35220819/

598 名前:デフォルトの名無しさん mailto:sage [2024/07/05(金) 10:29:56.20 ID:G0wJmtVU.net]
>>574 >>577
rstk より tk ( https://crates.io/crates/tk ) の方が良いよ

599 名前:デフォルトの名無しさん mailto:sage [2024/07/05(金) 18:22:04.62 ID:cNWaNn+n.net]
どちらも利用者少なくて数の差ではわからんな

600 名前:デフォルトの名無しさん mailto:sage [2024/07/06(土) 04:04:15.80 ID:MPM8/XaB.net]
Tkは何十年も前のGUIで古いからね

601 名前:デフォルトの名無しさん [2024/07/06(土) 04:24:49.23 ID:mF2Bv0pD.net]
やりたいことを出来る範囲で最小限の道具を選ぶのが望ましい。
Tk で足りるときは Tk を使えばよい。

602 名前:デフォルトの名無しさん mailto:sage [2024/07/06(土) 09:36:32.81 ID:5g1fLWJR.net]
UNIX系でGUIをどうしても使わないといけない場合にTk使ってたけど
今はhtmlでいいかなって

603 名前:デフォルトの名無しさん mailto:sage [2024/07/06(土) 09:36:55.52 ID:tDR9EaCv.net]
wgpu最強だが変化速過ぎ

604 名前:デフォルトの名無しさん mailto:sage [2024/07/06(土) 10:12:50.18 ID:fehAbjyn.net]
正直GUIをRustで書くメリットが思いつかない
ただの2DグラフィックでRustの実行速度を求めるってのはおかしな話だと思うもん
ロジックをRustで書いてGUIは安定してるReactでいいよ

605 名前:デフォルトの名無しさん mailto:sage [2024/07/06(土) 10:14:23.55 ID:5g1fLWJR.net]
wgpuは三角を書きたい人向けでGUIとは関係ない



606 名前:デフォルトの名無しさん mailto:sage [2024/07/06(土) 11:05:29.63 ID:l5YBQ3zH.net]
>>592
お前がそう思うならそうなんだろう
お前ん中ではな

607 名前:デフォルトの名無しさん mailto:sage [2024/07/06(土) 12:27:12.12 ID:KR8eM4HE.net]
>>592
reactはデータリフトアップして上にまとめるのめんどい。状態管理だけにライブラリ導入とか無理あるんじゃねーの

608 名前:デフォルトの名無しさん mailto:sage [2024/07/06(土) 12:35:51.52 ID:5g1fLWJR.net]
streamlitなどのHTML書かないでも作れるようなのがメジャーになればいいんだけど

609 名前:デフォルトの名無しさん mailto:sage [2024/07/06(土) 12:47:45.00 ID:5g1fLWJR.net]
reactがパックされてて高度なページはjinjaみたいので中のデータだけいじれればなんでもいい気がする

通常のページの記述はhtmlではなく素のrustで簡単に書ける必要がある

610 名前:デフォルトの名無しさん mailto:sage [2024/07/06(土) 13:00:47.32 ID:mF2Bv0pD.net]
ウェブ技術系は普段使いするにはリッチすぎるんだよな。
屋上屋を重ねまくった一番上でしょうもないことをするのは気が引ける。

611 名前:デフォルトの名無しさん mailto:sage [2024/07/06(土) 13:56:26.87 ID:5g1fLWJR.net]
streamlitレベルでいいんだけどな

612 名前:デフォルトの名無しさん [2024/07/06(土) 14:33:03.19 ID:+47S9kNa.net]
rust版のstreamlit作れよ

613 名前:デフォルトの名無しさん [2024/07/06(土) 14:56:55.97 ID:X3tW4qHs.net]
タウリンなんていらん
eguiで充分

614 名前:デフォルトの名無しさん [2024/07/06(土) 22:06:51.02 ID:PIuhFLFS.net]
Rustってオブジェクト指向言語ではないということですが、それでも困ることはないんです

615 名前:か?

これが最後の言語だ!とRustって名付けたんですか?
[]
[ここ壊れてます]



616 名前:デフォルトの名無しさん [2024/07/06(土) 22:35:00.58 ID:KApGuCzH.net]
Rust触ってないから分らんけど、QtのRustラッパーライブラリは無いのん?
一応Android/iOS含めたソースコードレベルでのマルチプラットフォームライブラリに進化しているらしいが、Haskellにすらラッパーライブラリあるんなら、Rustにも探せばあるんじゃ?

617 名前:デフォルトの名無しさん [2024/07/07(日) 00:52:56.61 ID:goRFIXq7.net]
>>602
ネタにマジレスかもしれないけどRustはオブジェクト指向的なものも使えるよ
構造体にメソッドを持たせたり、インターフェースのようなものも扱える
継承はないけど、これはむしろ「その方が良い」というもので、同じくモダンな言語であるGOでも継承は無くしてる

618 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 01:50:01.52 ID:NnH56+1c.net]
オブジェクト指向プログラミングには
クラス継承という悪いやり方を用いるダメな方法と
クラス継承を用いない正しい方法があって
RustやGoなどのモダンな言語は後者の方法をサポートしている

619 名前:デフォルトの名無しさん [2024/07/07(日) 08:48:31.04 ID:5sr/rOi5.net]
>>603
ないわけじゃないけどまともに使えるレベルではないらしい。使ってないから知らんけど。
Qt自体QMLとか迷走してる感じあるし結局JSでやるならもうReact使えばいいんじゃね?感ある

620 名前:デフォルトの名無しさん [2024/07/07(日) 09:17:14.13 ID:7aG8TPof.net]
>>604-605
ありがとうございました。
「継承」って良いからオブジェクト指向言語の機能になっていたのではないんですか?
なんか時代とともに、昔は良いとされていたものが今ではダメになったりするんですか?
なぜそんなに揺らぐのでしょうか?
言語の設計の学者はぼんくらばかりなんですか?

621 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 09:17:45.74 ID:LJE8DJUz.net]
継承がないほうが「正しい」というのは行きすぎた思想だよ。
正しく使えないカスばっかりだという現実に敗北しただけ。

622 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 09:49:42.70 ID:Qx35uTG5.net]
何がダメかというと「ある型(クラス)が別の型(クラス)の実装を継承してしまうこと」でこれが依存関係となり負の連鎖をもたらす
クラスの継承はこれに該当するから使ってはいけない
Rustにも継承とみなせる機能はあるけれど上記に該当しないため大丈夫
そこが決定的な違い

623 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 10:06:45.11 ID:rz+I+TB4.net]
>実装を継承してしまうこと」でこれが依存関係となり負の連鎖をもたらす
実装継承を使えないレベルの人はだいたいこういうふわっとした認識だよね

624 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 10:11:15.42 ID:Eha1J0DV.net]
暗殺術を正しく使える賢者がいる国なんてあったら嫌だなあ
正しく使える者など絶対存在しないという思想は行き過ぎではなくむしろ穏健派

625 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 10:27:32.62 ID:nRN7u0+P.net]
全部が悪いと言う話じゃないけど

既存部分をただ継承させるだけならいいけど一部を上書きしたりして
それが全ての箇所で矛盾のない正しい挙動になるか判定が難しいか不可能な場合がある

結果実装コスト以上に考えざるを得ない…残念なことに本当に楽をしたのかどうか不明な場合がある
継承がないとそれは避けられるから使うな!と言う人が出てくる



626 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 10:29:57.11 ID:nRN7u0+P.net]
変数などに細かいアクセス制限のない言語は特に陥りやすい
制限があったところで制作者がそれを適切に選ばなければならない

どうしても経験や思考時間を必要とする
ガチ勢にはそれが無駄に思えるんだろう

627 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 10:32:06.74 ID:syATK/7U.net]
実装継承は問題を引き起こすだけでなく
代わりの継承機能を提供することで
実装継承は全く不要になったことが大きい
そのためRust、Zig、Nim、Goなどモダンな言語はいずれも言語仕様からクラスを追放している

628 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 10:33:57.16 ID:nRN7u0+P.net]
それをやっても実質オーバーライド問題は解決されていないけどな

629 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 10:45:17.84 ID:4XBGKwNL.net]
>>607
実装継承はすごく便利だからオブジェクト指向言語では誰でも使いやすい機能としてサポートされてた
でも便利すぎて乱用されたからその経験と反省から不便でも乱用されにくいようにした方が得策という考えに至った言語開発者が増えたというのが2010年代
だから今は実装継承は上級者向けの機能という扱い
GoでもRustでも一般的なオブジェクト指向言語よりもわざと使いにくくすることで利便性と問題点を理解して実装方法を選択できる上級者向けの技術になっている

630 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 10:46:54.77 ID:RLTFRTn6.net]
>>615
それは(実装継承となる)クラスでのみ問題となるよな

631 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 10:53:40.16 ID:suA6qkkI.net]
>>616
デタラメを書くなよ
問題となる機能の代わりに便利で問題を起こさない機能を導入したのがRustだ
頭の固いクラス原理主義の人だけが使いにくいと主張してるが
クラスの洗脳から解き放たれた普通の人たちはRustが便利で使いやすいとの理解に至っている

632 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 11:05:57.49 ID:nRN7u0+P.net]
>>618
それは違うかなw
Rustで具体的に他と何が違ってて便利になってるか明言できるか?

Rustでも本質は変わってないのでなんも考えないでコピペ(継承)は避けましょうね
ぐらいのレベルでしかない

633 名前:デフォルトの名無しさん [2024/07/07(日) 11:21:22.62 ID:goRFIXq7.net]
>>607
当時は良いと考えられてたものが後から振り返って「あれは良くなかった」と分かる例はプログラミングに限らず多くあるだろ
Cの時代にRustを設計しろというのは無理で、その間にC++やJavaを経験し、そこで生まれた課題意識がないとGoやRustは生まれなかった
ニュートンの時代に古典力学を超えた量子力学を発見しろみたいなもの

634 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 11:23:38.24 ID:E46Yge5y.net]
>>619
コピペを避けるためにあるのが継承
ただし継承には2種類あって
>>609に説明がある実装継承とそうならない継承がある
実装継承の典型例がクラス継承
実装継承は他の型(またはクラス)に実装を完全に依存してしまっているために硬直化や崩壊などを招いてしまう
解決方法は単純で実装継承とならない継承機能をRustのようにサポートすればよい

635 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 11:31:52.81 ID:Eha1J0DV.net]
当初から、算数の四則演算の型を継承で説明できないことを
知りながら無理を通したぼんくらが流行らせたのだ

難しい算数よりも布教しやすい教義を優先するほうが儲かるという判断
その判断が合理的と思うかどうかは人それぞれ



636 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 11:55:49.26 ID:nRN7u0+P.net]
根本的に継承だけの問題じゃない
結局可視であろうがなかろうが関数自体の挙動が理解しないといけない

addがあってもリストの一番前に追加するか後ろに追加するかと言う機能の違いが合って
コーディングする側がそれを統一的に扱って思った場所に追加されずにバグになる
そういう話だからトレイトだからとか継承亡くしたからとかどうとか関係ない

637 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 11:59:33.31 ID:kX4AKaVh.net]
継承はなくても良いがあると便利 vs 継承はあってはならない
C++は知らなくてもいいが先に知っておくと理解が速い vs C++の理解はいらない

こういう境界線のビミョーな議論だと「まだ結論は出てない」と嘯きやすく続けやすいんだろうか

638 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 13:43:23.71 ID:7CPxEWjC.net]
interfaceはおっけー、abstractは隠蔽されるからだめってことだよ
継承全てが悪というわけではない

639 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 13:46:30.77 ID:7CPxEWjC.net]
kotlinでもabstractクラスはコード自動生成するときしか書かないもん
rustはtraitで十分だし

640 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 14:05:34.19 ID:nRN7u0+P.net]
rustにも派生はあるじゃん

641 名前:デフォルトの名無しさん [2024/07/07(日) 16:52:52.64 ID:7aG8TPof.net]
大きなプログラムを実際に書かずに、本を読むだけで、この言語のこの仕様は悪いとか良いとか判断できるようになりますか?

642 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 17:13:03.91 ID:KUDE2scl.net]
継承はいらん。

理想(のひとつ)はダックタイプで、継承は実装上の都合でそうなっている妥協の産物でしかない。

643 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 17:36:36.74 ID:h+XkpNj2.net]
今まで築いてきた価値観を繰り返し短い言葉で否定して徹底的に壊すというのが洗脳の基本

「継承は悪」「モダンな言語に継承はない」「Rustでは継承による問題は発生しない」(※全部嘘ですよ)

最初に洗脳をはじめた人と違って
洗脳者に洗脳された人は本質を理解していない
そればかりか真実かどうかなんてもはやどうでもよく
自分が信じてることだけが真実だと思っている
だから議論しようという気もなく一方的に同じことを繰り返し書くだけ
掲示板界隈では身近によくあることなので気をつけようね

644 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 18:10:28.88 ID:rdCPsToy.net]
継承はプログラミングで絶対に必要な重要な機能で重複コードを避けることができる
ただし継承といっても複数の方法があって実装継承だけは害を招いてしまう

実装継承とは別の型の具体的な実装をそのまま継承してしまうことを指す
つまり実装継承をすると二つの型の間に不必要に強力な依存関係が生じてしまう

クラス継承でプログラムを書くと自然にこの害悪な実装継承となってしまう
そのため様々な異なる方針のモダンな言語が同じ結論に達してクラスを言語仕様から無くした

Rustではトレイトを使うことで健全な継承機能のみを使うことができる
特にトレイトのデフォルト実装はどの型にも依存しないため実装継承にならずに健全な継承のメリットを最大限に享受することができる

645 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 18:53:59.08 ID:0Udg54Yk.net]
>>628
たくさん本を読み自分の頭で考える努力をすればある程度まではなれる
ただし実地の経験がなければ最終的には他人の受け売りを判断基準にするしかなく
経験のある人間に比べると妥当な判断ができない状況が多くなる

言語の仕様は一面的に良いとか悪いとかという判断を下せるものはほとんどない
長所短所を把握した上でどういう状況であれば他の仕様に比べて優れていて
逆にどういう状況であれば他の仕様に比べて劣るのかという
状況に合わせた判断が必要

つまり妥当な判断を下せる確率を上げるためには
言語の仕様を把握する力よりもそれが使われる状況を幅広く奥深く想定する力を身につけることが重要
これを本を読むだけで身につけようとしてもすぐに頭打ちになる



646 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 19:04:36.65 ID:tn8SIXEe.net]
>>622
>算数の四則演算の型を継承で説明できない
詳しく。

647 名前:デフォルトの名無しさん [2024/07/07(日) 19:34:52.42 ID:goRFIXq7.net]
>>628
他の言語での開発経験がある人が仕様を見て「この言語のこの仕様は好き/嫌い」と言うことはあると思う
どの言語も初心者という人だと無理
それに言語の良し悪しなんて点数で評価できるようなものでないし、好みの問題だったり、ライブラリなどの周辺環境だったり、作りたいもの次第だったりする

648 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 21:58:17.95 ID:rdCPsToy.net]
好き嫌いと良い悪いはしっかり区別つけなければならない
他の型との間で不必要に強力な依存関係が生じてしまう実装継承は悪い
この実装継承となってしまうクラス継承は悪い
Rustに実装継承はなくトレイトを用いることで健全な継承を活用してプログラミングできる

649 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 22:26:34.08 ID:rVoIwJvq.net]
受け売り知識しか持たないとこういう感じで論拠薄弱で空疎な意見しか書けなくなる
いい反面教師だね

650 名前:デフォルトの名無しさん [2024/07/07(日) 22:51:49.25 ID:goRFIXq7.net]
Rustが継承の問題を防げるのってトレイトだけじゃなくてenumの存在も大きいよね
静的ポリモーフィズムを自然に実装できるから、多態のために無理やりインタフェースに当て嵌めようとしたり、ダウンキャストが必要になったりといったものを防げる
本質的に違うものを抽象化しようとして失敗してる例を見たことのある人はそれなりにいるはず

651 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 23:03:31.83 ID:Eha1J0DV.net]
>>633
整数クラスは分数クラスを継承したいが、分母を表す変数は継承したくない

それと文字列 + 文字列が定義されている言語では
分数 + 整数の定義に必要な関数も継承したくない
その関数は文字列と無関係だから

652 名前:デフォルトの名無しさん [2024/07/07(日) 23:46:19.40 ID:QlaAOMK5.net]
>>638
>整数クラスは分数クラスを継承したいが、分母を表す変数は継承したくない
普通、C++だと、整数クラスを作っておき、
分数クラスはそれを継承せずに、
整数クラスを2つメンバに持つクラス
として定義しますよね。
その場合、整数クラスと分数クラスは継承関係を持ってない。

653 名前:デフォルトの名無しさん mailto:sage [2024/07/07(日) 23:51:53.41 ID:gwkq/Sum.net]
>>635
クラス継承の問題はある程度の規模でプログラミングしてきた人の多くが体験してきて、
その根本的原因は実装継承にあることが多くのサイトで解説されている通りだけど、
従来の言語ではクラス継承に代わる手段が弱かったり不便であるため、
仕方なく欠陥のあるクラス継承を使い続けてきた不幸

654 名前:ネ歴史があるんだよ。
クラス継承を使わずにすむRustは恵まれてる。
[]
[ここ壊れてます]

655 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 00:13:34.95 ID:dSFAEVvP.net]
>>638
分数クラスを継承して整数クラスを作りたいという要求と
分母を表す変数は継承したくないという要求が矛盾してる

分数クラスを継承して整数クラスを作りたいということは
分数を特化したものが整数であるというモデルを
分数クラスと整数クラスの実装でも作りたいということ
そのためには整数クラスにも分母を表す変数が当然必要

矛盾した要求が実現できないのは実装技術の問題ではなく要求の不備



656 名前:デフォルトの名無しさん [2024/07/08(月) 00:24:32.58 ID:aZihrzFg.net]
>>607
コード メトリック - 継承の深さ (DIT)
https://learn.microsoft.com/ja-jp/visualstudio/code-quality/code-metrics-depth-of-inheritance?view=vs-2022

継承もやりすぎると毒になるってだけで、全くダメってわけじゃない。

657 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 00:26:00.53 ID:wE6spjgC.net]
>>638
不適切な継承の典型例だな

658 名前:デフォルトの名無しさん [2024/07/08(月) 00:36:15.98 ID:aZihrzFg.net]
>>638
数学では整数の組から分数作るけど、整数クラスが親クラスじゃないのは変じゃない?
(そもそも、継承より整数クラスのインスタンスを分子用と分母用の2個使う委譲スタイルの方が適切だと思うけど)

(n,m)とn/mは同型

659 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 01:24:33.08 ID:QXtalhpf.net]
どういう用途のためにクラスを作ろうとしているのか不明瞭な段階で
特定の実装方法が適切だと思い込むのは感心しない

660 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 05:17:42.23 ID:9vKk3LiW.net]
>>630
継承自体は悪くない
重複コードを回避できて保守性も向上する
つまり継承自体は良いもの

ただし実装継承だけは悪
異なる型同士に過度な依存をもたらし保守性を悪くする
クラス継承は実装継承となるため悪
モダンな各言語がクラスを排除した理由はそのため

Rustに実装継承はなく継承でそのような問題を起こさない

661 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 09:13:52.72 ID:1Z2Y8mSg.net]
継承で重複コードを回避できるのは実装も共有する継承だけ
つまり実装継承だけ

Rustスレでこんな初歩的なことを説明しなきゃいけないのはすごく悲しい

662 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 09:32:49.17 ID:QAb8fFud.net]
今回はいつまでやるの?

663 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 09:42:44.60 ID:jJBNmhlI.net]
>>647
実装継承の意味を理解したほうがいいんじゃね?
ある型Aの実装を別の型Bが継承することが実装継承と呼ばれているんだよ
これは不必要に依存関係が強すぎて片方を機能拡張しようとしたときなど破綻を招きがち
だから実装継承となるのは避けるべきと言われているね

664 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 10:06:04.28 ID:eiH/KN8v.net]
ワイの思う継承はenum_dispatch crate でやれるから困ったことないなぁ
お前らの心の中の継承は知らんがw

665 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 10:42:22.99 ID:UCsocQnW.net]
分数はバカっぽい
有理数と言え



666 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 10:42:53.94 ID:29FzOd3r.net]
>>647
Rustに実装継承はないけど
継承があり重複コードを回避できている

667 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 10:43:30.84 ID:29FzOd3r.net]
例えばどんな型でどんな内部構造でも
その型にトレイトのnext関数を実装するだけでイテーレータとして機能するが
その時に他のメソッド(nthとかmapとかfoldなど)のコードを自分で書かなくても自動的に継承されて機能する

668 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 10:44:27.48 ID:29FzOd3r.net]
これをデフォルト実装と言い特定の型の構造に全く依存しないコードのみを書くことができる
つまり問題を起こす実装継承とならず
Rustでは健全な継承が実現されている

669 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 10:55:22.37 ID:6tgHXwg2.net]
複オジの耳に念仏
まさに>>630

670 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 11:03:01.23 ID:aq0ZJn08.net]
デフォルト実装の制限のかけ方が成功の肝かな
トレイトなので各型のメンバーフィールドには一切アクセスできないため実装継承が上手く回避されてる

671 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 11:27:47.73 ID:Qb4+6aEo.net]
「実装は継承しているけど実装継承ではない」w

672 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 11:38:02.68 ID:0gbetOzk.net]
複オジ論法は無敵だな

673 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 11:49:10.64 ID:aq0ZJn08.net]
>>657
他の型の実装に実装が依存することが実装継承と呼ばれてる

674 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 13:25:29.85 ID:QAb8fFud.net]
継承の本当の問題は、LSPを満たさない部分型関係を作ってしまいがちということ
他の型の実装に依存するのが良くないというのはDIの話で、直接は関係ない

675 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 13:56:53.31 ID:0on8bWSc.net]
うそん
crate製作者サイドでCargo.toml内の
他のcrateへの依存関係の描き方がいい加減だと
割りと頻繁に詰む
人間が追跡して治して行けば使えなくもないが
cratesは破綻する可能性がある



676 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 15:03:24.53 ID:HJF+848e.net]
クレートdownloadでか過ぎ

どうみてもどんぐりです
ばいばいおさるさん
ころころす

677 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 17:42:30.38 ID:NWN6grys.net]
>>660
クラスを用いる言語では必ず満たすべきLSP(リスコフの置換原則)が頻繁に守られていない現実から
GoやRustなどモダンな言語はクラスそのものを廃止して改善したわけだ
他の型の実装に依存するのが良くないのも当たり前の話でそこは各型へ移譲しなければならない

678 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 18:36:24.36 ID:jkhWqaDw.net]
>>663
LSP全然理解してないんやな
クラスの有無とか全く関係ないぞ

679 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 18:41:05.12 ID:BP+Tby1x.net]
>>657
ジワジワくる

680 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 19:00:42.33 ID:lBXxnkJT.net]
>>657が実装継承とは何かすら理解できていなくて草

681 名前:デフォルトの名無しさん mailto:sage [2024/07/08(月) 23:32:15.60 ID:HOKpNi7I.net]
所有権といい継承といいLSPといい
某オジは抽象概念を捻じ曲げるスキルが高すぎだろ

682 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 00:42:48.79 ID:m6Akkl5N.net]
>>660
LSPは派生型がその基底型を継承する時その振る舞いは同じで代替できるという当たり前な話なんだが
クラスはこの件でも欠陥があるため意識してプログラムを書かないとLSPに反してしまう
Rustはクラスがなくトレイトは枠組みだけで基底型ではないためLSPは全く関係ないぞ

683 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 02:24:36.95 ID:ZNKPIxXk.net]
>LSPは派生型がその基底型を継承する時その振る舞いは同じで代替できるという当たり前な話なんだが

0点

684 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 11:02:57.90 ID:Gz8hLZg7.net]
書けば書くほど無知をさらしてしまう複製オジさん草る

685 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 12:31:29.17 ID:B8U2Xwe0.net]
>>664
対象となるものはクラスしかないよね



686 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 12:39:43.65 ID:YflJELWV.net]
>>668
φ(x) を型 T のオブジェクト x に関して証明可能な性質とする。このとき、φ(y) は型 T のサブタイプ S のオブジェクト y について真でなければならない。

φは主に事前条件・事後条件・不変条件で、言語によっては例外条件も入ってくる。
この観点からはRustのTraitは力不足。なんでLSPを引き合いに出せるのかわからん。

687 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 12:57:46.02 ID:aoAam1/W.net]
>>672
自分でそれを書いておいて理解できていないのかよ
そこに明記されてるようにTもSもオブジェクトを持つ具体型についての話だ
Rustのtraitは具体型ではないため関係ないぞ
そしてtraitを実装する各型の間にはサブタイプの関係はないためそこも対象とならない
そこを理解できずに「RustのTraitは力不足」とデタラメを吹聴するのは恥ずかしい

688 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 13:01:26.64 ID:YflJELWV.net]
>>673
事前条件とかはどこ行ったの?

689 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 13:20:56.23 ID:aoAam1/W.net]
>>674
φ(x) のxはオブジェクトと明記されてるのが見えないのかね
さらにSはTのサブタイプと明記されている
Rustのtrait自体はオブジェクトを持たない
さらにtraitを実装する二つの型同士にサブタイプの関係は生じない
つまり対象外でφが存在しないため事前条件も何もない

690 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 13:35:41.29 ID:YflJELWV.net]
>>675
>明記されてるのが見えないのかね
>Rustのtrait自体はオブジェクトを持たない

それは「RustのTraitはLSPと関係ない」と言いたいの?

>φが存在しないため事前条件も何もない
事前条件も何も表明できないのは「力不足」そのものですな。

691 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 14:43:14.46 ID:Tc+iYmTn.net]
リファクタリングするとき
プログラム(CPU)の動作の副作用は起きないけど
コーディングの変更に対して副作用が大き過ぎるというか広過ぎる

692 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 15:17:32.29 ID:l7dFkPpL.net]
>>673
マジでLSP全然理解してないんやな
LSPは具体型かどうかなんて全く関係ないぞ

693 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 15:20:15.91 ID:aoAam1/W.net]
>>676
LSPに明記されている前提すら満たさない異なるものであるため
「RustのTraitはLSPと関係ない」で合っている
LSPが対象としている遺物における諸問題に悩まされずに済むように
新たな視点で整理されたより良いものとしてRustのTraitが提供されている

694 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 15:28:08.29 ID:aoAam1/W.net]
>>678
LSPは具体型のみが対象
抽象型を対象にしようとしても適用するにはそのいずれかの具体型となる

695 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 17:53:13.80 ID:uNqr/AfO.net]
https://x.com/shuzaibusoku7/status/1809567812555542920
リアル複おじ



696 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 20:23:57.43 ID:YflJELWV.net]
>>679
RustとLSPが関係ないのなら、LSPを引き合いに出すのは大嘘か。
知ってて言っているなら詐欺師だな。

そもそもTraitでpanic禁止にできない時点で「LSPが対象としている遺物における諸問題に悩まされずに済む」というのも大嘘だしな。

697 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 20:49:10.75 ID:sTXYSGuF.net]
簡単な話だよな
オブジェクト指向プログラミングで
例えばクラスを使うと
LSPに違反する二つの型のコード例を容易に作れてしまう
つまりクラスは本質的に欠陥品なんだよ

Rustのトレイトを使うと
LSPに違反する二つの型のコード例を作ることができない
つまりRustのトレイトは優れた方式なんだよ

698 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 21:07:20.42 ID:YflJELWV.net]
>>683
あるトレイトでpanic2を禁止しようとしました。事前条件(あるいは例外条件)でnopanicとしたかったけど、そんなのは無いのでとりあえずデフォルト実装でpanic禁止にしました。
しかしトレイトユーザーはそんなのお構い無しにunsafe rustでpanicを使います。ついにpanicが発生してシステムダウンしました。

LSPでケアしている問題はRustのTraitを使っている限り発生しないんじゃないんだっけ?

699 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 21:56:05.19 ID:sTXYSGuF.net]
Rustのトレイトは優れているため
LSPに違反するコード例を作ることができないんだよ
もしRustに文句をつけたかったら
LSPに違反する二つの型のコード例を作って示してごらん
Rustで違反例を作るのは不可能だよ

700 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 22:08:43.14 ID:ZNKPIxXk.net]
>>685
Rustに文句をつけたいとかではなく
>>660でLSPに言及された途端に実装継承とか言わなくなって「最初から自分はLSPを理由に継承のダメさを語ってましたけど」って態度でイキリ倒してるの(+結局理解してなさそうなの)がバカにされとるんやで

701 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 22:36:56.01 ID:YflJELWV.net]
>>685
>>684みたいに、
トレイトがpanicを禁止したいのに、ユーザーのトレイト実装がpanicを返す
というのはLSP違反だろ。

702 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 22:44:26.63 ID:loMF79su.net]
LSPはそんなことを要求していないよ
LSPをちゃんと読んで理解しようね

703 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 22:50:55.17 ID:aoAam1/W.net]
>>686
クラスは様々な問題点を抱えている
クラスでは実装継承となるため異なる型同士に不必要に過度な依存関係をもたらす硬直性も問題点の一つ
クラスはLSP(リスコフの置換原則)を満たさないプログラムが量産されてしまう問題点も別の一つ
どちらの問題点もRustならtraitを使うため問題が起きない

704 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 22:52:12.26 ID:j8eVmrRh.net]
猿ども落ち着いてください!

ここで論破合戦したところでなんの得にもなりません

705 名前:デフォルトの名無しさん [2024/07/09(火) 22:57:23.83 ID:/lHavWP5.net]
>>685
リスコフの置換原則は設計的な原則だから言語仕様で違反を防ぐことはできないぞ
悪名高い長方形・正方形の問題はトレイトがあっても起こり得る

trait Rectangle {
 fn set_width(&mut self, width: i32);
 fn set_height(&mut self, height: i32);
 fn width(&self) -> i32;
 fn height(&self) -> i32;
 fn area(&self) -> i32 { self.width() * self.height() }
}

struct Square { len: i32 }

impl Rectangle for Square {
 fn set_width(&mut self, width: i32) { self.len = width; }
 fn set_height(&mut self, height: i32) { self.len = width; }
 fn width(&self) -> i32 { self.len }
 fn height(&self) -> i32 { self.len }
}

fn func(x: &mut impl Rectangle) {
 x.set_width(3);
 x.set_height(4);

 // xが長方形であれば以下が成り立つはずだが、Square型を渡された場合に失敗する
 assert!(x.area() == 12);
}



706 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 23:17:09.97 ID:dptasXVA.net]
>>691
長方形がトレイトで正方形が構造体とか意味不明なんだが他の形はどっちにするんだ?
おかしいだろ

707 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 23:22:06.46 ID:J+Fyw0mO.net]
>>691
トレイトは機能を表します
2つの異なる長さを持つ(受け取る)機能を定義しているのならば
正方形はその実装型にはなりえません

708 名前:デフォルトの名無しさん [2024/07/09(火) 23:24:11.46 ID:KAvgjhF7.net]
>>692
IRectanble トレイトとかに読み替えてくれ
これは設計的に問題のある例を恣意的に示しているので不自然な点はあるけど、意図は伝わると思う

分かる人は分かると思うけど、問題は「そもそも正方形はwidthとheightという2つの値を扱うインタエースを持つべきでない」というところなので、Rectangleトレイトを作った時点で破綻している
けどそれは設計の問題なので、トレイトという仕組みによってコンパイラが防げるものではないということ

709 名前:デフォルトの名無しさん [2024/07/09(火) 23:30:16.52 ID:KAvgjhF7.net]
>2つの異なる長さを持つ(受け取る)機能を定義しているのならば
>正方形はその実装型にはなりえません
論理的にはそう
でも実際にそういうコードを書けばビルドは通る

>>685
>LSPに違反する二つの型のコード例を作って示してごらん
>Rustで違反例を作るのは不可能だよ
とあったので、これはその反例として示した
このような問題は設計の問題であり、まずい設計をする人が使えばRustでも問題は起こり得るということを言いたい

710 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 23:35:35.51 ID:h2DmPYHm.net]
>>691
君はLSPを理解できていない
LSPはis-aの関係を持つ二つの型に対して遵守すべきルールだ
Rustのtraitとその実装型はis-aの関係ではなくhas-aの関係を持つ
したがってtraitとその実装型は明らかにLSPの対象外となる

711 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 23:40:48.87 ID:h2DmPYHm.net]
>>695
LSPに違反する二つの型はis-aの関係を持つsupertypeとsubtypeでなければならない
>>691はhas-aの関係なのでLSPに違反する二つの型のコード例とはなっていない

712 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 23:56:35.46 ID:ZNKPIxXk.net]
>Rustのtraitとその実装型はis-aの関係ではなくhas-aの関係を持つ

すげーのが出てきたなこりゃw

713 名前:デフォルトの名無しさん mailto:sage [2024/07/09(火) 23:59:12.82 ID:loMF79su.net]
LSPはis-a関係に対して守るべき原則
has-a関係に対してLSPの適用は論外
コード>>691はLSPの違反例となっていない

714 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 00:09:07.13 ID:H4rrLaXL.net]
メンバ関数名をそのままtraitの名前にしちまえば
そのメンバを持つ者とtraitの関係はhas-a

715 名前:デフォルトの名無しさん [2024/07/10(水) 00:10:24.05 ID:HryWiaEt.net]
過去に見た (rust以外の) プロジェクトの失敗例だと
・もともとFooというクラスがあった
・新しく作るBooクラスについて、Fooクラスと同じように扱えれば既存コードをあまり変更しなくても済むぞ!と誰かが気づいた
・その人物は Foo クラスのメソッドを元に IFoo インタフェースを定義し、それを Foo と Boo に実装させた
ことから混沌としたコードが生まれた例がある

この失敗をやらかした人は、Rustでも同じように「既存の Rectangle クラスを元に IRectangle トレイトを作り、それを Rectangle と Square に実装させる」ことをやりかねない

Rustではそれが不自然なパターンになりやすいし、起こりにくくはあるけど、本質的には設計の問題



716 名前:デフォルトの名無しさん [2024/07/10(水) 00:29:11.77 ID:HryWiaEt.net]
「Rustを書く人はみんな賢いからそのような問題は起こさないはずだ」というなら話は別たけど
実装者の設計能力は言語仕様によって担保できるものではない

717 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 00:33:23.92 ID:L/ekmjSC.net]
>>701
それらインタフェースやトレイトを用いている時点でLSPの対象外となっている
LSPを満たす必要がないどころかそんな制限があったら支障が出る
>>691のコードをLSP違反例として出してきたのは明確に間違い
おバカな設計例としてならば理解する

718 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 00:35:49.38 ID:L/ekmjSC.net]
>>702
おバカな設計を言語仕様で防げるなんて主張は誰もしていない
あなたが勘違い思い込みで暴走している

719 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 00:36:32.00 ID:NGyo+F/O.net]
LSPを全く理解してないばかりか
サブタイピングも理解しとらんのやな
よう継承継承言うたなぁw

720 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 00:53:28.80 ID:ur6BKR72.net]
クラスが問題だらけの欠陥品なことが災いを招いてるよね
モダンなプログラミング言語の多くがクラスを捨て去ってくれて感謝

721 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 01:13:16.99 ID:1XduDtMr.net]
>>688
>>679の言う「LSPが対象としている遺物における諸問題に悩まされずに済むように」するためには必要なんだよ。
LISKOVのA behavioral notion of subtyping でも「include exception」と言っているだろ。

まぁ、panicが例外にもなれないそびえ立つクソだからRustから排除すべき、と言うなら同意するが。

722 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 01:26:45.94 ID:UJdk5M3g.net]
>>707
LSPはsuperclassとsubclassといったような関係を持つ型同士について満たすべき話が書かれてるんよ
その前提を無視してpanicがどうこう言い出してるからズレとるんよ

723 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 01:45:22.45 ID:1XduDtMr.net]
>>708
それを言うなら>>682で言っている通り、RustのTraitでLSPに言及するのが大嘘なんだよ。

RustのTraitは同じTraitでも簡単に異なる振る舞いを実装できる(panicみたいな致命的な振る舞い含め)のに、「LSPが対象としている遺物における諸問題に悩まされずに済む」とかの大嘘が出てくるのは何ともアホらしい話。

724 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 02:13:28.47 ID:1XduDtMr.net]
>>698
RustのTraitとImplの関係はまさしくsubtypeだしis-aの関係なのにな。「継承しなければsubtypeじゃないしis-aにもならない」と間違って覚えているんかね。

725 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 02:30:31.13 ID:GS4KrVsy.net]
どこかで聞きかじっただけの「継承は悪」に辻褄を合わせようとしてどんどん変な理屈を積み重ねているだけでしょ



726 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 02:33:48.76 ID:H5PXuDT2.net]
>>707
LSPでは例外を返すなら基底型で返す例外とそのサブタイプのみに限られるとしか言及していない
例外で値をキャッチできなくなることや値を返す抜け道になることを防ぐためだ

ちなみにRustのpanic!では値を返すことはできなくてpanicメッセージのみ
そして普通のプログラムでpanicをキャッチすることはない点など前提が全く異なる
Rustで従来の例外を扱うケースはpanic!を使わずにResultの返り値で返す
したがってpanic!はLSPで出てくる例外の話に該当しないだろう

727 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 03:06:35.71 ID:mzDH1NTP.net]
>それらインタフェースやトレイトを用いている時点でLSPの対象外となっている
間違ってるよ
インターフェースだろうがトレイトだろうがサブタイピングは成立するよ
サブタイピングが成立すれば当然LSPの対象範囲だよ

>>691の例もLSPの違反例としては合ってるよ
間違った継承の使い方の例としてよく使われてるよね

728 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 04:10:08.62 ID:xXJVwGE7.net]
>>684
>panic禁止にしました。

たとえno_std環境であろうとpanicは禁止にできない

>unsafe rustでpanicを使います。

panicを引き起こすのも扱うのもunsafeを必要としない

>panicが発生してシステムダウンしました。

panic発生がそのままシステムダウンではない
何ら特別な設定をしない標準状態でもスレッド内で起きたpanicはエラーとして返るだけで他のスレッドは動き続ける

729 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 07:01:39.33 ID:H4rrLaXL.net]
>>710
型クラスのinstanceであると宣言すればsubtypeじゃないのは自明だぜ
じゃあtraitをimplすると宣言したら
自明だった問題が突如として最先端の未解決問題に変化するのか?
しないでしょ
同じでしょ

730 名前:デフォルトの名無しさん [2024/07/10(水) 07:02:08.59 ID:HryWiaEt.net]
>>704
ずっと「オブジェクト指向言語のクラスが抱えている問題はRustでは起こらない」と主張してる人がいるでしょ
それに対して、そんなことはないよと言ってるだけ

731 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 07:35:50.92 ID:1hn7S5X0.net]
>>716
あらゆる問題が解決されたという話は出てないでしょ
クラスが抱えてる問題でRustによって解決されてる様々な例が出ているだけで

732 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 08:46:54.18 ID:1XduDtMr.net]
>>714
だからLSPが対象としている諸問題はRustじゃ解決しないと主張しているんだよ。

>>715
implの実装次第なのに、
「LSPが対象としている遺物における諸問題に悩まされずに済む」と言っているアホが居るのよ。
そんな機能はRustのTrailには無いわな。

>>717
「遺物における諸問題に悩まされずに済む」と言っているアホが居るのよ。しまいにはRustとLSPは関係無いとか言うし。
そんなわけ無いだろと主張している。

733 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 12:00:16.62 ID:GhKm8r1f.net]
>>718
そのアンカ先は全部複オジだろ
LSPも知らない、サブタイピングも知らない、継承で起こりうる簡単な問題も知らない
にもかかわらず知ったかぶりして嘘を並び立てる
こんなやつがそうそういるわけがない

734 名前:デフォルトの名無しさん [2024/07/10(水) 12:37:44.86 ID:1YSFCzN+.net]
キチガイは1人見かけたら10人はいると思え

735 名前:デフォルトの名無しさん [2024/07/10(水) 13:29:52.02 ID:kPG9kWdt.net]
>>701
そのやり方がなぜ悪いのか理解できませんので、教えてください。
例えば、C++だと、以下の様にするのも別に悪いやり方ではないような
気がするのですが。
class Number {・・・};
Number add(Number &a, Number &b);
Number mul(Number &a, Number &b);
class Integer : public Number {・・・};
class Rational : public Number {・・・};



736 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 13:32:41.05 ID:2GPD5dJ4.net]
ChatGPTってモノシリなんですね?

737 名前:デフォルトの名無しさん [2024/07/10(水) 13:34:42.29 ID:kPG9kWdt.net]
>>721
改めて見てみると、add()やmul()の戻り値にNumberの実態を返しているのがおかしい気もしますが。
IntegerやRationalにadd()やmul()を仮想関数として定義するのが良いのかもしれません。
そのような点で改良の余地が沢山ありそうです。

738 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 13:47:33.33 ID:2GPD5dJ4.net]
>>720
色んな板の色んなスレをみて来ているが
どこにでもいるのは事実

739 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 14:42:18.00 ID:H4rrLaXL.net]
10人いると思ってる人自身が11人目になりやすいから気をつけなよ
数値の計測が抱えている問題は、そもそも計測していない人には起こらない

740 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 15:49:38.80 ID:WriLZMcZ.net]
>>721
add(integer, rational)できる?

741 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 16:24:23.57 ID:2GPD5dJ4.net]
ミイラとりがミイラになるのは昔から

742 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 16:42:16.40 ID:aw6hROvm.net]
>>712
>例外で値をキャッチできなくなることや値を返す抜け道になることを防ぐためだ
違うよ
勝手な想像でLSPを誤解釈しないで

substituteされる型Tに対して定義された仕様上(契約上)の振る舞いを
substituteする型Sが満たしてなければLSP違反
つまり仕様上panicを禁止したトレイトの関数を
panicする関数でimplしたらLSP違反


743 名前:
LSPではあくまで”仕様上定義された振る舞い”が問題
[]
[ここ壊れてます]

744 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 18:28:13.04 ID:/bwWoePd.net]
>>728
panicを禁止という概念も方法もなく不可能だよ
何をしたいの?

745 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 21:04:08.95 ID:H4rrLaXL.net]
catchするという対案がない
対案との比較が抱えている問題はそもそも対案がない言語では起こらない



746 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 21:42:13.36 ID:DHf/HCo5.net]
>>729
そいつはRust叩きで連投していた>>684
panicを禁止できると思い込み
unsafeを使うとpanicできると思い込んでいる

747 名前:デフォルトの名無しさん [2024/07/10(水) 22:01:49.20 ID:HryWiaEt.net]
>>721
「インタフェースを定義し、それに基づいて実装する」という設計なら問題ないのだけど、
これは「あるクラスに依存していたコード群が新しいクラスでも動くようにするため」という発想になっており、大規模な開発だとこのやり方はだいたい失敗するよという話

例を書きづらいけど、例えば「A社製の装置を制御するアプリ」があったとして、
新しく「B社製の装置も制御できるようにする」という追加の開発案件があったとする。
この時点ではまだADeviceControllerは抽象化されておらず、A社装置の仕様に強く依存したクラスであるとする。
これを「ADeviceController が持つメソッドを IDeviceController として取り出し、それを BDeviceControllerにも実装させる」とすると確実に事故る。
「B社装置にだけある機能Xを呼びたい」「A社装置にあった機能YがB社装置にはない」といった違いを吸収しきえれず、インタフェースがぐちゃぐちゃになったり、「呼んでも何もしない」とかの形で誤魔化したり、呼び出し元でサブクラスの判定が必要になったりする

こうならないようにするには
a. 具体的な機器に依存しない、機器の振る舞いを適切に抽象化したインタフェースを定義する
b. 代数的データ型を使う
という方法があり、 Rust では b. の方法も使いやすいので、個人的にはそこが良いなと思う

748 名前:デフォルトの名無しさん [2024/07/10(水) 22:15:46.44 ID:b9m+kH0p.net]
設計が悪いといえばその通りなんだけど、そのせいでインタフェースが崩壊しているプロジェクトは実際にあるし、RustやGoが継承を廃止した理由の一つでもあると思う
クラス継承だとこの問題はもっと簡単に起こりやすい
前述の例は (あくまでも見かけ上は) インタフェースを定義しており、クラスを継承してるわけではないので、Rustのトレイトでもやろうと思えば起こるけどね

749 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 22:19:25.73 ID:FlmWdBd4.net]
言語を選ぶにあたって継承の有無は選択肢に入らんし正直言ってどうでもいいわ
代替手段があるのにいつまで言ってんだ

750 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 22:32:22.87 ID:dGMDZq55.net]
>>729
仕様を定義するという簡単なお話がほんとにわからないのかな?

panicを例にすると頭がパニクるみたいなので
リスコフの論文にあるFIFO/LIFOの例で言い換えると
仕様としてLIFOの振る舞いを要求するトレイトの関数を
FIFOの振る舞いで実装したらLSP違反ってこと

簡単なお話でしょ?

751 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 22:40:16.17 ID:H4rrLaXL.net]
既に言語を選んだのにまだ、is-aとhas-aどっちにするか選べとか
catchするかしないか選べとか
言語の内部でいつまでも選択が繰り返されるシステムが謎なんよ

いつまで言われるかといえば謎が解けるまでだよ

752 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 23:21:18.85 ID:visgGGe9.net]
>>732
それは共通インターフェースと特定装置にしかないインターフェースをそれぞれ別で用意すべきだと思う
拡張メソッドや拡張トレイトも活用する

ただA社装置もB社装置も1つの共通したコードで扱うなら
サブクラス判定ではないにしても呼び出し元での分岐は何かしら必要

753 名前:デフォルトの名無しさん mailto:sage [2024/07/10(水) 23:44:27.81 ID:6pwTfhEs.net]
>>733
RustやGoは違う方法で継承を行っているというだけで継承を廃止したというのは誤解
わざと誤解

754 名前:させてるという面もあるにはある []
[ここ壊れてます]

755 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 00:29:09.09 ID:dTTJ6k+i.net]
クイズ
JavaScriptのプロトタイプチェーンはis-a?
それともhas-a?



756 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 00:30:41.75 ID:sJ7PGs8/.net]
>>732
一般的に何らかの上位層と下位層があるときに
Rustではその界面にtraitを置いて
上位層はそのtraitを利用する側
下位層はそのtraitを実装する側
とSILIDのDIP (Dependency Inversion Principle)にするのがそのa.だね
もしクラスでやるときは抽象化を徹底した上で色んな注意が必要になるところ
Rustは自然にコーディングできてありがたいね

757 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 01:01:01.84 ID:sJ7PGs8/.net]
スマソ
SILIDはSOLIDのタイポ

758 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 01:26:06.15 ID:sLOW5r2m.net]
>>740
インターフェース知らないの?

759 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 01:37:36.53 ID:sJ7PGs8/.net]
>>742
インタフェースは各言語で付加仕様がバラバラ多種多様だから慎重に言うと
それ自体はフィールド変数など持たず完全に抽象化できつつ
実装必須メソッドとデフォルト実装提供メソッドがサポートされて
その中で利用可能な他のインタフェース(またはtrait)群による制約ができて
となるとどの言語が残るかな

760 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 03:34:06.04 ID:huEwUyFV.net]
それはたぶんDじゃなくてIかな……

761 名前:デフォルトの名無しさん [2024/07/11(木) 09:53:46.09 ID:TzM2Jqw+.net]
https://doc.rust-jp.rs/ 終了の件

762 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 11:33:08.04 ID:gcQpVY2c.net]
>>744
DもIも両方関係あるよ

763 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 11:36:08.08 ID:gcQpVY2c.net]
>>743
インターフェースが使えるメジャーな言語は全部残る
C#, Java, Kotlin, Swift, TypeScript, Dart

764 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 11:46:30.35 ID:ITTQebkb.net]
ʕ◔ϖ◔ʔ

765 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 12:31:18.41 ID:QtPgEU0q.net]
>>747
ウソはあかん



766 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 13:53:08.83 ID:gabJiib7.net]
>>747
サーバー用途で強いJavaは残るね
Kotlin/Swiftもモバイルアプリのネイティブ言語として残る
TSはJSで十分っていう風潮が漂いつつあるけどまあ残るだろう
死ぬのはC#とDartかな

767 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 14:12:48.49 ID:0oGtZVd6.net]
LSPで嘘ばっかりついてたのがバレたから
またしょうもない話をはじめてごまかそうとしてるのか
いい加減にしろよ

768 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 16:22:35.45 ID:o6wwWo1Z.net]
LSPに書かれていることすら読まずに
RustのトレイトがLSPの対象だと言い張ってたもんな

769 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 16:57:46.28 ID:acwFdQNv.net]
PartialOrdとPartialEqの一貫性とかLSPっぽいけど
Substitution(置換)とはちょっと違うんだよな
無理矢理Sに当てるならSurrogation(代用)あたりか
これをLSPに含めるかは定義重視vs意味重視で意見が分かれそう

770 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 17:15:40.81 ID:HnhcW2rv.net]
LSPはsupertypeのインスタンス(オブジェクト)とsubtypeのインスタンスの振る舞いを比較してそこで満たすべき原則を挙げていますから
Rustのtraitをsupertypeとしてみてもそのインスタンスが存在しないため振る舞いの比較ができないですね
traitはLSPとは関係ない立ち位置にいます

771 名前:デフォルトの名無しさん [2024/07/11(木) 20:33:40.77 ID:eOImp5ti.net]
ごちゃごちゃ難しいこと考えてるうちにエンバグしたりなんかして。

772 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 21:02:05.21 ID:qBSAH7HU.net]
>>750
サーバー用途こそJavaはRustとGoに蹴散らされて終わるだろ

773 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 21:30:58.09 ID:wPVHCKh0.net]
実際のところRustはサーバーサイドで使われてるの?

774 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 22:25:27.54 ID:A0mL7vqg.net]
実際は派生クラスの方が支持されていたとしても基底クラスを蹴散らしてはならない
とLSPは言っている

775 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 22:35:40.65 ID:Z3SFRt47.net]
>>757
使われてないよ



776 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 22:47:57.53 ID:Wdw77EAw.net]
>>757
Rust利用のトップがウェブのサーバー側
この件は過去スレでも何度も出ているので興味あるなら見るといいよ
その理由も明白でリソースコスト削減が最も効くため

777 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 22:50:39.98 ID:wG+w8SXo.net]
サーバーは常時稼働させるものだからねえ

778 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 23:16:00.08 ID:liPsU6bJ.net]
>>757
GAFAMとかCloudflareとかトラフィックの多いとこに入ってるから誰もが必ずお世話になってる程度には使われてる
日本でサーバーサイドの仕事が沢山あるか、という意味ならそんなことはない

779 名前:デフォルトの名無しさん mailto:sage [2024/07/11(木) 23:24:11.59 ID:b01V4j67.net]
世界中で着実にRustへ置き換わっていってるね
特にクラウドを利用しているとランニングコストに直結するので

780 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 00:13:00.93 ID:0qGKBZrU.net]
>>753, 754
トレイトの場合はLSPで言うsupertypeやsubtypeになるのは
トレイトを利用して作られるimpl Traitやtrait objectの型だよ

PartialOrd/PartialEqやFn/FnMut/FnOnceのように
supertrait/subtraitの関係にあるやつも便宜的にトレイトで互換性が語られるけど
実際はそれらを利用して作られる型についての話なのと同じなんだよ

781 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 00:16:45.77 ID:U8/iJiIO.net]
>>764
真面目に相手してあげるの偉いな

782 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 00:19:01.43 ID:iZsWh24v.net]
>>764
いいえ
traitが実装される具体的な型は全てsubtypeに相当する兄弟同士であるため
親となるsupertypeの具体的な型はありませんはありません

783 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 00:19:49.06 ID:iZsWh24v.net]
>>764
いいえ
traitが実装される具体的な型は全てsubtypeに相当する兄弟同士であるため
親となるsupertypeに相当する具体的な型はありません

784 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 00:47:16.73 ID:KyXC0KGT.net]
トレイトにはフィールド変数が一つもなくてメソッドも各個別型で実装されるものだから事前条件・事後条件など比較もできなくてLSP適用は無理でしょ

>>764
supertrait/subtraitの場合に例えばある構造体についてそのインスタンスはどちらも同一になるからLSPの前提である二つのインスタンス間での差は論じられないでしょ

785 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 09:52:35.34 ID:bw8b12Bg.net]
>>757
Rustは殆どどこにも使われてないよ



786 名前:デフォルトの名無しさん [2024/07/12(金) 10:23:09.62 ID:LuKbokrL.net]
「C言語は分かる。機械語も分かる、回路もわかる。30万払うからRustのメモリ安全のからくりをサクッとレクチャーしてくれ」
みたいなニーズがあっさり無料で満たされているべきだと思うんだ

787 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 10:57:31.20 ID:KyXC0KGT.net]
誤解は色々あるけど「努力すれば必ずゼロコストになるカラクリ」が
あると思ってるならそれが誤解だね
クイックソートやハッシュテーブルと同じく、最悪の場合のコストは低くない

788 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 11:16:56.09 ID:LuKbokrL.net]
間違ってたら指摘してくれ

メモリは唯一の所有者を持つ
所有者たる変数がスコープを抜けた時、もしくは所有者たる変数に他の値が代入された時、メモリは自動的に解放される
Rustの、メモリに関する様々な文法はひとえにレキシカルライフタイムのためである
レキシカルライフタイムすなわち字句的寿命は、プログラムを走らせなくともコンパイル時に変数の寿命が把握できる仕掛けである
メモリの使途に矛盾が発生しているとき、Rustコンパイラはエラーを吐く

789 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 11:28:19.38 ID:LuKbokrL.net]
そもそも動的メモリ確保一般を知っていますかって話で、
この質問にイエスと答えられる人は横着ができるべき

790 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 13:01:13.97 ID:KyXC0KGT.net]
>>771
Rustのゼロコスト抽象化はそういう意味ではなくてRustの様々な抽象化仕様を実行時の追加コストゼロで実現していることでしょ

>>772
値がムーブされないままスコープが尽きたらデストラクタが自動で呼ばれるだけでしょ
だからRcのように参照カウンタを用いて共有ownershipを提供する仕組みもあるよ

791 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 13:21:18.68 ID:KyXC0KGT.net]
唯一の所有者が存在することと所有者の情報を誰でも取得できることを
区別するのは少し難しい
大谷の家が実在することと住所を公表できることを区別できない人もいるかもしれない

792 名前:デフォルトの名無しさん [2024/07/12(金) 14:02:34.71 ID:HU5SDXKx.net]
「A が Bの継承クラスであること。即ち、C++で
class A : public B {・・・};
と書くのは『A is B』である時が良い事が多いですよ」
という説が有りますけれど、
「多い」というだけだと理解してたんですが、このスレの人には、このルール
を徹底徹尾適用できる言語を夢見ておられるようですね。

793 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 14:20:30.92 ID:KyXC0KGT.net]
ここでID何度か被ってきたけどポエムの人とID被ったのは初めて

>>776
クラス継承はメリットが少なくデメリットが多いと長年の共通体験で判明してそれが共通認識となっているから
様々な異なる方針のモダンな言語たちがクラス廃止の点では共通方針となっただけでしょ

794 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 15:35:12.29 ID:4qvv2DeJ.net]
何気なく cargo update すると後悔する orz

795 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 15:44:29.48 ID:4qvv2DeJ.net]
GAFAM は存在しない
今は GAMAM



796 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 15:46:16.40 ID:4qvv2DeJ.net]
>>772
drop(hoge)

797 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 15:49:17.77 ID:4qvv2DeJ.net]
>>773
Box
Rc
Arc
Cell
RefCell
OnceCell
Pin

798 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 17:11:30.65 ID:LuKbokrL.net]
>>780
サンキュー

>>781
そのあたり全然勉強してない
「相互に参照し合うあうメモリは持てません。それを制限してあまりあるメリットを提供します。どうしてもやりたい人のために別口を用意しました」
という事実が重要

799 名前:デフォルトの名無しさん [2024/07/12(金) 20:20:08.14 ID:0tYdINiS.net]
Rust製コードエディター「Zed」がLinuxにようやく対応
Windowsサポートにも期待

ttps://forest.watch.impress.co.jp/docs/news/1607906.html

800 名前:デフォルトの名無しさん [2024/07/12(金) 20:23:46.34 ID:0tYdINiS.net]
個人利用は無償 ~JetBrainsがRust向けIDE「RustRover」を一般公開
メモリ安全性を保障したプログラミング言語「Rust」の開発に特化した統合開発環境

ttps://forest.watch.impress.co.jp/docs/news/1607747.html

801 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 20:46:42.78 ID:KyXC0KGT.net]
別口を用意するとは?
RustらしくないRustを用意することかな

もし日本語らしくない日本語が何か成果を出したら
日本語らしさを学習したAIに都合が悪い

802 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 21:35:52.40 ID:VV8L6PZC.net]
>>784
慣れの問題なんだろうけど
vscodeがいい…

803 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 22:05:28.85 ID:LuKbokrL.net]
>>785
参照カウンタ等がその別口
逆に聞くけど全てを参照カウンタで書かないのはなぜ?

804 名前:デフォルトの名無しさん [2024/07/12(金) 22:12:50.70 ID:VeLgD+zy.net]
>>781
RcやBoxは分かりやすいけどStringやVecも動的確保だよね、ということに気付いてない人もいるかも?

Rustが良いのはムーブが基本なおかげで意図

805 名前:せぬメモリコピーが起きないこと
所有権を他に渡す (ある構造体から別の構造体にか、あるコンテナから別のコンテナにとか移動する) 際にコストが発生しない
C++は逆で明示的に move しないと意図せぬコピーが起こる
[]
[ここ壊れてます]



806 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 22:30:09.43 ID:KyXC0KGT.net]
>>787
強制されてないから
嫌なら使わなければいい

807 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 22:37:23.69 ID:LuKbokrL.net]
電気電子板の人が、Rustの特集やってるインターフェース誌を買って読んだけどわからんかったって言ってたよ

808 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 22:52:07.26 ID:LuKbokrL.net]
>>789
俺はそんなことしないよ
全てを参照カウンタなんて使わずに書かない理由を探る

809 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 23:03:04.47 ID:IhFaP3QA.net]
>>787
C++で常にshared_ptrを使うと遅い
参照カウンタを利用しがちなSwiftやNimは遅い

810 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 23:08:24.73 ID:LuKbokrL.net]
参照カウンタ自体は全然新しくない
Rustがそれを無くせない理由が知りたい

811 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 23:24:14.35 ID:LuKbokrL.net]
複数の所有者がいる場合に参照カウンタが有効なのは分かる
難しいのは循環参照
参照カウンタで何が書け、何しか書くべきでないか

812 名前:デフォルトの名無しさん [2024/07/12(金) 23:48:00.71 ID:VeLgD+zy.net]
>>793
メモリ安全性を提供するため
オブジェクトを共有するのに「所有権は1人だけが持ち、他はそれを参照する」仕組みだと、すでに実体が消えてるオブジェクトを参照する問題が起こり得る
Rustでは、そのようなオブジェクトは参照カウンター付き (RcやArc) にするか、ライフタイムにより「寿命の短いものが寿命の長いものを参照している」ことを示さない限りコンパイルが通らないようにすることで安全性を保証している

逆にC++は参照カウンターなしでも共有できるけど正しく実装しないとメモリ関連のバグを引き起こす
この手のバグはセキュリティの問題になり得る問題を特定しにくい等の厄介さがあるから、Rustはそれをコンパイル時にできる限り防ぐという考え

813 名前:デフォルトの名無しさん mailto:sage [2024/07/12(金) 23:56:48.21 ID:n+FrpY/U.net]
同一スレッド内の別タスクと共有する時にRcを使う
別スレッドや別スレッドになりうる別タスクと共有する時にArcを使う

814 名前:デフォルトの名無しさん [2024/07/13(土) 00:02:12.31 ID:mV5TIlCk.net]
親子関係のようなオブジェクト間で相互参照するならWeakを使う
これはRcやArcから作るもので、「メインの所有者とそれを弱参照する共有相手」の関係になる
Weak側は相手がまだ存在することを確認できないと参照できないというもの

815 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 00:46:50.81 ID:UG7jOJ2R.net]
Rust の所有権システムは機械的に静的検証が可能なように設計されている。
しかし Rust のルールでの機械的静的検証で安全だと確信できないが実際には安全というケースは
ごく普通にあり、その内の典型的なものは実行時のチェックで補えるようにライブラリが整備されている。



816 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 02:23:43.98 ID:k/Plwdnm.net]
>>787
全てをRcで扱って渡すときはRcをclone()して渡せばライフタイムを気にしなくて済むが
参照カウンタとその増減のオーバーヘッドだけでなく
書き換えたいなら内部可変性を持ちそのオーバーヘッドも加わるとともに
スタック上で済むときも必ずヒープ利用となるオーバーヘッドもある

817 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 08:49:12.36 ID:zzh5ASvo.net]
zennとかqiitaとかのrust記事みてると
活発に描いてた人は2019-2022くらいで
その後更新されてないのが多い
みんな試しただけで使ってないのか

818 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 08:51:48.91 ID:zzh5ASvo.net]
>>784
いくつものバージョンのrustやそのバージョン用のcratesを
それぞれ独立に管理して切り替えて使える統合環境なら嬉しいな
venvみたいな

819 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 08:54:10.60 ID:zzh5ASvo.net]
>>788
>Rustが良いのはムーブが基本なおかげで意図せぬメモリコピーが起きない

doubt

820 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 08:56:33.88 ID:zzh5ASvo.net]
>>790
特集のRustは知らんけど
特集じゃなかったときのインターフェースで紹介されたRustは
(インターフェース誌の読者に多いであろう)C言語利用者に判り易く説明されていた
そういうスタンスだからC知らん人にはきついのかも

821 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 08:58:41.51 ID:zzh5ASvo.net]
>>793
無くせない訳じゃなくて
参照カウンタを使わない描き方は今でも充分過ぎるほど可能
特に純粋な関数型言語を使ったことのある人は後者の方が得意だろう

822 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 09:03:05.94 ID:UG7jOJ2R.net]
ムーブは管理上の概念で、低レイヤではコピーしてる。
Rust のムーブはカスタマイズの余地なくコピーする (最適化で消えることはある) が C++ のムーブはカスタマイズの余地 (ムーブコンストラクタの定義) があるので効率の面から考えると Rust のほうがよいとは言えない。

823 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 09:29:23.45 ID:+smP1Ssu.net]
>>801
venvはないわー
cargoやrustupだけでずっと簡単に管理できる
IDEをそれらをGUIから活用するだけ

824 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 09:38:04.64 ID:4hBdJvP4.net]
コマンドプロンプトを無くせない理由を考え続けているそこのあなた
まあいいじゃんそういうの

825 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 09:38:06.14 ID:OKewYK0N.net]
>>800
当時記事書いてた一人だけど、日本語書籍も増えたしいまさら書くことないんだよね
アドベントカレンダーがあるならネタ考えるか、くらい
自分はまだRust使ってるし、当時記事書いてた人たちもRust使ってるベンチャーとかに転職してて、だいたいみんな書いてるんじゃないかな



826 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 10:09:47.61 ID:aKeOI53x.net]
Rustはカンファレンスとか見てても最近は成熟したからなのか特に目新しいものはない気がする

827 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 10:11:38.51 ID:CU8fyG8D.net]
vscodeにできてjetbrains製ideにできないことってある?
正直jetbrainsのヤツのほうがvscodeより使いやすい

828 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 10:27:13.13 ID:E2vTTaV1.net]
JetBrains製品は金払ってまで使うほどVSCodeより優れてるわけでないだけで良いIDEではある
VSCodeを何故使うかは商用利用無料だからに尽きるんだわ

829 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 10:59:18.93 ID:SqKWY/h6.net]
>>767 >>768
>traitが実装される具体的な型は全てsubtypeに相当する兄弟同士であるため
>supertrait/subtraitの場合に例えばある構造体についてそのインスタンスはどちらも同一になるから
どちらも同じ勘違いをしてるよ
よく読もうね

What is wanted here is something like the following substitution property:
If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T,
the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T

830 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 11:00:31.54 ID:l6/BNZgQ.net]
仮にfleetが商用無料になるなら喜んでvscodeを捨てるけど金にがめついjetbrainsが商用無料で配るなんてありえない話
javaやkotlinならともかくrustなら商用無料のvscodeで十分

831 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 11:14:27.08 ID:3n/3tOrD.net]
>>812
そこでRustの場合はTがトレイトでSが構造体などの各型で
「impl T for S 」とS型にトレイトTを実装して
「let o1: S = ...」がS型の値(=オブジェクト)になる
『object o1 of type S』 ←存在する
『object o2 of type T』 ←存在しない
したがってRustのトレイトはLSPとなんら関係がない

832 名前:デフォルトの名無しさん [2024/07/13(土) 11:36:15.00 ID:mV5TIlCk.net]
よく分からんけど
fn do_somethg(x: impl T)
にS型のオブジェクトoを渡すなら、do_somethingにとって o is T が成り立つんじゃない?
この関数は渡された o が S1 なのか S2 なのかは認識しないのだし

833 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 11:44:56.49 ID:4Ly9sDTU.net]
>>815
fn foo(x: impl T)は単相化されて
fn foo(x: S1)と
fn foo(x: S2)の二つの関数になるんだよ
いずれにしてもxはS1の値かS2の値であって
Tの値は存在しないね

834 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 11:50:56.55 ID:6r0IzkzM.net]
>>813
さすがフリーライダー。
相手に対する敬意が毛ほども無い。

835 名前:デフォルトの名無しさん [2024/07/13(土) 11:54:54.91 ID:mV5TIlCk.net]
それはコンパイルのされ方の話であって意味の上での問題ではない気がする
Box<dyn T> なら動的ディスパッチされるわけだし
let x: T = ... のような変数を作れないという意味ならその通りだけど、それはオブジェクト指向言語におけるインターフェースでも同じでは
(それともインターフェースに対してLSPは成り立たない?)



836 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 12:02:36.42 ID:7b/8td6H.net]
>>812,814,816
なんで毎回飛んでレスするの?

837 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 12:09:19.16 ID:Zf2Y/4l2.net]
前も貼ったけどRustはこういうニーズを背負ってる

オブジェクト指向を学ばなかった話
https://qiita.com/adaiimps/items/e04ae03371435aeffe87

C++、ObjectiveC、JavaだったのがRust、LLVM、ELFになって、あーやっぱこっちの方が面白いねと、
好きも嫌いもなく色んな言語を学びまくってる人はLLVMは学ばないのかなと

838 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 12:15:08.95 ID:SXOx4oHh.net]
>>818
LSPでは「o1 of type S」と「o2 of type T」の二つのobjectの挙動を比較してるのよ
「o2」が存在しないと挙動の差を論じられないですよ

839 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 12:31:19.55 ID:IqeBToeS.net]
rust始めたけどtokioまわりの非同期処理が難しい…

840 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 12:34:40.11 ID:UG7jOJ2R.net]
置換原則に沿うかどうかは具体的な実装を検証しないとわからないし、大抵の場合に機械的に検証することは出来ない。
型をサブタイプの関係にするのは原則に沿う「ことにする」という表明になることはあるが、原則に沿うことの保証にはならんのだ。

841 名前:デフォルトの名無しさん [2024/07/13(土) 12:40:54.94 ID:mV5TIlCk.net]
>>821
>>812 を字義通りに解釈するならそうだけど、その文章はC#やJavaが登場する前の1988年のもので、現在のオブジェクト指向にそのまま適用して良いのか?と思う
インターフェースでない、実体のあるクラスの継承関係についてしか言えなくなるし

現在だとリスコフの置換原則は抽象インターフェースも含んで説明される方が多いように思う
「クラスを継承する際のみに適用できるルール」のように説明されてるのは、少なくとも自分は見たことがない

842 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 12:44:05.69 ID:Bid5yHc7.net]
お前らずっと同じ話をループさせてんな😅

843 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 12:51:22.30 ID:kEBSnfkM.net]
>>824
親(基底)と子(派生)の挙動の差で満たすべき条件をLSPは挙げてるよね
少なくとも親にも挙動(実装)が存在しないとLSPを満たしているかどうか言及できないと思う

844 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 13:43:19.43 ID:4hBdJvP4.net]
>>825
好き嫌いの感覚に素直に従えば面白味のないループはすぐ止まりそうなのに

845 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 13:52:54.97 ID:E+PNnzD+.net]
PartialOrd: PartialEqは
PartialEq(等価判定)を持つ型にPartialOrd(半順序判定)を追加するときに
a.partial_cmp(b) == Some(Ordering::Equal)

a.eq(b) (⇔ a == b)
が同じになることを期待してる

この場合の置換の対象は型のインスタンスではなく使われる型の関数だから
LSPをインスタンスの置換に限定するか処理の置換にまで拡張するかで結論が変わる

PartialOrdの追加はPartialEqを使ってる既存のコードに影響しないから
技術的にはLSPと無関係ともいえるし
PartialOrdとPartialEqの等価判定の互換性は概念的にLSPの対象とも考えられる



846 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 14:35:50.27 ID:MYuplL5h.net]
つまりRustのトレイトは
LSPの原義に従うと対象外となり
拡張して考えるとLSPを常に満たす
ことになるわけか

847 名前:デフォルトの名無しさん [2024/07/13(土) 15:25:32.20 ID:mV5TIlCk.net]
>>829
意味の上で考えるとしても「常に」は満たさないかと

struct MyString(String);
impl Clone for MyString {
 fn clone(&self) -> Self {
  Self("元の文字列と関係ない文字列".to_string())
 }
}

のようにすれば、そのトレイトが期待する動作に反した型は作れるわけで
引数や戻り値のシグニチャの同一性だけに注目するならtraitに違反することはできないけど、それなら継承やインタフェースでも同じで、「LSPに違反してはならない」という原則はそもそも意味がない (常に違反できないから) ってことになるし

848 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 15:38:58.70 ID:MYuplL5h.net]
>>830
それLSPのどの項目に違反してる?
LSPは振る舞いに関する形式的なものなのでそのような意味論にまでは踏み込んでいないよ

849 名前:デフォルトの名無しさん [2024/07/13(土) 15:50:29.46 ID:mV5TIlCk.net]
>>831
例えば
fn test_clone(x: impl Clone + PartialEq) {
 assert!(x.clone(), x);
}
はClone および PartialEq トレイトの振る舞いに依存したコードだけど、この振る舞いに反した型は作れるよね
トレイトは事後要件 (x.clone() == x) を定義できないし、そもそも Clone はそれを担保していないと主張することはできるけど、それならLPSって何のためにあるんだ?ってなるし

850 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 15:54:23.34 ID:4hBdJvP4.net]
「内在論理」に踏み込めば争いを解決できる説のようなものか
逆効果なのでは?

851 名前:デフォルトの名無しさん [2024/07/13(土) 15:55:51.56 ID:mV5TIlCk.net]
訂正
>>832 のアサート行は assert!(x.clone(), x) でなく assert!(x.clone() == x)

852 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 15:57:24.24 ID:UG7jOJ2R.net]
>>831
不変条件を弱められないルールだろう。
不変条件はシグネチャや定義域で表現できないものも含めた振る舞いの仕様全てのことで、挙動が (仕様に照らして) 望ましくなければ原則を満たさないと言える。

853 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 16:03:55.44 ID:E+PNnzD+.net]
829でPartialEq/PartialOrdを例に出したのは
この2つのtraitがsuper/subの関係にあるからで
Cloneとその実装型の関係とは別だよ
PartialEqとPartialOrdの等価判定についてのLSPを考えてる

PartialOrd: PartialEqとする以上
PartialOrdの比較はPartialEqの等価条件を保存すべき←LSP?
みたいな

854 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 16:10:18.20 ID:MYuplL5h.net]
>>836
確かにそちらの例は二つのトレイトがsuperとsubの関係だからLSPを満たしてるけど
>>830の例はLSPとは関係ないな

855 名前:デフォルトの名無しさん [2024/07/13(土) 17:43:27.19 ID:mV5TIlCk.net]
>>831
意味でなく形式に拘るなら「事後要件を弱めてはいけない」などのルールは、要件がプログラム等の形式で表現されない限りLSPの評価の土台にすら上がらないってことにならない?

Cloneトレイトは公式のドキュメントに

// Required method
fn clone(&self) -> Self;
Returns a copy of the value.

とあって、exampleでは実際に assert_eq を使って説明しているので、この説明を元にCloneトレイトを実装する型の妥当性を判断して良いように思う
これでもまだ「それは意味論上のものでしかない」というなら、逆にそれをクリアしてクラス間の振る舞いを示している現実的な例を教えてくれ



856 名前:デフォルトの名無しさん mailto:sage [2024/07/13(土) 22:57:22.69 ID:ZTGyFNne.net]
>>838
それは単純な例だから上手くいってるように思い込めるんじゃないかな
例えばclassの場合はもっと複雑な例になってもsuperclassのコードと挙動が実際にあり
それとsubclassの挙動や(必要なら)コードと照らし合わせて判定できるよ

しかしtraitにはそれがないからドキュメントや付加assertなど一段上のメタ情報を用いなければ何も進めることができない
したがってLSPの枠組みと似てる面はあっても別物

857 名前:デフォルトの名無しさん mailto:sage [2024/07/14(日) 04:00:15.58 ID:xmUtANA3.net]
知らんけど
JavaとかC#の世界でも、interfaceが実装者に要求する条件を実装者が実際には満たさない、って場合にLSP違反って言われるの?
ならRustのtraitでも同じこと言ってよさそうだけど、多分言わんよな

858 名前:デフォルトの名無しさん mailto:sage [2024/07/14(日) 05:23:41.72 ID:QaC7oPd0.net]
継承なしのカプセル化だけなら普通のC言語でもできるし、再コンパイルの問題(変更を加えたファイルだけを再コンパイルすればいいという原則の破れ)も発生しない
それがそのままライブラリやオブジェクトの単位になったんじゃないの

859 名前:デフォルトの名無しさん mailto:sage [2024/07/14(日) 06:49:30.82 ID:ma8dE8UE.net]
文系:xとは未知のもの
厨房:いや未知のものはyやろ
理系:未知のものはfですdf/dx=g(f)を解きます

860 名前:デフォルトの名無しさん mailto:sage [2024/07/14(日) 07:37:29.94 ID:iqWqiKXK.net]
>>841
Rustのtraitにはクラスのような継承はないけど、抽象的なコードを継承できるよ

861 名前:デフォルトの名無しさん mailto:sage [2024/07/14(日) 07:37:59.13 ID:iqWqiKXK.net]
例えばIteratorのtraitにはこのようにfoldメソッドのコードがあって

fn fold<B, F>(mut self, init: B, mut f: F) -> B
where
 Self: Sized,
 F: FnMut(B, Self::Item) -> B,
{
 let mut accum = init;
 while let Some(x) = self.next() {
  accum = f(accum, x);
 }
 accum
}

862 名前:デフォルトの名無しさん mailto:sage [2024/07/14(日) 07:39:51.02 ID:iqWqiKXK.net]
未知のIteratorであっても重複コードを書くことなく自動的にこのfoldメソッドが使える

863 名前:デフォルトの名無しさん mailto:sage [2024/07/14(日) 07:40:10.97 ID:iqWqiKXK.net]
クラスのメソッド継承との決定的な違いは、このコードにメンバー変数は一切登場せず、つまりいかなる構成の型からも独立した抽象的なコードであること

864 名前:デフォルトの名無しさん [2024/07/14(日) 09:23:36.10 ID:JssLuzWj.net]
fold って next とどうちがうん

865 名前:デフォルトの名無しさん [2024/07/14(日) 10:13:20.02 ID:aq5pPuoi.net]
>>847
nextはイテレーターを一つ進めるもの、foldやreduceはイテレーターに対して畳み込みを行うもの
例えば「配列内の全ての数値を足し合わせる」とか「全ての数値を掛け算する」「配列内の文字列を全て連結する」いった操作を行うものだよ

この類のものは他の言語でも使われるし、簡潔なコードを書けるようになるから知っておくと良いよ
配列等のコンテナに対して一般に map, filter, reduce と呼ばれる操作があって、そのうちreduceは「要素を畳み込んで1つの値にする」もの
畳み込む方法を関数で渡すもので、概念的には [1, 2, 3].reduce(add) や [1, 2, 3].reduce(multiply) のような形になる
渡す関数は関数のほかクロージャ (言語によってはラムダ式とも) も使える
こんな感じに抽象化するとfor文を使わなくて済むし、何をやってるかが明確になる



866 名前:デフォルトの名無しさん mailto:sage [2024/07/14(日) 10:32:15.39 ID:iqWqiKXK.net]
言語によって呼び名や使い分けが微妙に異なるけど
Rustでは2種類をこう呼び分けています
foldは初期値を別途指定する万能型の畳み込み
reduceは初期値が最初の要素となる畳み込み

867 名前:デフォルトの名無しさん mailto:sage [2024/07/14(日) 10:33:24.33 ID:iqWqiKXK.net]
そして万能型のfoldを呼び出す形で
このような特定の型の構造に依存しない抽象的なコードが
trait Iteratorに用意されているため使えます

fn reduce<F>(mut self, f: F) -> Option<Self::Item>
where
 Self: Sized,
 F: FnMut(Self::Item, Self::Item) -> Self::Item,
{
 let first = self.next()?;
 Some(self.fold(first, f))
}

868 名前:デフォルトの名無しさん mailto:sage [2024/07/14(日) 11:05:51.89 ID:iqWqiKXK.net]
なぜ二種類あるのか?と

869 名前:いうと
長さ0だと最初の要素すらないため
reduceはOption型が返る特徴があります

例えば和を求める場合でも
長さ0だったらNoneになってほしいならば
reduce(|sum, n: i32| sum + n)

長さ0なら和が0となってほしいならば
fold(0, |sum, n: i32| sum + n)

と使い分けることができます
ちなみに後者はsum()メソッドが用意されています
[]
[ここ壊れてます]

870 名前:デフォルトの名無しさん mailto:sage [2024/07/14(日) 11:33:51.37 ID:iqWqiKXK.net]
ごめんなさい
>>851で型指定「: i32」の部分は不要です
Iteratorの要素の型に必ず定まります
空配列[]から始めると型指定がどこにもないため横着してそこで指定しちゃったという顛末でした

871 名前:デフォルトの名無しさん mailto:sage [2024/07/14(日) 12:47:51.97 ID:JssLuzWj.net]
>>822
tokio 自体は難しくないけど
cargo test と組み合わせると難しくなる罠

872 名前:デフォルトの名無しさん [2024/07/14(日) 12:50:40.22 ID:JssLuzWj.net]
>>848
map も reduce も filter も知ってるけど(pythonとかから)
fold は知らんかった?楠

873 名前:デフォルトの名無しさん mailto:sage [2024/07/14(日) 12:54:55.73 ID:JssLuzWj.net]
>>850
python の reduce は初期値を [0] にするのも任意に設定するのも
同じ reduce という名前でいけるのが
Rust だと reduce と fold で使い分ける必要があるということね
Rust が面倒だと言うことは理解した

874 名前:デフォルトの名無しさん mailto:sage [2024/07/14(日) 13:21:58.79 ID:iqWqiKXK.net]
>>855
そういうことではないよ
RustではOption型やResult型でエラーや異常値を含めて正しい状況を値として得られるんだよ
例えば長さ0で初期値なしの時に
Pythonだとエラーだよね
Rustは常に値として返してくれて今回はOption<Self::Item>型

875 名前:デフォルトの名無しさん mailto:sage [2024/07/14(日) 14:06:11.77 ID:CpW1/GRz.net]
>>854
ML 系とか LISP 系の言語ではだいたい reduce や fold は用意されてるね。
ものによっては右側 (シーケンスの終端) から畳み込むとかのバリエーションもある。



876 名前:デフォルトの名無しさん mailto:sage [2024/07/14(日) 14:15:44.82 ID:iqWqiKXK.net]
Rustならrev().fold(...)だね

877 名前:デフォルトの名無しさん mailto:sage [2024/07/14(日) 15:28:53.80 ID:QaC7oPd0.net]
テンプレートが出てきたあたりからC++の勉強をやめたのだけど
これは「型を引数に取ってインスタンス化する」ということでおk?
それがトレイトをまたいだ場合、いつどこで誰が何してるか分からなくなる
ファイルをまたぐインライン関数みたいにソースレベルでなされること?

878 名前:デフォルトの名無しさん mailto:sage [2024/07/14(日) 16:59:00.63 ID:Q38o8Kq2.net]
>>840
JavaとかC#の世界でも、interfaceが実装者に要求する条件を実装者が実際には満たさない、って場合にLSP違反って言われるの?
言われるよ
リスコフ本人が書いたJavaの本にも書いてある

879 名前:デフォルトの名無しさん mailto:sage [2024/07/14(日) 17:32:49.60 ID:Q38o8Kq2.net]
>>839
>ドキュメントや付加assertなど一段上のメタ情報を用いなければ何も進めることができない
一段上のメタ情報であるspecificaitonを使いなさいというのがリスコフの教え
それがBehavioral SubtypingってものでLSPが伝えようとしてる原則だよ

880 名前:デフォルトの名無しさん mailto:sage [2024/07/14(日) 20:15:07.35 ID:QaC7oPd0.net]
ああ、なんだ
クレート=ELFファイルだと思ってたけど違うのね

881 名前:デフォルトの名無しさん mailto:sage [2024/07/14(日) 23:33:04.31 ID:jL63bGYb.net]
もちろんクレートはコンパイルしてELFに出来得る

882 名前: 警備員[Lv.12] mailto:sage釣 [2024/07/15(月) 00:49:06.25 ID:iuOQZB5q.net]
そうかCOFFあかんか。
AIXとかはどうするんだろう?

883 名前:デフォルトの名無しさん mailto:sage [2024/07/15(月) 01:06:24.34 ID:qZQFNGwo.net]
LLVMのバックエンドにCOFFもあるよ

884 名前:デフォルトの名無しさん mailto:sage [2024/07/15(月) 01:09:28.33 ID:RXziJOxB.net]
LLVMの役割
ELFもCOFFもXCOFFもいける

885 名前:デフォルトの名無しさん mailto:sage [2024/07/15(月) 01:55:53.37 ID:S6UfnUI4.net]
>>860-861
なるほどね、本当に特定の言語処理系の型システムの実装が云々というところからは離れたところにある概念なんだ
あえて関連付けるなら、型システムの部分型付け関係がbehavioral subtypingにもなるように定義すべきであると
上位型が具体型であるために暗黙の条件が多数想定される状況では特にLSPを意識すべきだが、それに限定される概念ではないと



886 名前:デフォルトの名無しさん mailto:sage [2024/07/15(月) 02:35:13.63 ID:fmM+TfOR.net]
supertypeの実装がない場合は
LSPの不変条件・事前条件・事後条件などsubtypeの実装と比較しようがなく
LSPの対象になりようがないよね

887 名前:デフォルトの名無しさん [2024/07/15(月) 03:42:20.85 ID:csp8v2ux.net]
docs.rs の左上のRマーク
今話題のRen4のマークに似てるね

888 名前:デフォルトの名無しさん [2024/07/15(月) 09:46:03.12 ID:kpV4D65H.net]
コレクションしないんだから狭義には参照カウンタはGCとは言えない。
広義には含めてやってもいいが。

889 名前:デフォルトの名無しさん mailto:sage [2024/07/15(月) 11:20:28.28 ID:qZQFNGwo.net]
ライブラリは.rlibまたは.rmetaで、これもELFやCOFFとは別物
ふむ

890 名前: 警備員[Lv.1][新芽] [2024/07/15(月) 11:29:04.89 ID:omk2e105.net]
たしかにRマークってRustから周りのやつ外したような感じじゃん

891 名前:デフォルトの名無しさん mailto:sage [2024/07/15(月) 11:58:24.83 ID:K85WsTqt.net]
Ren4のRマークはsans-serifのゴシック体だからRustのロゴとは全然違うだろ
本人のやる気、こだわりのなさをフォントで表現してるんだから
RustのRと一緒にしたら双方に失礼

892 名前:デフォルトの名無しさん mailto:sage [2024/07/15(月) 13:14:40.10 ID:ZO/EZAih.net]
単に好みの問題だけど
ウィルスっぽくて気持ち悪い
好きじゃない

893 名前:デフォルトの名無しさん [2024/07/15(月) 14:14:44.43 ID:ko+PCaVU.net]
>>874
元々サビ菌がモチーフやからしゃーない

894 名前:デフォルトの名無しさん mailto:sage [2024/07/15(月) 18:49:44.14 ID:GgRIn2WF.net]
独裁者にも見た目がダサい奴がよくいるけど言っても無駄だ
デザインの力とは全然違う別の力でねじ伏せてくる

895 名前:デフォルトの名無しさん [2024/07/15(月) 19:16:07.61 ID:Vjas5sQD.net]
ダサいという指摘に理由を説明しても、ダサいことは変わらないんだよな
言語がダサければ信者もダサい
うだうだ言いながらダサい服着てそう



896 名前:デフォルトの名無しさん mailto:sage [2024/07/15(月) 22:03:42.65 ID:e+J3OGv0.net]
イテレータ要素をヒープに格納するにはこれでいいんか
.fold(Vec::new(), |mut v, t| { v.push(t); v })

897 名前:デフォルトの名無しさん mailto:sage [2024/07/15(月) 22:12:32.29 ID:S6UfnUI4.net]
またイテレータの話してる

898 名前:デフォルトの名無しさん mailto:sage [2024/07/15(月) 22:50:12.36 ID:9YaXaz6n.net]
>>878
collectしろや

899 名前:デフォルトの名無しさん [2024/07/15(月) 23:25:29.58 ID:wT4qVw/w.net]
>>878
分かって書いてるかもだけど一応
let v = (0..10).collect::<Vec<i32>>();
コンテナにまとめるならこんな感じに collect を使う
例えば文字を走査するイテレーターをStringにcollectするようなことも可

型パラメーターは推論が効くのでそれに任せても良い
左辺に情報があるならcollectの型パラメーターはいらない
let v: Vec<i32> = (0..10).collect();
要素の型が分かるなら、右辺のコンテナの中身は_で推論させても良い
let v = (0i32..10).collect::<Vec<_>>();

900 名前:デフォルトの名無しさん mailto:sage [2024/07/15(月) 23:35:20.09 ID:nug4GWMJ.net]
クロージャにキャプチャさせれば既存ベクタへ格納も追加もできる
let mut v = Vec::new();
iter.fold((), |_, t| v.push(t));
しかしこれではfold使ってる意味がなくこれと一緒 
iter.for_each(|t| v.push(t));

もちろん正解は既存Vecへ追加なら
v.extend(iter);
新規にVecへ収集なら
let v = iter.collect::<Vec<_>>();

901 名前:デフォルトの名無しさん mailto:sage [2024/07/16(火) 23:25:36.51 ID:ab19AXDr.net]
Foo::from_iter(iter)でもいいね
例えばVec::from_iter(iter)
特にIntoIteratorな時にinto_iter()を省けて見やすいよ

902 名前:デフォルトの名無しさん mailto:sage [2024/07/17(水) 18:51:22.39 ID:Hw1cPZyQ.net]
イテレータをcollectしたい場合と
イテレータではないIntoIteratorを別の構造体に変換したい場合とは文脈が違うでしょ

from_iterを直接呼ぶのは基本的に後者
前者の場合にターボフィッシュ書かなくてもいいという理由で
from_iterを直接呼ぶのはidiomaticではない

903 名前:デフォルトの名無しさん mailto:sage [2024/07/17(水) 21:48:43.22 ID:3eay5eeN.net]
前者のケースでfrom_iterを直接呼んでても分かるから別にいいよ
自分で書くときはcollect使うけど

904 名前:デフォルトの名無しさん mailto:sage [2024/07/17(水) 23:54:54.61 ID:zgRAxdKk.net]
これは短い方がいい
let x = HashMap::<_, _>::from_iter(vec);
let x = vec.into_iter().collect::<HashMap::<_, _>>();

905 名前:デフォルトの名無しさん mailto:sage [2024/07/17(水) 23:55:29.92 ID:zgRAxdKk.net]
これはほぼ長さ変わらないからどちらがわかりやすいか
let x = HashMap::<_, _>::from_iter(iter);
let x = iter.collect::<HashMap::<_, _>>();



906 名前:デフォルトの名無しさん mailto:sage [2024/07/18(木) 01:10:31.87 ID:CNIyJc+8.net]
どちらも一度変数で受ける形になるので型アノテーションが必要なら
let x: HashMap<_, _> のように基本的には左辺に書く

HashMapなら型パラメータ部分も推論に頼らず
明示的に書くことのほうが多いかもしれない

イテレータをcollectしたい場合というのは
イテレータのメソッドチェーンで各種処理をしてから
最終的にcollectする形になることが多いから
from_iterの直呼びじゃなくcollectが好まれる

907 名前:デフォルトの名無しさん mailto:sage [2024/07/18(木) 02:40:28.19 ID:0QBRSK+b.net]
ところでchronoって、しょっちゅうAPIが変わるし
やたら冗長な書き方になるし結構クソじゃない?

908 名前:デフォルトの名無しさん mailto:sage [2024/07/18(木) 12:05:40.95 ID:WL/aeG4d.net]
書き方が気に入らないならtime-rsを試してみたら?

909 名前:デフォルトの名無しさん mailto:sage [2024/07/18(木) 21:07:48.37 ID:2m7Ost/Q.net]
なるほど

trait Iterator {
 type Item;
 
 fn collect<B: FromIterator<Self::Item>>(self) -> B
 where
  Self: Sized,
 {
  FromIterator::from_iter(self)
 }
}

910 名前:デフォルトの名無しさん mailto:sage [2024/07/18(木) 23:31:33.62 ID:GQ1B8wHA.net]
代数的データ型ってなんかすごいけど知名度がモナドより低いな

911 名前:デフォルトの名無しさん mailto:sage [2024/07/19(金) 02:03:52.09 ID:MUvBupZH.net]
>>890
使ってみたけど、time-rsいいね
いつのまにかダウンロード数でchronoを上回る競合があったとは知らんかった
タイムゾーンの扱いがやや簡略化されてるけど、夏時間のない日本人的には問題ない
月を直接intで指定できないのが英語仕様やな……ってちょっと気になる

912 名前:デフォルトの名無しさん mailto:sage [2024/07/19(金) 03:51:08.70 ID:riLGg6QV.net]
>>891
この各収納先への移譲と両側のトレイト境界が汎用化の肝
trait FromIterator<A>: Sized {
 fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self;
}

913 名前:デフォルトの名無しさん mailto:sage [2024/07/19(金) 06:06:24.35 ID:LryDU6eW.net]
Rustはジェネリックとトレイト境界と抽象的なデフォルト実装のおかげで
安全で利便性の高いコードの汎用共通化に成功していますね

914 名前:デフォルトの名無しさん [2024/07/19(金) 23:21:36.34 ID:rC6z5NUh.net]
cloud strike のはテロルやね

915 名前:デフォルトの名無しさん [2024/07/19(金) 23:30:11.35 ID:rC6z5NUh.net]
>>886
let x; HashMap::<_, _> = vec.try_into()?;

>>889
+1



916 名前:デフォルトの名無しさん mailto:sage [2024/07/19(金) 23:52:20.75 ID:8WlCJE3Q.net]
>>897
エラーとなりますた

917 名前:デフォルトの名無しさん mailto:sage [2024/07/20(土) 00:12:48.41 ID:bNknJoN/.net]
>>896
ウィルスバスター以来の快挙やね

918 名前:デフォルトの名無しさん mailto:sage [2024/07/20(土) 14:16:49.05 ID:F167yFzL.net]
>>898
; が : の間違いかな

>>899
暴落予想
note.com/asset_n_ichi/n/nceaa6f318b1e

919 名前:デフォルトの名無しさん mailto:sage [2024/07/20(土) 23:38:20.92 ID:6EAP68vq.net]
>>897
HashMapとVecにTryFromが実装されていないから無理
FromIteratorが実装されているのでそれを使う

920 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 01:48:23.56 ID:eUhj6//q.net]
★┷┓
┃D┃
┃D┃
┃K┃
┃で┃
┃も┃
┃r┃
┃u┃
┃s┃
┃t┃
┃が┃
┃使┃
┃え┃
┃ま┃
┃す┃
┃よ┃
┃う┃
┃に┃
┗━★

921 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 09:43:03.00 ID:QhoywuRk.net]
>>901
こういうのが「Rustは学習コストが高い」って言われる原因なんだろうな
答えを知ってる人は判ってても答えを知らない人は判らない
答えを調べるのにコストがかかりすぎる

922 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 10:14:17.60 ID:TGGT0XLq.net]
とあるライブラリに変な癖があるという話は
どの言語でもあるからそういう話ではないだろ

923 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 10:29:10.85 ID:U3c7smqS.net]
イテレータ使ったことない

924 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 10:35:28.58 ID:W0nR4Dwz.net]
>>903
Rustはその点シンプルでクセもなく覚えやすい

基本的に複数の要素ならFromIterator
VecでもHashMapでも何でもいける
複数のcharやstrなどからString作成もいける
複数のstrやStringやPathなどからPathBuf作成もいける

Fromは基本的に単独要素や配列(=静的固定長)から他へ変換

925 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 11:03:59.33 ID:BMrg5vDt.net]
>>903
>>897のはコンパイルエラーの内容が読めればすぐわかる
エラーの内容が読める程度の基礎力は最初に勉強して身につける必要がある
そもそもtry_intoでどういうケースならエラーにして欲しいのか考えればおかしいことに気付く

サードパーティライブラリの学習コストは他の言語に比べると顕著に高いが
基本的な言語機能や標準ライブラリは言うほど高くない
JavaやC#あたりと比べるとむしろ学習コスト低いんじゃないかと思う



926 名前:デフォルトの名無しさん [2024/07/21(日) 11:04:04.35 ID:xuKRyHnL.net]
>>903
それくらいchatGPTで教えてもらえるだろ

927 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 11:14:46.17 ID:BMrg5vDt.net]
>>908
俺もそう思って試してみたけど駄目だね
エラーの簡単な原因とcollect使えみたいな代替案は出してくるけど
根本的な理解につながる答えを返せないだけでなくいろいろと間違った情報を返してくる

928 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 11:48:09.12 ID:W0nR4Dwz.net]
from_iter(array)で済むのに
なぜ配列からHashMapへのFromがあるのか理由はおそらく
配列からmoveするinto_iter()が数年前までなかったためだと思う
今は配列を含めて要素が複数なら→イテレータ利用→FromIteratorと覚えればよいかと

929 名前:デフォルトの名無しさん [2024/07/21(日) 11:54:05.33 ID:9I2odrUJ.net]
そもそもイテレーターとコンテナの概念を勘違いしてる可能性ありそう
別種のコンテナ同士の変換は (特別な対応がない限り) 直接的には無理で、イテレーターを介して中身の要素を走査すれば渡せるということ

みかん箱を冷蔵庫に変換することはできないけど、箱の中のみかんを1つずつ取り出して、それを冷蔵庫型に纏める (collect) ことはできるような感じ

930 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 12:08:53.38 ID:QhoywuRk.net]
今回は >>910 さんをベストアンサーとさせて頂きます
みなさんご協力ありがとうございました

931 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 12:17:32.86 ID:rbHgMj6q.net]
>>911
それは単に抽象度の違いであって勘違いでも何でもない

932 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 12:17:32.92 ID:QhoywuRk.net]
>>911
勘違いはしてない

use std::collections::HashMap;
use std::iter::FromIterator;

fn main() {
let u = vec![("hoge", 1), ("fuga", 2)];
let x: HashMap::<_, _> = u.into_iter().collect();
println!("{:?}", x);
let v = vec![("hoge", 1), ("fuga", 2)];
let y = HashMap::<_, _>::from_iter(v); // use std::iter::FromIterator
println!("{:?}", y);
let w = [("hoge", 1), ("fuga", 2)]; // array
let z = HashMap::<_, _>::from(w);
println!("{:?}", z);
}

933 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 12:21:47.94 ID:QhoywuRk.net]
なぜ Vec から HashMap は from が使えないのか?
の問いに GPT は答えてくれない

934 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 12:29:53.31 ID:+gih9iRs.net]
>>910
順番が逆
arrayにIntoIteratorが実装された方が先で
From array for HashMapのほうが後

935 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 12:32:17.29 ID:BMrg5vDt.net]
>>915
そこはFromのimplがないからと答えてくれる
coherenceの制約を先回りして答えてくれるかどうかは質問次第



936 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 13:57:28.77 ID:W0nR4Dwz.net]
>>916
ありがと
調べたらその順だね
そうなるとFrom<配列>だけを特別に用意した理由は配列が基本型だからだろうか
HashMap::from(array)のコードを見ると
HashMap::from_iter(array)とFromIteratorの実装を呼び出すだけなので

937 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 16:06:46.61 ID:nMuf3u03.net]
MapやSetのリテラルがないけどリテラルに近い感覚で初期化したい場合の代替策として用意されたのがFromの実装

938 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 16:20:17.13 ID:BJsLblxy.net]
_iterの5文字が節約できるメリットだけか

939 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 16:39:36.83 ID:u5tRysNp.net]
>>920
タイプアノテーションの要不要があるのでもっと節約できるよ

940 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 16:43:19.24 ID:BJsLblxy.net]
>>921
不要になる例を出して

941 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 17:05:45.63 ID:QAZ3DYjh.net]
FromがあるとIntoが使えるからHashMap返すときとか引数で渡すときに
HashMap::from([..])
の代わりに
[..].into()
で書ける

型を明記するletだと大差ないかも
let map: HashMap<K, V> = [..].into();
let map = HashMap::<K, V>::from([..]);

942 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 17:22:33.98 ID:BJsLblxy.net]
>>923
そこでタイプアノテーションが不要になる例はないよな
関数の引数型か返り型に書いている

into()と書ける件も
collect()と書けるから
FromIteratorに対してFromもあるメリットは3文字節約できるだけか

943 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 21:02:32.72 ID:eUhj6//q.net]
dyn traits以外にinto使うなよ。変換するんだから

let s = "Hello, world!";
let string = Into::<String>::into(s);

じゃなくて

let s = "Hello, world!";
let string = String::form(s);

だろ。

944 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 21:07:32.49 ID:BUmQiTHC.net]
は?

945 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 22:10:59.79 ID:kEjkNYpd.net]
>>922
use std::collections::HashMap;

fn main() {
let xs = [(1, "a"), (2, "b"), (3, "c")];
let map = HashMap::from(xs);
println!("{:?}", map);
}



946 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 22:23:54.17 ID:vNf5wQaP.net]
>>927
HashMap::from_iter(xs)で十分じゃね

947 名前:デフォルトの名無しさん mailto:sage [2024/07/21(日) 22:30:45.10 ID:kEjkNYpd.net]
>>928
error[E0283]: type annotations needed for `HashMap<i32, &str, _>`
--> src/main.rs:5:9
|
5 | let map = HashMap::from_iter(xs);
| ^^^ ------- type must be known at this point
|

948 名前:デフォルトの名無しさん mailto:sage [2024/07/22(月) 12:16:14.88 ID:7a9cZObY.net]
配列からのFromは機能が制限されている
struct HashMap<K, V, S = RandomState> { ... }
impl<K: Eq + Hash, V, S: BuildHasher + Default> FromIterator<(K, V)> for HashMap<K, V, S> { ... }
impl<K: Eq + Hash, V, const N: usize> From<[(K, V); N]> for HashMap<K, V, RandomState> { ... }

949 名前:デフォルトの名無しさん mailto:sage [2024/07/22(月) 12:18:01.98 ID:7a9cZObY.net]
つまりFromは重いデフォルトハッシャーに固定されてしまっている
FromIteratorを使えば自由に速いものを利用できる
let xxx = HashMap::<_, _, FxHash>::from_iter(array);

950 名前:デフォルトの名無しさん mailto:sage [2024/07/23(火) 01:07:15.84 ID:XvQFw5Nb.net]
HashMap::from(配列)の場合は
デフォルトハッシャーで困るユースケースは稀だから
APIのエルゴノミクスのために意図的にRandomStateに固定してる
そのおかけでタイプアノテーションなしで書ける

タイプアノテーション無しの場合はデフォルト指定の型を優先的に使うよう
Rustのコンパイラが改良されればこの辺の差はなくなる

951 名前:デフォルトの名無しさん mailto:sage [2024/07/23(火) 01:10:26.97 ID:XvQFw5Nb.net]
>>931
>let xxx = HashMap::<_, _, FxHash>::from_iter(array);
FxHashのところはFxBuildHasherだね
let xxx = FxHashMap::from_iter(array);と書いたほうがいろいろ親切

親切設計のライブラリなら
let xxx = AHashMap::from(array);
のようにFromIteratorだけでなくFromも使える

952 名前:デフォルトの名無しさん [2024/07/23(火) 01:31:49.01 ID:Rfg4Mjqa.net]
tupleをiteratorしたいんだが無理?

953 名前:デフォルトの名無しさん mailto:sage [2024/07/23(火) 02:50:50.92 ID:l+hNtTPE.net]
こういう意味?
let t = ("abcde", "fghijkl", "mno", "pqrstuvw", "xyz");
assert_eq!("abcdefghijklmnopqrstuvwxyz", Into::<[_; 5]>::into(t).into_iter().collect::<String>());

954 名前:デフォルトの名無しさん mailto:sage [2024/07/23(火) 09:22:40.63 ID:iSDzXJU2.net]
同じ型だけの要素で構成されるtupleならいけそうだけど
色んな型ば混ざってるtupleはエラー出そう

955 名前:デフォルトの名無しさん mailto:sage [2024/07/23(火) 11:25:10.18 ID:ijWLrFq+.net]
dynにすれば色んな型を混ぜられる
関数から返すときはBox<dyn ...>にする
例えば数値と文字列が混じる有名な例をRustでdynを使って書くと

type FizzBuzz = Box<dyn std::fmt::Display>;

fn fizz_buzz_iter() -> impl Iterator<Item=FizzBuzz> {
 (1..).map(|int| match (int % 3, int % 5) {
  (0, 0) => Box::new("FizzBuzz") as FizzBuzz,
  (0, _) => Box::new("Fizz"),
  (_, 0) => Box::new("Buzz"),
  (_, _) => Box::new(int),
 })
}

fn main() {
 for x in fizz_buzz_iter().take(30) {
  println!("{x}");
 }
}



956 名前:デフォルトの名無しさん mailto:sage [2024/07/23(火) 17:24:06.93 ID:hqmWVJB3.net]
またFizzBuzzイテレータ書いてる……

957 名前:デフォルトの名無しさん [2024/07/23(火) 21:36:57.26 ID:1jhTJKzb.net]
>>936
Haskellだとタプルって構造体代わりだから、色んな型が混ざってる方が普通だけど…。
(ともすれば関数も入れるし。同じ型だけってのはリストのイメージ)

Rustじゃ用途違うん?

958 名前:デフォルトの名無しさん mailto:sage [2024/07/23(火) 21:58:12.50 ID:joaeWjir.net]
タプルは型の制限なくバラバラでいいよ
今回はそれを>>934「iteratorしたい」なので
同じ型に揃えるためにdynかenumを使う

959 名前:デフォルトの名無しさん mailto:sage [2024/07/23(火) 23:07:54.81 ID:tKFzmUCx.net]
ほとんどの言語でオブジェクトを返す時にヒープを使うから
RustでもBox<dyn>を使っても構わないけど
ライフタイムさえ満たしてやればヒープを使わずに&dynにできるよ

use std::fmt::Display;
type FizzBuzz<'a> = &'a dyn Display;

fn fizz_buzz_iter<'a, T: Display>(i: &'a[T], s: &'a[&str; 3]) -> impl Iterator<Item = FizzBuzz<'a>> {
 (1..).map_while(|int| match (int % 3, int % 5) {
  (0, 0) => Some(&s[0] as FizzBuzz),
  (0, _) => Some(&s[1]),
  (_, 0) => Some(&s[2]),
  (_, _) => i.get(int).map(|int| int as FizzBuzz),
 })
}

fn main() {
 let i: [_; 256] = std::array::from_fn(|i| i as u8);
 let s: [_; 3] = ["FizzBuzz", "Fizz", "Buzz"];
 for x in fizz_buzz_iter(&i, &s).take(30) {
  println!("{x}");
 }
}

960 名前:デフォルトの名無しさん [2024/07/23(火) 23:38:39.26 ID:QoNSkCmh.net]
「tupleでイテレートできないの?」という質問に「こういうイテレータなら異なる型を混ぜられるよ」と回答するあたりがいかにもな感じ
率直に「できる/できない」で回答した上で補足として書けばいいのに

961 名前:デフォルトの名無しさん mailto:sage [2024/07/23(火) 23:40:03.74 ID:38zrS1+w.net]
トレイトオブジェクトをdynと呼ぶのは複オジだけ

962 名前:デフォルトの名無しさん mailto:sage [2024/07/23(火) 23:40:30.32 ID:38zrS1+w.net]
>>942
それな

963 名前:デフォルトの名無しさん mailto:sage [2024/07/23(火) 23:49:18.56 ID:lLea54if.net]
Rust 2018 editionからdyn必須に変わった

964 名前:デフォルトの名無しさん mailto:sage [2024/07/24(水) 00:02:23.05 ID:QMkBbV1F.net]
できる/できないで言えばできるよ

タプルの要素がすべて同じ型で要素数が12個以内ならFrom/Intoで配列に変換してイテレートする
それ以外ならextension traitで自前のイテレータを返すメソッドをタプルに実装する
他にも方法あるけどこの2つが主

タプルの型・要素数、イテレート時の型を汎用化したい場合はマクロが必須でそこそこめんどくさい
特にヘテロなタプルを汎用的にイテレート用の型に揃えるのはめんどくさい

本当にタプルで管理するのが望ましいのか
タプルで管理しつつイテレータで回すのがベストなのか
まずはよく考えたほうがいいと思う

965 名前:デフォルトの名無しさん mailto:sage [2024/07/24(水) 00:15:33.28 ID:sAqPevwn.net]
dynを使えば型が何種類でもいけてトレイト境界も使えて楽だろうけどdynは重い
Fizz Buzzのように2種類の型で済むならEitherを使う
色んなトレイトを透過的に対応してくれている

use either::Either::{self, Left, Right};

type FizzBuzz = Either<usize, &'static str>;

fn fizz_buzz_iter() -> impl Iterator<Item = FizzBuzz> {
 (1..).map(|int| match (int % 3, int % 5) {
  (0, 0) => Right("FizzBuzz"),
  (0, _) => Right("Fizz"),
  (_, 0) => Right("Buzz"),
  (_, _) => Left(int),
 })
}



966 名前:デフォルトの名無しさん mailto:sage [2024/07/24(水) 00:35:21.34 ID:UKniupNy.net]
リフレクションのサポートとかにもっと力入れてれば普通にできるんだろうけど、しゃあなし
Rustはそういうの好かない言語だから

967 名前: 警備員[Lv.2][新芽] mailto:sage [2024/07/24(水) 00:44:54.58 ID:djH/Nw1D.net]
rustって流行るかな

968 名前:デフォルトの名無しさん [2024/07/24(水) 03:12:39.74 ID:s3z853Sv.net]
>>940
タプルをイテレーションしたい…。

リストとか、配列みたいに使いってことですよね?
Haskellでは無理ですが、Rustでは可能なのでしょうか?
(構造体代わりと言った通り、構造体をイテレーションしようと思わないですよね?)

Python,RubyのリストとHaskellのそれみたいに、そもそもの意味が違う可能性もありますし…。

969 名前:デフォルトの名無しさん [2024/07/24(水) 03:25:04.27 ID:sCVmnNU/.net]
>>935
let t = ("abcde", 123, "mno", "pqrstuvw", 456);
for e Into::<[_; 5]>::into(t).into_iter() {
println!("{:?}", e)
}
無理ポorz

970 名前:デフォルトの名無しさん [2024/07/24(水) 03:30:03.16 ID:sCVmnNU/.net]
>>946
それっぽいクレートがあるけどよう判らん
これはどんな感じ?
https://crates.io/crates/tuple-iter

971 名前:デフォルトの名無しさん mailto:sage [2024/07/24(水) 03:57:10.87 ID:yTLgnmif.net]
これは典型的なXY問題だから相手にするだけ無駄
質問者は本当に解決したい元の課題Xを素直に話すべき
自分の思い込みで勝手に判断して進めた二次的な課題Yについて質問しているからそれについては相手にしなくていい

972 名前:デフォルトの名無しさん mailto:sage [2024/07/24(水) 04:42:12.08 ID:sCVmnNU/.net]
>>946
imple IntoIterator for (&str, u64, &str, &str, u64) {
...
}
で出来るかと思ったけど
this is not defined in the current crate because tuples are always foreign

973 名前:デフォルトの名無しさん mailto:sage [2024/07/24(水) 05:38:42.31 ID:U0F2g2Py.net]
dynやenumにしろと本質的なアドバイスをもらえているのに対応しようとしない人

974 名前:デフォルトの名無しさん mailto:sage [2024/07/24(水) 07:25:15.81 ID:Py4dd1Kh.net]
たしかにXY問題だな
「異なる型が入り乱れてイテレートしたい」←何のために?
「異なる型が入り乱れてタプルがある」←どうやってそれが出来た?

975 名前:デフォルトの名無しさん [2024/07/24(水) 08:43:52.20 ID:NUYI7xpt.net]
・タプルは型を混合できる
・タプルはイテレートできない
・異なる型でのイテレートがしたいなら、タプルの代わりに Box<dyn Trait> のような動的型かenum (直和型) の配列を使う
で良いんじゃない?



976 名前:デフォルトの名無しさん mailto:sage [2024/07/24(水) 08:43:57.79 ID:sCVmnNU/.net]
とりあえず出来ました
struct Hoge<'a> { t: (&str, u64, &str, &str, u64) }

impl<'a> IntoIterator for Hoge<'a> {
type Item = Fuga<'a>;
type IntoIter = std::vec::IntoIter<Self::Item>;

fn into_iter(self) -> Self::IntoIter {
vec![
Fuga::from(self.t.0),
Fuga::from(self.t.1),
Fuga::from(self.t.2),
Fuga::from(self.t.3),
Fuga::from(self.t.4),
].into_iter()
}
}
みなさんありがとうございました

977 名前:デフォルトの名無しさん [2024/07/24(水) 08:50:34.05 ID:NUYI7xpt.net]
XY問題だとか言うけど、上のFizzBuzイテレーターなんかはXとYのどちらとも関係ないでしょ
既にあるデータに対してイテレートする方法でなく、FizzBuzを0から生成するだけだから
それをしつこく何度も書くあたりが本物

978 名前:デフォルトの名無しさん mailto:sage [2024/07/24(水) 09:24:46.95 ID:eaHzhPzb.net]
>>959
それな

979 名前:デフォルトの名無しさん mailto:sage [2024/07/24(水) 09:30:08.78 ID:+W2StRcH.net]
意味のないFizzBuzzを散々書いておいて答えられなくなったら急に質問者を攻撃する複オジくん草

980 名前:デフォルトの名無しさん mailto:sage [2024/07/24(水) 12:35:19.94 ID:qFVR7Ywl.net]
必要な個数のタプルを配列に変換するコードでいいんじゃないかな
これは長さ自由に機械的にマクロで生成できそう

struct Wrapper<A, B, C, D, E>((A, B, C, D, E));

impl<A, B, C, D, E> From<Wrapper<A, B, C, D, E>> for [Tx; 5]
where
 Tx: From<A> + From<B> + From<C> + From<D> + From<E>,
{
 fn from(x: Wrapper<A, B, C, D, E>) -> Self {
  [Tx::from(x.0.0), Tx::from(x.0.1), Tx::from(x.0.2), Tx::from(x.0.3), Tx::from(x.0.4)]
 }
}

impl<A, B, C, D, E> IntoIterator for Wrapper<A, B, C, D, E>
where
 Tx: From<A> + From<B> + From<C> + From<D> + From<E>,
{
 type Item = Tx;
 type IntoIter = std::array::IntoIter<Self::Item, 5>;
 
 fn into_iter(self) -> Self::IntoIter {
  let x: [Self::Item; 5] = self.into();
  x.into_iter

981 名前:()
 }
}
[]
[ここ壊れてます]

982 名前:デフォルトの名無しさん mailto:sage [2024/07/24(水) 12:36:33.67 ID:qFVR7Ywl.net]
あとはタプルに登場する型を列挙して
例えばこんなコードを機械的に自動生成させてしまえばいいね

type T1 = &'static str;
type T2 = i64;
type T3 = f64;

enum Tx { T1(T1), T2(T2), T3(T3), }

impl From<T1> for Tx { fn from(x: T1) -> Self { Self::T1(x) } }
impl From<T2> for Tx { fn from(x: T2) -> Self { Self::T2(x) } }
impl From<T3> for Tx { fn from(x: T3) -> Self { Self::T3(x) } }

impl std::fmt::Display for Tx {
 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
  match self {
   Self::T1(x) => write!(f, "{x}"),
   Self::T2(x) => write!(f, "{x}"),
   Self::T3(x) => write!(f, "{x}"),
  }
 }
}

983 名前:デフォルトの名無しさん mailto:sage [2024/07/24(水) 12:38:12.03 ID:qFVR7Ywl.net]
そうするとタプルの中の型の順番は任意でよくて
タプルをラッパーにかませるだけで利用できるよ

fn main() {
 let tuple = ("abcde", 123, "nop", 0.456, 789);
 for x in Wrapper(tuple) {
  println!("{x}");
 }
 for (i, x) in Wrapper((-1, "pi", 3, 3.14159, "END")).into_iter().enumerate() {
  println!("{i}: {x}");
 }
}

984 名前:デフォルトの名無しさん mailto:sage [2024/07/24(水) 12:43:52.56 ID:mjGiit/q.net]
効いてる効いてるw

985 名前:デフォルトの名無しさん mailto:sage [2024/07/24(水) 12:49:36.37 ID:TJmYfYAi.net]
「XY問題だから相手にするだけ無駄」と言い放っておいてからの〜〜



986 名前:デフォルトの名無しさん mailto:sage [2024/07/24(水) 17:04:11.48 ID:1Kw3Uuff.net]
もっと建設的な話題はないの?

987 名前:デフォルトの名無しさん mailto:sage [2024/07/24(水) 19:14:00.84 ID:UKniupNy.net]
5chより建設的なコミュニティを列挙し移住を検討するのが目下最も建設的な話題である

988 名前:デフォルトの名無しさん [2024/07/24(水) 21:00:33.77 ID:bzm5y73f.net]
最近出た便利クレートの話とかすれば良いんじゃね?

989 名前:デフォルトの名無しさん mailto:sage [2024/07/24(水) 22:25:44.31 ID:mF9Tvkg9.net]
ベストな日付処理クレートについて議論しよう

990 名前:デフォルトの名無しさん mailto:sage [2024/07/25(木) 08:45:26.25 ID:q/t9CUhu.net]
おすすめクレートの話はしてほしいな~

991 名前:デフォルトの名無しさん mailto:sage [2024/07/25(木) 10:09:56.78 ID:P+cFrEvf.net]
クレートの話をしてくれー、と

992 名前:デフォルトの名無しさん [2024/07/25(木) 22:41:22.06 ID:zdgCFOr2.net]
クレートではないけれど今日リリースのRust 1.80でLazyCell, LazyLockが安定版に入ったよ
グローバルな変数を外部クレート無しで書きやすくなる

993 名前:デフォルトの名無しさん mailto:sage [2024/07/25(木) 22:49:30.69 ID:9YYk7vP+.net]
>>973
それ、OnceCell使ってたコードは全部置き換えた方がいい奴?

994 名前:デフォルトの名無しさん [2024/07/25(木) 23:18:37.32 ID:zdgCFOr2.net]
>>974
自分はそれを言えるほど詳しくないけど、必ずしも必要ではないと思う
依存クレートを減らせる点で嬉しいし、今から書くコードでは新しいものにして良いと思うけど、今使ってるものをすぐに置き換える必要があるとまでは思わない
特にライブラリを作ってる場合は、rustcを今日リリースされたばかりの最新バージョンに上げないとライブラリをビルドできなくなるということなので、もう少し待った方が良いかもしれない

995 名前:デフォルトの名無しさん mailto:sage [2024/07/26(金) 00:25:09.02 ID:/65SSmn2.net]
OnceLockからLazyLockへ移行すると
変数宣言と初期化関数が離れていた可読性の問題が解決するとともに
例えばget_or_initを一箇所にするために一つ関数を用意したりするなどしていた手間も省けるようになるね
そして何よりも最大のメリットはDerefによりアクセスできる利便性



996 名前:デフォルトの名無しさん mailto:sage [2024/07/26(金) 23:32:15.42 ID:/65SSmn2.net]
とりあえず定番のこのあたりを置き換えた
static RE: LazyLock<Regex> = LazyLock::new(|| Regex::new("...").unwrap());
static SE: LazyLock<Selector> = LazyLock::new(|| Selector::parse("...").unwrap());

997 名前:デフォルトの名無しさん mailto:sage [2024/07/27(土) 11:02:49.38 ID:WfV9QQMJ.net]
LazyLockよさそうね

998 名前:デフォルトの名無しさん mailto:sage [2024/07/27(土) 18:38:25.11 ID:U5WpGSyZ.net]
俺の今日のハマりポイントを紹介

bindgenにC++のコンストラクタを作らせると、データが壊れる
よく調べたら公式ドキュメントのConstructor semanticsに書いてあった
https://rust-lang.github.io/rust-bindgen/cpp.html

コンストラクタを抜けたとき、C++とちがってRustは値をムーブしちゃうので
struct内部を参照したポインタが変なところを参照してバグる

999 名前:デフォルトの名無しさん [2024/07/27(土) 19:30:58.99 ID:s18eFGvS.net]
C++も部分的に使えるとはいえ、FFIするならCのAPIにしておく方が無難な気はする

1000 名前:デフォルトの名無しさん mailto:sage [2024/07/27(土) 20:04:50.53 ID:U5WpGSyZ.net]
>>980
bindgenはFirefoxがプロダクトでたくさん使ってるって聞いて、いけると思ったんだ
Firefoxは大半がC++だから

1001 名前:デフォルトの名無しさん [2024/07/28(日) 15:27:45.35 ID:v6kdbv5j.net]
>>978
LazyLockさようなら
に観えた

1002 名前:デフォルトの名無しさん mailto:sage [2024/07/28(日) 15:29:40.57 ID:v6kdbv5j.net]
>>979
RustとC++は相性最悪
RustとCは相性良いバッチリ

1003 名前:デフォルトの名無しさん mailto:sage [2024/07/30(火) 01:24:35.90 ID:xgbf/AIH.net]
>>979
この件って、RustはC++と比べて無駄にムーブするから遅いってこと?

1004 名前:デフォルトの名無しさん mailto:sage [2024/07/30(火) 06:04:09.29 ID:RHAjweCG.net]
無駄な移動は消える
cargo asmで生成コードを見ることでそれを確認できる
移動前と移動後のアドレスを表示させて最適化を阻害することで元は別々となる例も確認できる

1005 名前:デフォルトの名無しさん [2024/07/30(火) 12:06:12.26 ID:tiWzrJ23.net]
>>984

>コンストラクタを抜けたとき、C++とちがってRustは値をムーブしちゃうので
>struct内部を参照したポインタが変なところを参照してバグる

って書いてるのに、読解力無い人?



1006 名前:デフォルトの名無しさん mailto:sage [2024/07/30(火) 19:02:27.28 ID:dzXOiSL/.net]
>>985
移動じゃなくてムーブね
ここまでのレスで使われてる述語を踏襲すればいいよ

1007 名前:デフォルトの名無しさん mailto:sage [2024/07/30(火) 20:13:33.28 ID:VUdF4pDl.net]
>>985
最適化のかかり具合でバグが消えたり現れたりする嫌なパターンだな

1008 名前:デフォルトの名無しさん mailto:sage [2024/07/30(火) 20:41:43.84 ID:+5mpqNgW.net]
>>986
Rustを使えばそんなバグは起きない
参照のライフタイムは参照先より長くなることがコンパイル時点で保証される

>>988
Rustならばそこでバグは起きようがない

1009 名前:デフォルトの名無しさん [2024/07/30(火) 22:41:22.15 ID:GjQxUZ/0.net]
>>989
本人じゃないのに出しゃばらせて頂きますが…。

Rust単体じゃなくて、C++との相性問題ですよ。相性最悪って書いてるんだから。
起きようがないじゃなくて、実際に起きてるらしいじゃないですか。

最適化で治るのなら大したことじゃなくても、デバッグ時にハマるの確実な類のバグ。

将来的に全部Rustで書けば起きないような問題も、過渡期の今は良く起きます。

「Rustを使えば」「Rustなら」。
そうでしょうけど、実際問題ライブラリがなければ既存のC/C++ライブラリ使う場面は多々あるでしょう。
(枯れたライブラリならなおさら)

これはRustに限らず、後続の言語全てが抱えている問題です。

1010 名前:デフォルトの名無しさん [2024/07/30(火) 22:49:06.91 ID:MqLM+D1V.net]
最適化じゃなくて単に移動の問題
Box::newで要素を直接ヒープに作れない (いちどスタックに作られてからコピーされる) のと同じで、コンストラクタを抜ける前に構造体が maybeuninit::assume_init で移動する
その上で構造体のアドレスがC++のメソッドにthisポインタとして渡される際に問題を引き起こす、というように思える
だとすると最適化の有無は関係なく起こる気がする

ついでにいえば >>987 もあまり意味のない発言で、移動はムーブの訳語でもある (例えばC++の仕様の訳語に移動コンストラクタという表現がある) し、そもそもこの問題はムーブセマンティクスによるものでもない
これはStringやVecが持つリソースを所有権ごと移動することで効率的に別の変数に割り当てるもので、構造体のアドレスのようなローレベルなものとは違うかと

1011 名前:デフォルトの名無しさん [2024/07/30(火) 22:59:00.85 ID:MqLM+D1V.net]
移動とムーブが仕様として別物だというなら、移動は英語でどう表現されてるんだ?

1012 名前:デフォルトの名無しさん mailto:sage [2024/07/30(火) 23:00:06.83 ID:L/ylOhaJ.net]
>>990
それはRust単体では全く発生しない問題だね
C++とRustを併用する時にRustの知識を持たない人がハマるという話
FFI部分は両者の概念と挙動の違いの知識を持った人が作るべきだね

1013 名前:デフォルトの名無しさん mailto:sage [2024/07/30(火) 23:13:56.95 ID:EnloT7kO.net]
>>979
>>値をムーブしちゃうのでstruct内部を参照したポインタが変なところを参照してバグる

Rustでそのような自己参照はムーブでライフタイム切れとなるためバグは発生しなくて
自己参照を保ちたいならば値がムーブしなければよくて
値がムーブしないためにはスタック上でそのまま使うかヒープ上に確保して使えばよくて
それを保証するためにRustではPinという枠組みがあって安全に取り扱えるようになってるよ

1014 名前:デフォルトの名無しさん [2024/07/30(火) 23:19:18.00 ID:MqLM+D1V.net]
>>994
bindgenの作者に言ってあげればいいと思うよ
ついでに改善したコードをPRしてコントリビュートしてみてはどうだろう
使用者のミスを擦るよりもずっと有意義なはず

1015 名前:デフォルトの名無しさん [2024/07/30(火) 23:48:00.88 ID:dZ3/RfBM.net]
同意



1016 名前:デフォルトの名無しさん [2024/07/31(水) 11:32:49.64 ID:yHR2oE13.net]
結合が密過ぎないかこの言語

1017 名前:デフォルトの名無しさん [2024/07/31(水) 11:35:31.65 ID:yHR2oE13.net]
>将来的に全部Rustで書けば起きないような問題

さっさと仕事しろおまいらってことですね判ります

1018 名前:デフォルトの名無しさん [2024/07/31(水) 12:10:03.24 ID:yHR2oE13.net]
>>985
Pin

1019 名前:デフォルトの名無しさん [2024/07/31(水) 12:10:59.00 ID:yHR2oE13.net]
Pin<Arc<T>>

1020 名前:1001 [Over 1000 Thread ID:Thread.net]
このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 65日 5時間 29分 33秒

1021 名前:過去ログ ★ [[過去ログ]]
■ このスレッドは過去ログ倉庫に格納されています






[ 新着レスの取得/表示 (agate) ] / [ 携帯版 ]

前100 次100 最新50 [ このスレをブックマーク! 携帯に送る ] 2chのread.cgiへ
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧](;´∀`)<305KB

read.cgi ver5.27 [feat.BBS2 +1.6] / e.0.2 (02/09/03) / eucaly.net products.
担当:undef