公式
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/
探検
Rust part24
■ このスレッドは過去ログ倉庫に格納されています
2024/05/27(月) 06:41:26.82ID:T4AFD1f4
671デフォルトの名無しさん
2024/07/09(火) 12:31:29.17ID:B8U2Xwe0 >>664
対象となるものはクラスしかないよね
対象となるものはクラスしかないよね
672デフォルトの名無しさん
2024/07/09(火) 12:39:43.65ID:YflJELWV >>668
φ(x) を型 T のオブジェクト x に関して証明可能な性質とする。このとき、φ(y) は型 T のサブタイプ S のオブジェクト y について真でなければならない。
φは主に事前条件・事後条件・不変条件で、言語によっては例外条件も入ってくる。
この観点からはRustのTraitは力不足。なんでLSPを引き合いに出せるのかわからん。
φ(x) を型 T のオブジェクト x に関して証明可能な性質とする。このとき、φ(y) は型 T のサブタイプ S のオブジェクト y について真でなければならない。
φは主に事前条件・事後条件・不変条件で、言語によっては例外条件も入ってくる。
この観点からはRustのTraitは力不足。なんでLSPを引き合いに出せるのかわからん。
673デフォルトの名無しさん
2024/07/09(火) 12:57:46.02ID:aoAam1/W >>672
自分でそれを書いておいて理解できていないのかよ
そこに明記されてるようにTもSもオブジェクトを持つ具体型についての話だ
Rustのtraitは具体型ではないため関係ないぞ
そしてtraitを実装する各型の間にはサブタイプの関係はないためそこも対象とならない
そこを理解できずに「RustのTraitは力不足」とデタラメを吹聴するのは恥ずかしい
自分でそれを書いておいて理解できていないのかよ
そこに明記されてるようにTもSもオブジェクトを持つ具体型についての話だ
Rustのtraitは具体型ではないため関係ないぞ
そしてtraitを実装する各型の間にはサブタイプの関係はないためそこも対象とならない
そこを理解できずに「RustのTraitは力不足」とデタラメを吹聴するのは恥ずかしい
674デフォルトの名無しさん
2024/07/09(火) 13:01:26.64ID:YflJELWV >>673
事前条件とかはどこ行ったの?
事前条件とかはどこ行ったの?
675デフォルトの名無しさん
2024/07/09(火) 13:20:56.23ID:aoAam1/W >>674
φ(x) のxはオブジェクトと明記されてるのが見えないのかね
さらにSはTのサブタイプと明記されている
Rustのtrait自体はオブジェクトを持たない
さらにtraitを実装する二つの型同士にサブタイプの関係は生じない
つまり対象外でφが存在しないため事前条件も何もない
φ(x) のxはオブジェクトと明記されてるのが見えないのかね
さらにSはTのサブタイプと明記されている
Rustのtrait自体はオブジェクトを持たない
さらにtraitを実装する二つの型同士にサブタイプの関係は生じない
つまり対象外でφが存在しないため事前条件も何もない
676デフォルトの名無しさん
2024/07/09(火) 13:35:41.29ID:YflJELWV >>675
>明記されてるのが見えないのかね
>Rustのtrait自体はオブジェクトを持たない
それは「RustのTraitはLSPと関係ない」と言いたいの?
>φが存在しないため事前条件も何もない
事前条件も何も表明できないのは「力不足」そのものですな。
>明記されてるのが見えないのかね
>Rustのtrait自体はオブジェクトを持たない
それは「RustのTraitはLSPと関係ない」と言いたいの?
>φが存在しないため事前条件も何もない
事前条件も何も表明できないのは「力不足」そのものですな。
677デフォルトの名無しさん
2024/07/09(火) 14:43:14.46ID:Tc+iYmTn リファクタリングするとき
プログラム(CPU)の動作の副作用は起きないけど
コーディングの変更に対して副作用が大き過ぎるというか広過ぎる
プログラム(CPU)の動作の副作用は起きないけど
コーディングの変更に対して副作用が大き過ぎるというか広過ぎる
678デフォルトの名無しさん
2024/07/09(火) 15:17:32.29ID:l7dFkPpL679デフォルトの名無しさん
2024/07/09(火) 15:20:15.91ID:aoAam1/W >>676
LSPに明記されている前提すら満たさない異なるものであるため
「RustのTraitはLSPと関係ない」で合っている
LSPが対象としている遺物における諸問題に悩まされずに済むように
新たな視点で整理されたより良いものとしてRustのTraitが提供されている
LSPに明記されている前提すら満たさない異なるものであるため
「RustのTraitはLSPと関係ない」で合っている
LSPが対象としている遺物における諸問題に悩まされずに済むように
新たな視点で整理されたより良いものとしてRustのTraitが提供されている
680デフォルトの名無しさん
2024/07/09(火) 15:28:08.29ID:aoAam1/W681デフォルトの名無しさん
2024/07/09(火) 17:53:13.80ID:uNqr/AfO682デフォルトの名無しさん
2024/07/09(火) 20:23:57.43ID:YflJELWV >>679
RustとLSPが関係ないのなら、LSPを引き合いに出すのは大嘘か。
知ってて言っているなら詐欺師だな。
そもそもTraitでpanic禁止にできない時点で「LSPが対象としている遺物における諸問題に悩まされずに済む」というのも大嘘だしな。
RustとLSPが関係ないのなら、LSPを引き合いに出すのは大嘘か。
知ってて言っているなら詐欺師だな。
そもそもTraitでpanic禁止にできない時点で「LSPが対象としている遺物における諸問題に悩まされずに済む」というのも大嘘だしな。
683デフォルトの名無しさん
2024/07/09(火) 20:49:10.75ID:sTXYSGuF 簡単な話だよな
オブジェクト指向プログラミングで
例えばクラスを使うと
LSPに違反する二つの型のコード例を容易に作れてしまう
つまりクラスは本質的に欠陥品なんだよ
Rustのトレイトを使うと
LSPに違反する二つの型のコード例を作ることができない
つまりRustのトレイトは優れた方式なんだよ
オブジェクト指向プログラミングで
例えばクラスを使うと
LSPに違反する二つの型のコード例を容易に作れてしまう
つまりクラスは本質的に欠陥品なんだよ
Rustのトレイトを使うと
LSPに違反する二つの型のコード例を作ることができない
つまりRustのトレイトは優れた方式なんだよ
684デフォルトの名無しさん
2024/07/09(火) 21:07:20.42ID:YflJELWV >>683
あるトレイトでpanic2を禁止しようとしました。事前条件(あるいは例外条件)でnopanicとしたかったけど、そんなのは無いのでとりあえずデフォルト実装でpanic禁止にしました。
しかしトレイトユーザーはそんなのお構い無しにunsafe rustでpanicを使います。ついにpanicが発生してシステムダウンしました。
LSPでケアしている問題はRustのTraitを使っている限り発生しないんじゃないんだっけ?
あるトレイトでpanic2を禁止しようとしました。事前条件(あるいは例外条件)でnopanicとしたかったけど、そんなのは無いのでとりあえずデフォルト実装でpanic禁止にしました。
しかしトレイトユーザーはそんなのお構い無しにunsafe rustでpanicを使います。ついにpanicが発生してシステムダウンしました。
LSPでケアしている問題はRustのTraitを使っている限り発生しないんじゃないんだっけ?
685デフォルトの名無しさん
2024/07/09(火) 21:56:05.19ID:sTXYSGuF Rustのトレイトは優れているため
LSPに違反するコード例を作ることができないんだよ
もしRustに文句をつけたかったら
LSPに違反する二つの型のコード例を作って示してごらん
Rustで違反例を作るのは不可能だよ
LSPに違反するコード例を作ることができないんだよ
もしRustに文句をつけたかったら
LSPに違反する二つの型のコード例を作って示してごらん
Rustで違反例を作るのは不可能だよ
686デフォルトの名無しさん
2024/07/09(火) 22:08:43.14ID:ZNKPIxXk687デフォルトの名無しさん
2024/07/09(火) 22:36:56.01ID:YflJELWV688デフォルトの名無しさん
2024/07/09(火) 22:44:26.63ID:loMF79su LSPはそんなことを要求していないよ
LSPをちゃんと読んで理解しようね
LSPをちゃんと読んで理解しようね
689デフォルトの名無しさん
2024/07/09(火) 22:50:55.17ID:aoAam1/W >>686
クラスは様々な問題点を抱えている
クラスでは実装継承となるため異なる型同士に不必要に過度な依存関係をもたらす硬直性も問題点の一つ
クラスはLSP(リスコフの置換原則)を満たさないプログラムが量産されてしまう問題点も別の一つ
どちらの問題点もRustならtraitを使うため問題が起きない
クラスは様々な問題点を抱えている
クラスでは実装継承となるため異なる型同士に不必要に過度な依存関係をもたらす硬直性も問題点の一つ
クラスはLSP(リスコフの置換原則)を満たさないプログラムが量産されてしまう問題点も別の一つ
どちらの問題点もRustならtraitを使うため問題が起きない
690デフォルトの名無しさん
2024/07/09(火) 22:52:12.26ID:j8eVmrRh 猿ども落ち着いてください!
ここで論破合戦したところでなんの得にもなりません
ここで論破合戦したところでなんの得にもなりません
691デフォルトの名無しさん
2024/07/09(火) 22:57:23.83ID:/lHavWP5 >>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);
}
リスコフの置換原則は設計的な原則だから言語仕様で違反を防ぐことはできないぞ
悪名高い長方形・正方形の問題はトレイトがあっても起こり得る
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);
}
692デフォルトの名無しさん
2024/07/09(火) 23:17:09.97ID:dptasXVA693デフォルトの名無しさん
2024/07/09(火) 23:22:06.46ID:J+Fyw0mO694デフォルトの名無しさん
2024/07/09(火) 23:24:11.46ID:KAvgjhF7 >>692
IRectanble トレイトとかに読み替えてくれ
これは設計的に問題のある例を恣意的に示しているので不自然な点はあるけど、意図は伝わると思う
分かる人は分かると思うけど、問題は「そもそも正方形はwidthとheightという2つの値を扱うインタエースを持つべきでない」というところなので、Rectangleトレイトを作った時点で破綻している
けどそれは設計の問題なので、トレイトという仕組みによってコンパイラが防げるものではないということ
IRectanble トレイトとかに読み替えてくれ
これは設計的に問題のある例を恣意的に示しているので不自然な点はあるけど、意図は伝わると思う
分かる人は分かると思うけど、問題は「そもそも正方形はwidthとheightという2つの値を扱うインタエースを持つべきでない」というところなので、Rectangleトレイトを作った時点で破綻している
けどそれは設計の問題なので、トレイトという仕組みによってコンパイラが防げるものではないということ
695デフォルトの名無しさん
2024/07/09(火) 23:30:16.52ID:KAvgjhF7 >2つの異なる長さを持つ(受け取る)機能を定義しているのならば
>正方形はその実装型にはなりえません
論理的にはそう
でも実際にそういうコードを書けばビルドは通る
>>685 で
>LSPに違反する二つの型のコード例を作って示してごらん
>Rustで違反例を作るのは不可能だよ
とあったので、これはその反例として示した
このような問題は設計の問題であり、まずい設計をする人が使えばRustでも問題は起こり得るということを言いたい
>正方形はその実装型にはなりえません
論理的にはそう
でも実際にそういうコードを書けばビルドは通る
>>685 で
>LSPに違反する二つの型のコード例を作って示してごらん
>Rustで違反例を作るのは不可能だよ
とあったので、これはその反例として示した
このような問題は設計の問題であり、まずい設計をする人が使えばRustでも問題は起こり得るということを言いたい
696デフォルトの名無しさん
2024/07/09(火) 23:35:35.51ID:h2DmPYHm >>691
君はLSPを理解できていない
LSPはis-aの関係を持つ二つの型に対して遵守すべきルールだ
Rustのtraitとその実装型はis-aの関係ではなくhas-aの関係を持つ
したがってtraitとその実装型は明らかにLSPの対象外となる
君はLSPを理解できていない
LSPはis-aの関係を持つ二つの型に対して遵守すべきルールだ
Rustのtraitとその実装型はis-aの関係ではなくhas-aの関係を持つ
したがってtraitとその実装型は明らかにLSPの対象外となる
697デフォルトの名無しさん
2024/07/09(火) 23:40:48.87ID:h2DmPYHm698デフォルトの名無しさん
2024/07/09(火) 23:56:35.46ID:ZNKPIxXk >Rustのtraitとその実装型はis-aの関係ではなくhas-aの関係を持つ
すげーのが出てきたなこりゃw
すげーのが出てきたなこりゃw
699デフォルトの名無しさん
2024/07/09(火) 23:59:12.82ID:loMF79su700デフォルトの名無しさん
2024/07/10(水) 00:09:07.13ID:H4rrLaXL メンバ関数名をそのままtraitの名前にしちまえば
そのメンバを持つ者とtraitの関係はhas-a
そのメンバを持つ者とtraitの関係はhas-a
701デフォルトの名無しさん
2024/07/10(水) 00:10:24.05ID:HryWiaEt 過去に見た (rust以外の) プロジェクトの失敗例だと
・もともとFooというクラスがあった
・新しく作るBooクラスについて、Fooクラスと同じように扱えれば既存コードをあまり変更しなくても済むぞ!と誰かが気づいた
・その人物は Foo クラスのメソッドを元に IFoo インタフェースを定義し、それを Foo と Boo に実装させた
ことから混沌としたコードが生まれた例がある
この失敗をやらかした人は、Rustでも同じように「既存の Rectangle クラスを元に IRectangle トレイトを作り、それを Rectangle と Square に実装させる」ことをやりかねない
Rustではそれが不自然なパターンになりやすいし、起こりにくくはあるけど、本質的には設計の問題
・もともとFooというクラスがあった
・新しく作るBooクラスについて、Fooクラスと同じように扱えれば既存コードをあまり変更しなくても済むぞ!と誰かが気づいた
・その人物は Foo クラスのメソッドを元に IFoo インタフェースを定義し、それを Foo と Boo に実装させた
ことから混沌としたコードが生まれた例がある
この失敗をやらかした人は、Rustでも同じように「既存の Rectangle クラスを元に IRectangle トレイトを作り、それを Rectangle と Square に実装させる」ことをやりかねない
Rustではそれが不自然なパターンになりやすいし、起こりにくくはあるけど、本質的には設計の問題
702デフォルトの名無しさん
2024/07/10(水) 00:29:11.77ID:HryWiaEt 「Rustを書く人はみんな賢いからそのような問題は起こさないはずだ」というなら話は別たけど
実装者の設計能力は言語仕様によって担保できるものではない
実装者の設計能力は言語仕様によって担保できるものではない
703デフォルトの名無しさん
2024/07/10(水) 00:33:23.92ID:L/ekmjSC704デフォルトの名無しさん
2024/07/10(水) 00:35:49.38ID:L/ekmjSC705デフォルトの名無しさん
2024/07/10(水) 00:36:32.00ID:NGyo+F/O LSPを全く理解してないばかりか
サブタイピングも理解しとらんのやな
よう継承継承言うたなぁw
サブタイピングも理解しとらんのやな
よう継承継承言うたなぁw
706デフォルトの名無しさん
2024/07/10(水) 00:53:28.80ID:ur6BKR72 クラスが問題だらけの欠陥品なことが災いを招いてるよね
モダンなプログラミング言語の多くがクラスを捨て去ってくれて感謝
モダンなプログラミング言語の多くがクラスを捨て去ってくれて感謝
707デフォルトの名無しさん
2024/07/10(水) 01:13:16.99ID:1XduDtMr708デフォルトの名無しさん
2024/07/10(水) 01:26:45.94ID:UJdk5M3g709デフォルトの名無しさん
2024/07/10(水) 01:45:22.45ID:1XduDtMr710デフォルトの名無しさん
2024/07/10(水) 02:13:28.47ID:1XduDtMr >>698
RustのTraitとImplの関係はまさしくsubtypeだしis-aの関係なのにな。「継承しなければsubtypeじゃないしis-aにもならない」と間違って覚えているんかね。
RustのTraitとImplの関係はまさしくsubtypeだしis-aの関係なのにな。「継承しなければsubtypeじゃないしis-aにもならない」と間違って覚えているんかね。
711デフォルトの名無しさん
2024/07/10(水) 02:30:31.13ID:GS4KrVsy どこかで聞きかじっただけの「継承は悪」に辻褄を合わせようとしてどんどん変な理屈を積み重ねているだけでしょ
712デフォルトの名無しさん
2024/07/10(水) 02:33:48.76ID:H5PXuDT2 >>707
LSPでは例外を返すなら基底型で返す例外とそのサブタイプのみに限られるとしか言及していない
例外で値をキャッチできなくなることや値を返す抜け道になることを防ぐためだ
ちなみにRustのpanic!では値を返すことはできなくてpanicメッセージのみ
そして普通のプログラムでpanicをキャッチすることはない点など前提が全く異なる
Rustで従来の例外を扱うケースはpanic!を使わずにResultの返り値で返す
したがってpanic!はLSPで出てくる例外の話に該当しないだろう
LSPでは例外を返すなら基底型で返す例外とそのサブタイプのみに限られるとしか言及していない
例外で値をキャッチできなくなることや値を返す抜け道になることを防ぐためだ
ちなみにRustのpanic!では値を返すことはできなくてpanicメッセージのみ
そして普通のプログラムでpanicをキャッチすることはない点など前提が全く異なる
Rustで従来の例外を扱うケースはpanic!を使わずにResultの返り値で返す
したがってpanic!はLSPで出てくる例外の話に該当しないだろう
713デフォルトの名無しさん
2024/07/10(水) 03:06:35.71ID:mzDH1NTP >それらインタフェースやトレイトを用いている時点でLSPの対象外となっている
間違ってるよ
インターフェースだろうがトレイトだろうがサブタイピングは成立するよ
サブタイピングが成立すれば当然LSPの対象範囲だよ
>>691の例もLSPの違反例としては合ってるよ
間違った継承の使い方の例としてよく使われてるよね
間違ってるよ
インターフェースだろうがトレイトだろうがサブタイピングは成立するよ
サブタイピングが成立すれば当然LSPの対象範囲だよ
>>691の例もLSPの違反例としては合ってるよ
間違った継承の使い方の例としてよく使われてるよね
714デフォルトの名無しさん
2024/07/10(水) 04:10:08.62ID:xXJVwGE7 >>684
>panic禁止にしました。
たとえno_std環境であろうとpanicは禁止にできない
>unsafe rustでpanicを使います。
panicを引き起こすのも扱うのもunsafeを必要としない
>panicが発生してシステムダウンしました。
panic発生がそのままシステムダウンではない
何ら特別な設定をしない標準状態でもスレッド内で起きたpanicはエラーとして返るだけで他のスレッドは動き続ける
>panic禁止にしました。
たとえno_std環境であろうとpanicは禁止にできない
>unsafe rustでpanicを使います。
panicを引き起こすのも扱うのもunsafeを必要としない
>panicが発生してシステムダウンしました。
panic発生がそのままシステムダウンではない
何ら特別な設定をしない標準状態でもスレッド内で起きたpanicはエラーとして返るだけで他のスレッドは動き続ける
715デフォルトの名無しさん
2024/07/10(水) 07:01:39.33ID:H4rrLaXL >>710
型クラスのinstanceであると宣言すればsubtypeじゃないのは自明だぜ
じゃあtraitをimplすると宣言したら
自明だった問題が突如として最先端の未解決問題に変化するのか?
しないでしょ
同じでしょ
型クラスのinstanceであると宣言すればsubtypeじゃないのは自明だぜ
じゃあtraitをimplすると宣言したら
自明だった問題が突如として最先端の未解決問題に変化するのか?
しないでしょ
同じでしょ
716デフォルトの名無しさん
2024/07/10(水) 07:02:08.59ID:HryWiaEt717デフォルトの名無しさん
2024/07/10(水) 07:35:50.92ID:1hn7S5X0718デフォルトの名無しさん
2024/07/10(水) 08:46:54.18ID:1XduDtMr719デフォルトの名無しさん
2024/07/10(水) 12:00:16.62ID:GhKm8r1f >>718
そのアンカ先は全部複オジだろ
LSPも知らない、サブタイピングも知らない、継承で起こりうる簡単な問題も知らない
にもかかわらず知ったかぶりして嘘を並び立てる
こんなやつがそうそういるわけがない
そのアンカ先は全部複オジだろ
LSPも知らない、サブタイピングも知らない、継承で起こりうる簡単な問題も知らない
にもかかわらず知ったかぶりして嘘を並び立てる
こんなやつがそうそういるわけがない
720デフォルトの名無しさん
2024/07/10(水) 12:37:44.86ID:1YSFCzN+ キチガイは1人見かけたら10人はいると思え
721デフォルトの名無しさん
2024/07/10(水) 13:29:52.02ID:kPG9kWdt >>701
そのやり方がなぜ悪いのか理解できませんので、教えてください。
例えば、C++だと、以下の様にするのも別に悪いやり方ではないような
気がするのですが。
class Number {・・・};
Number add(Number &a, Number &b);
Number mul(Number &a, Number &b);
class Integer : public Number {・・・};
class Rational : public Number {・・・};
そのやり方がなぜ悪いのか理解できませんので、教えてください。
例えば、C++だと、以下の様にするのも別に悪いやり方ではないような
気がするのですが。
class Number {・・・};
Number add(Number &a, Number &b);
Number mul(Number &a, Number &b);
class Integer : public Number {・・・};
class Rational : public Number {・・・};
722デフォルトの名無しさん
2024/07/10(水) 13:32:41.05ID:2GPD5dJ4 ChatGPTってモノシリなんですね?
723デフォルトの名無しさん
2024/07/10(水) 13:34:42.29ID:kPG9kWdt >>721
改めて見てみると、add()やmul()の戻り値にNumberの実態を返しているのがおかしい気もしますが。
IntegerやRationalにadd()やmul()を仮想関数として定義するのが良いのかもしれません。
そのような点で改良の余地が沢山ありそうです。
改めて見てみると、add()やmul()の戻り値にNumberの実態を返しているのがおかしい気もしますが。
IntegerやRationalにadd()やmul()を仮想関数として定義するのが良いのかもしれません。
そのような点で改良の余地が沢山ありそうです。
724デフォルトの名無しさん
2024/07/10(水) 13:47:33.33ID:2GPD5dJ4725デフォルトの名無しさん
2024/07/10(水) 14:42:18.00ID:H4rrLaXL 10人いると思ってる人自身が11人目になりやすいから気をつけなよ
数値の計測が抱えている問題は、そもそも計測していない人には起こらない
数値の計測が抱えている問題は、そもそも計測していない人には起こらない
726デフォルトの名無しさん
2024/07/10(水) 15:49:38.80ID:WriLZMcZ >>721
add(integer, rational)できる?
add(integer, rational)できる?
727デフォルトの名無しさん
2024/07/10(水) 16:24:23.57ID:2GPD5dJ4 ミイラとりがミイラになるのは昔から
728デフォルトの名無しさん
2024/07/10(水) 16:42:16.40ID:aw6hROvm >>712
>例外で値をキャッチできなくなることや値を返す抜け道になることを防ぐためだ
違うよ
勝手な想像でLSPを誤解釈しないで
substituteされる型Tに対して定義された仕様上(契約上)の振る舞いを
substituteする型Sが満たしてなければLSP違反
つまり仕様上panicを禁止したトレイトの関数を
panicする関数でimplしたらLSP違反
LSPではあくまで”仕様上定義された振る舞い”が問題
>例外で値をキャッチできなくなることや値を返す抜け道になることを防ぐためだ
違うよ
勝手な想像でLSPを誤解釈しないで
substituteされる型Tに対して定義された仕様上(契約上)の振る舞いを
substituteする型Sが満たしてなければLSP違反
つまり仕様上panicを禁止したトレイトの関数を
panicする関数でimplしたらLSP違反
LSPではあくまで”仕様上定義された振る舞い”が問題
729デフォルトの名無しさん
2024/07/10(水) 18:28:13.04ID:/bwWoePd730デフォルトの名無しさん
2024/07/10(水) 21:04:08.95ID:H4rrLaXL catchするという対案がない
対案との比較が抱えている問題はそもそも対案がない言語では起こらない
対案との比較が抱えている問題はそもそも対案がない言語では起こらない
731デフォルトの名無しさん
2024/07/10(水) 21:42:13.36ID:DHf/HCo5732デフォルトの名無しさん
2024/07/10(水) 22:01:49.20ID:HryWiaEt >>721
「インタフェースを定義し、それに基づいて実装する」という設計なら問題ないのだけど、
これは「あるクラスに依存していたコード群が新しいクラスでも動くようにするため」という発想になっており、大規模な開発だとこのやり方はだいたい失敗するよという話
例を書きづらいけど、例えば「A社製の装置を制御するアプリ」があったとして、
新しく「B社製の装置も制御できるようにする」という追加の開発案件があったとする。
この時点ではまだADeviceControllerは抽象化されておらず、A社装置の仕様に強く依存したクラスであるとする。
これを「ADeviceController が持つメソッドを IDeviceController として取り出し、それを BDeviceControllerにも実装させる」とすると確実に事故る。
「B社装置にだけある機能Xを呼びたい」「A社装置にあった機能YがB社装置にはない」といった違いを吸収しきえれず、インタフェースがぐちゃぐちゃになったり、「呼んでも何もしない」とかの形で誤魔化したり、呼び出し元でサブクラスの判定が必要になったりする
こうならないようにするには
a. 具体的な機器に依存しない、機器の振る舞いを適切に抽象化したインタフェースを定義する
b. 代数的データ型を使う
という方法があり、 Rust では b. の方法も使いやすいので、個人的にはそこが良いなと思う
「インタフェースを定義し、それに基づいて実装する」という設計なら問題ないのだけど、
これは「あるクラスに依存していたコード群が新しいクラスでも動くようにするため」という発想になっており、大規模な開発だとこのやり方はだいたい失敗するよという話
例を書きづらいけど、例えば「A社製の装置を制御するアプリ」があったとして、
新しく「B社製の装置も制御できるようにする」という追加の開発案件があったとする。
この時点ではまだADeviceControllerは抽象化されておらず、A社装置の仕様に強く依存したクラスであるとする。
これを「ADeviceController が持つメソッドを IDeviceController として取り出し、それを BDeviceControllerにも実装させる」とすると確実に事故る。
「B社装置にだけある機能Xを呼びたい」「A社装置にあった機能YがB社装置にはない」といった違いを吸収しきえれず、インタフェースがぐちゃぐちゃになったり、「呼んでも何もしない」とかの形で誤魔化したり、呼び出し元でサブクラスの判定が必要になったりする
こうならないようにするには
a. 具体的な機器に依存しない、機器の振る舞いを適切に抽象化したインタフェースを定義する
b. 代数的データ型を使う
という方法があり、 Rust では b. の方法も使いやすいので、個人的にはそこが良いなと思う
733デフォルトの名無しさん
2024/07/10(水) 22:15:46.44ID:b9m+kH0p 設計が悪いといえばその通りなんだけど、そのせいでインタフェースが崩壊しているプロジェクトは実際にあるし、RustやGoが継承を廃止した理由の一つでもあると思う
クラス継承だとこの問題はもっと簡単に起こりやすい
前述の例は (あくまでも見かけ上は) インタフェースを定義しており、クラスを継承してるわけではないので、Rustのトレイトでもやろうと思えば起こるけどね
クラス継承だとこの問題はもっと簡単に起こりやすい
前述の例は (あくまでも見かけ上は) インタフェースを定義しており、クラスを継承してるわけではないので、Rustのトレイトでもやろうと思えば起こるけどね
734デフォルトの名無しさん
2024/07/10(水) 22:19:25.73ID:FlmWdBd4 言語を選ぶにあたって継承の有無は選択肢に入らんし正直言ってどうでもいいわ
代替手段があるのにいつまで言ってんだ
代替手段があるのにいつまで言ってんだ
735デフォルトの名無しさん
2024/07/10(水) 22:32:22.87ID:dGMDZq55 >>729
仕様を定義するという簡単なお話がほんとにわからないのかな?
panicを例にすると頭がパニクるみたいなので
リスコフの論文にあるFIFO/LIFOの例で言い換えると
仕様としてLIFOの振る舞いを要求するトレイトの関数を
FIFOの振る舞いで実装したらLSP違反ってこと
簡単なお話でしょ?
仕様を定義するという簡単なお話がほんとにわからないのかな?
panicを例にすると頭がパニクるみたいなので
リスコフの論文にあるFIFO/LIFOの例で言い換えると
仕様としてLIFOの振る舞いを要求するトレイトの関数を
FIFOの振る舞いで実装したらLSP違反ってこと
簡単なお話でしょ?
736デフォルトの名無しさん
2024/07/10(水) 22:40:16.17ID:H4rrLaXL 既に言語を選んだのにまだ、is-aとhas-aどっちにするか選べとか
catchするかしないか選べとか
言語の内部でいつまでも選択が繰り返されるシステムが謎なんよ
いつまで言われるかといえば謎が解けるまでだよ
catchするかしないか選べとか
言語の内部でいつまでも選択が繰り返されるシステムが謎なんよ
いつまで言われるかといえば謎が解けるまでだよ
737デフォルトの名無しさん
2024/07/10(水) 23:21:18.85ID:visgGGe9 >>732
それは共通インターフェースと特定装置にしかないインターフェースをそれぞれ別で用意すべきだと思う
拡張メソッドや拡張トレイトも活用する
ただA社装置もB社装置も1つの共通したコードで扱うなら
サブクラス判定ではないにしても呼び出し元での分岐は何かしら必要
それは共通インターフェースと特定装置にしかないインターフェースをそれぞれ別で用意すべきだと思う
拡張メソッドや拡張トレイトも活用する
ただA社装置もB社装置も1つの共通したコードで扱うなら
サブクラス判定ではないにしても呼び出し元での分岐は何かしら必要
738デフォルトの名無しさん
2024/07/10(水) 23:44:27.81ID:6pwTfhEs739デフォルトの名無しさん
2024/07/11(木) 00:29:09.09ID:dTTJ6k+i クイズ
JavaScriptのプロトタイプチェーンはis-a?
それともhas-a?
JavaScriptのプロトタイプチェーンはis-a?
それともhas-a?
740デフォルトの名無しさん
2024/07/11(木) 00:30:41.75ID:sJ7PGs8/ >>732
一般的に何らかの上位層と下位層があるときに
Rustではその界面にtraitを置いて
上位層はそのtraitを利用する側
下位層はそのtraitを実装する側
とSILIDのDIP (Dependency Inversion Principle)にするのがそのa.だね
もしクラスでやるときは抽象化を徹底した上で色んな注意が必要になるところ
Rustは自然にコーディングできてありがたいね
一般的に何らかの上位層と下位層があるときに
Rustではその界面にtraitを置いて
上位層はそのtraitを利用する側
下位層はそのtraitを実装する側
とSILIDのDIP (Dependency Inversion Principle)にするのがそのa.だね
もしクラスでやるときは抽象化を徹底した上で色んな注意が必要になるところ
Rustは自然にコーディングできてありがたいね
741デフォルトの名無しさん
2024/07/11(木) 01:01:01.84ID:sJ7PGs8/ スマソ
SILIDはSOLIDのタイポ
SILIDはSOLIDのタイポ
742デフォルトの名無しさん
2024/07/11(木) 01:26:06.15ID:sLOW5r2m >>740
インターフェース知らないの?
インターフェース知らないの?
743デフォルトの名無しさん
2024/07/11(木) 01:37:36.53ID:sJ7PGs8/ >>742
インタフェースは各言語で付加仕様がバラバラ多種多様だから慎重に言うと
それ自体はフィールド変数など持たず完全に抽象化できつつ
実装必須メソッドとデフォルト実装提供メソッドがサポートされて
その中で利用可能な他のインタフェース(またはtrait)群による制約ができて
となるとどの言語が残るかな
インタフェースは各言語で付加仕様がバラバラ多種多様だから慎重に言うと
それ自体はフィールド変数など持たず完全に抽象化できつつ
実装必須メソッドとデフォルト実装提供メソッドがサポートされて
その中で利用可能な他のインタフェース(またはtrait)群による制約ができて
となるとどの言語が残るかな
744デフォルトの名無しさん
2024/07/11(木) 03:34:06.04ID:huEwUyFV それはたぶんDじゃなくてIかな……
745デフォルトの名無しさん
2024/07/11(木) 09:53:46.09ID:TzM2Jqw+746デフォルトの名無しさん
2024/07/11(木) 11:33:08.04ID:gcQpVY2c >>744
DもIも両方関係あるよ
DもIも両方関係あるよ
747デフォルトの名無しさん
2024/07/11(木) 11:36:08.08ID:gcQpVY2c748デフォルトの名無しさん
2024/07/11(木) 11:46:30.35ID:ITTQebkb ʕ◔ϖ◔ʔ
749デフォルトの名無しさん
2024/07/11(木) 12:31:18.41ID:QtPgEU0q >>747
ウソはあかん
ウソはあかん
750デフォルトの名無しさん
2024/07/11(木) 13:53:08.83ID:gabJiib7 >>747
サーバー用途で強いJavaは残るね
Kotlin/Swiftもモバイルアプリのネイティブ言語として残る
TSはJSで十分っていう風潮が漂いつつあるけどまあ残るだろう
死ぬのはC#とDartかな
サーバー用途で強いJavaは残るね
Kotlin/Swiftもモバイルアプリのネイティブ言語として残る
TSはJSで十分っていう風潮が漂いつつあるけどまあ残るだろう
死ぬのはC#とDartかな
751デフォルトの名無しさん
2024/07/11(木) 14:12:48.49ID:0oGtZVd6 LSPで嘘ばっかりついてたのがバレたから
またしょうもない話をはじめてごまかそうとしてるのか
いい加減にしろよ
またしょうもない話をはじめてごまかそうとしてるのか
いい加減にしろよ
752デフォルトの名無しさん
2024/07/11(木) 16:22:35.45ID:o6wwWo1Z LSPに書かれていることすら読まずに
RustのトレイトがLSPの対象だと言い張ってたもんな
RustのトレイトがLSPの対象だと言い張ってたもんな
753デフォルトの名無しさん
2024/07/11(木) 16:57:46.28ID:acwFdQNv PartialOrdとPartialEqの一貫性とかLSPっぽいけど
Substitution(置換)とはちょっと違うんだよな
無理矢理Sに当てるならSurrogation(代用)あたりか
これをLSPに含めるかは定義重視vs意味重視で意見が分かれそう
Substitution(置換)とはちょっと違うんだよな
無理矢理Sに当てるならSurrogation(代用)あたりか
これをLSPに含めるかは定義重視vs意味重視で意見が分かれそう
754デフォルトの名無しさん
2024/07/11(木) 17:15:40.81ID:HnhcW2rv LSPはsupertypeのインスタンス(オブジェクト)とsubtypeのインスタンスの振る舞いを比較してそこで満たすべき原則を挙げていますから
Rustのtraitをsupertypeとしてみてもそのインスタンスが存在しないため振る舞いの比較ができないですね
traitはLSPとは関係ない立ち位置にいます
Rustのtraitをsupertypeとしてみてもそのインスタンスが存在しないため振る舞いの比較ができないですね
traitはLSPとは関係ない立ち位置にいます
755デフォルトの名無しさん
2024/07/11(木) 20:33:40.77ID:eOImp5ti ごちゃごちゃ難しいこと考えてるうちにエンバグしたりなんかして。
756デフォルトの名無しさん
2024/07/11(木) 21:02:05.21ID:qBSAH7HU >>750
サーバー用途こそJavaはRustとGoに蹴散らされて終わるだろ
サーバー用途こそJavaはRustとGoに蹴散らされて終わるだろ
757デフォルトの名無しさん
2024/07/11(木) 21:30:58.09ID:wPVHCKh0 実際のところRustはサーバーサイドで使われてるの?
758デフォルトの名無しさん
2024/07/11(木) 22:25:27.54ID:A0mL7vqg 実際は派生クラスの方が支持されていたとしても基底クラスを蹴散らしてはならない
とLSPは言っている
とLSPは言っている
759デフォルトの名無しさん
2024/07/11(木) 22:35:40.65ID:Z3SFRt47 >>757
使われてないよ
使われてないよ
760デフォルトの名無しさん
2024/07/11(木) 22:47:57.53ID:Wdw77EAw761デフォルトの名無しさん
2024/07/11(木) 22:50:39.98ID:wG+w8SXo サーバーは常時稼働させるものだからねえ
762デフォルトの名無しさん
2024/07/11(木) 23:16:00.08ID:liPsU6bJ >>757
GAFAMとかCloudflareとかトラフィックの多いとこに入ってるから誰もが必ずお世話になってる程度には使われてる
日本でサーバーサイドの仕事が沢山あるか、という意味ならそんなことはない
GAFAMとかCloudflareとかトラフィックの多いとこに入ってるから誰もが必ずお世話になってる程度には使われてる
日本でサーバーサイドの仕事が沢山あるか、という意味ならそんなことはない
763デフォルトの名無しさん
2024/07/11(木) 23:24:11.59ID:b01V4j67 世界中で着実にRustへ置き換わっていってるね
特にクラウドを利用しているとランニングコストに直結するので
特にクラウドを利用しているとランニングコストに直結するので
764デフォルトの名無しさん
2024/07/12(金) 00:13:00.93ID:0qGKBZrU >>753, 754
トレイトの場合はLSPで言うsupertypeやsubtypeになるのは
トレイトを利用して作られるimpl Traitやtrait objectの型だよ
PartialOrd/PartialEqやFn/FnMut/FnOnceのように
supertrait/subtraitの関係にあるやつも便宜的にトレイトで互換性が語られるけど
実際はそれらを利用して作られる型についての話なのと同じなんだよ
トレイトの場合はLSPで言うsupertypeやsubtypeになるのは
トレイトを利用して作られるimpl Traitやtrait objectの型だよ
PartialOrd/PartialEqやFn/FnMut/FnOnceのように
supertrait/subtraitの関係にあるやつも便宜的にトレイトで互換性が語られるけど
実際はそれらを利用して作られる型についての話なのと同じなんだよ
765デフォルトの名無しさん
2024/07/12(金) 00:16:45.77ID:U8/iJiIO >>764
真面目に相手してあげるの偉いな
真面目に相手してあげるの偉いな
766デフォルトの名無しさん
2024/07/12(金) 00:19:01.43ID:iZsWh24v767デフォルトの名無しさん
2024/07/12(金) 00:19:49.06ID:iZsWh24v768デフォルトの名無しさん
2024/07/12(金) 00:47:16.73ID:KyXC0KGT トレイトにはフィールド変数が一つもなくてメソッドも各個別型で実装されるものだから事前条件・事後条件など比較もできなくてLSP適用は無理でしょ
>>764
supertrait/subtraitの場合に例えばある構造体についてそのインスタンスはどちらも同一になるからLSPの前提である二つのインスタンス間での差は論じられないでしょ
>>764
supertrait/subtraitの場合に例えばある構造体についてそのインスタンスはどちらも同一になるからLSPの前提である二つのインスタンス間での差は論じられないでしょ
769デフォルトの名無しさん
2024/07/12(金) 09:52:35.34ID:bw8b12Bg >>757
Rustは殆どどこにも使われてないよ
Rustは殆どどこにも使われてないよ
770デフォルトの名無しさん
2024/07/12(金) 10:23:09.62ID:LuKbokrL 「C言語は分かる。機械語も分かる、回路もわかる。30万払うからRustのメモリ安全のからくりをサクッとレクチャーしてくれ」
みたいなニーズがあっさり無料で満たされているべきだと思うんだ
みたいなニーズがあっさり無料で満たされているべきだと思うんだ
771デフォルトの名無しさん
2024/07/12(金) 10:57:31.20ID:KyXC0KGT 誤解は色々あるけど「努力すれば必ずゼロコストになるカラクリ」が
あると思ってるならそれが誤解だね
クイックソートやハッシュテーブルと同じく、最悪の場合のコストは低くない
あると思ってるならそれが誤解だね
クイックソートやハッシュテーブルと同じく、最悪の場合のコストは低くない
■ このスレッドは過去ログ倉庫に格納されています
ニュース
- 日本行き空路49万件キャンセル 中国自粛呼びかけ 日本行きチケット予約の約32%に相当 [ぐれ★]
- 【中国外務省】日中関係悪化は高市氏に責任と名指しで非難… ★3 [BFU★]
- 【中国外務省】日中関係悪化は高市氏に責任と名指しで非難… ★2 [BFU★]
- 外務省局長は無言で厳しい表情…日中の高官協議終了か 高市首相“台湾”発言で中国が強硬対応 発言撤回求めたか…★2 [BFU★]
- 小野田紀美・経済安保担当相「何か気に入らないことがあればすぐに経済的威圧をする国への依存はリスク」 [Hitzeschleier★]
- 政府、株式の配当など金融所得を高齢者の医療保険料や窓口負担に反映する方針を固めた [バイト歴50年★]
- 外務省局長、よくわからないまま帰国へ [834922174]
- 中国高官と話す外務省局長の表情、やばい ★2 [175344491]
- 【高市速報】日本人の3割「中国への武力行使に踏み切る必要がある」ANN世論調査 [931948549]
- 高市早苗政権「経済的威圧をしてくる国はリスク」 トランプぴょんぴょん政権さん…… [175344491]
- 中国外務省「日中関係の悪化は高市早苗首相が原因」と名指しで強く非難。キタ━(゚∀゚)━! [153490809]
- 偏差値35大臣「すぐに経済的威圧するところへの依存はリスク」 [834922174]
