公式
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
レス数が900を超えています。1000を超えると表示できなくなるよ。
2024/05/27(月) 06:41:26.82ID:T4AFD1f4
813デフォルトの名無しさん
2024/07/13(土) 11:00:31.54ID:l6/BNZgQ 仮にfleetが商用無料になるなら喜んでvscodeを捨てるけど金にがめついjetbrainsが商用無料で配るなんてありえない話
javaやkotlinならともかくrustなら商用無料のvscodeで十分
javaやkotlinならともかくrustなら商用無料のvscodeで十分
814デフォルトの名無しさん
2024/07/13(土) 11:14:27.08ID:3n/3tOrD >>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となんら関係がない
そこで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となんら関係がない
815デフォルトの名無しさん
2024/07/13(土) 11:36:15.00ID:mV5TIlCk よく分からんけど
fn do_somethg(x: impl T)
にS型のオブジェクトoを渡すなら、do_somethingにとって o is T が成り立つんじゃない?
この関数は渡された o が S1 なのか S2 なのかは認識しないのだし
fn do_somethg(x: impl T)
にS型のオブジェクトoを渡すなら、do_somethingにとって o is T が成り立つんじゃない?
この関数は渡された o が S1 なのか S2 なのかは認識しないのだし
816デフォルトの名無しさん
2024/07/13(土) 11:44:56.49ID:4Ly9sDTU >>815
fn foo(x: impl T)は単相化されて
fn foo(x: S1)と
fn foo(x: S2)の二つの関数になるんだよ
いずれにしてもxはS1の値かS2の値であって
Tの値は存在しないね
fn foo(x: impl T)は単相化されて
fn foo(x: S1)と
fn foo(x: S2)の二つの関数になるんだよ
いずれにしてもxはS1の値かS2の値であって
Tの値は存在しないね
817デフォルトの名無しさん
2024/07/13(土) 11:50:56.55ID:6r0IzkzM818デフォルトの名無しさん
2024/07/13(土) 11:54:54.91ID:mV5TIlCk それはコンパイルのされ方の話であって意味の上での問題ではない気がする
Box<dyn T> なら動的ディスパッチされるわけだし
let x: T = ... のような変数を作れないという意味ならその通りだけど、それはオブジェクト指向言語におけるインターフェースでも同じでは
(それともインターフェースに対してLSPは成り立たない?)
Box<dyn T> なら動的ディスパッチされるわけだし
let x: T = ... のような変数を作れないという意味ならその通りだけど、それはオブジェクト指向言語におけるインターフェースでも同じでは
(それともインターフェースに対してLSPは成り立たない?)
819デフォルトの名無しさん
2024/07/13(土) 12:02:36.42ID:7b/8td6H >>812,814,816
なんで毎回飛んでレスするの?
なんで毎回飛んでレスするの?
820デフォルトの名無しさん
2024/07/13(土) 12:09:19.16ID:Zf2Y/4l2 前も貼ったけどRustはこういうニーズを背負ってる
オブジェクト指向を学ばなかった話
https://qiita.com/adaiimps/items/e04ae03371435aeffe87
C++、ObjectiveC、JavaだったのがRust、LLVM、ELFになって、あーやっぱこっちの方が面白いねと、
好きも嫌いもなく色んな言語を学びまくってる人はLLVMは学ばないのかなと
オブジェクト指向を学ばなかった話
https://qiita.com/adaiimps/items/e04ae03371435aeffe87
C++、ObjectiveC、JavaだったのがRust、LLVM、ELFになって、あーやっぱこっちの方が面白いねと、
好きも嫌いもなく色んな言語を学びまくってる人はLLVMは学ばないのかなと
821デフォルトの名無しさん
2024/07/13(土) 12:15:08.95ID:SXOx4oHh822デフォルトの名無しさん
2024/07/13(土) 12:31:19.55ID:IqeBToeS rust始めたけどtokioまわりの非同期処理が難しい…
823デフォルトの名無しさん
2024/07/13(土) 12:34:40.11ID:UG7jOJ2R 置換原則に沿うかどうかは具体的な実装を検証しないとわからないし、大抵の場合に機械的に検証することは出来ない。
型をサブタイプの関係にするのは原則に沿う「ことにする」という表明になることはあるが、原則に沿うことの保証にはならんのだ。
型をサブタイプの関係にするのは原則に沿う「ことにする」という表明になることはあるが、原則に沿うことの保証にはならんのだ。
824デフォルトの名無しさん
2024/07/13(土) 12:40:54.94ID:mV5TIlCk825デフォルトの名無しさん
2024/07/13(土) 12:44:05.69ID:Bid5yHc7 お前らずっと同じ話をループさせてんな😅
826デフォルトの名無しさん
2024/07/13(土) 12:51:22.30ID:kEBSnfkM827デフォルトの名無しさん
2024/07/13(土) 13:43:19.43ID:4hBdJvP4 >>825
好き嫌いの感覚に素直に従えば面白味のないループはすぐ止まりそうなのに
好き嫌いの感覚に素直に従えば面白味のないループはすぐ止まりそうなのに
828デフォルトの名無しさん
2024/07/13(土) 13:52:54.97ID:E+PNnzD+ PartialOrd: PartialEqは
PartialEq(等価判定)を持つ型にPartialOrd(半順序判定)を追加するときに
a.partial_cmp(b) == Some(Ordering::Equal)
と
a.eq(b) (⇔ a == b)
が同じになることを期待してる
この場合の置換の対象は型のインスタンスではなく使われる型の関数だから
LSPをインスタンスの置換に限定するか処理の置換にまで拡張するかで結論が変わる
PartialOrdの追加はPartialEqを使ってる既存のコードに影響しないから
技術的にはLSPと無関係ともいえるし
PartialOrdとPartialEqの等価判定の互換性は概念的にLSPの対象とも考えられる
PartialEq(等価判定)を持つ型にPartialOrd(半順序判定)を追加するときに
a.partial_cmp(b) == Some(Ordering::Equal)
と
a.eq(b) (⇔ a == b)
が同じになることを期待してる
この場合の置換の対象は型のインスタンスではなく使われる型の関数だから
LSPをインスタンスの置換に限定するか処理の置換にまで拡張するかで結論が変わる
PartialOrdの追加はPartialEqを使ってる既存のコードに影響しないから
技術的にはLSPと無関係ともいえるし
PartialOrdとPartialEqの等価判定の互換性は概念的にLSPの対象とも考えられる
829デフォルトの名無しさん
2024/07/13(土) 14:35:50.27ID:MYuplL5h つまりRustのトレイトは
LSPの原義に従うと対象外となり
拡張して考えるとLSPを常に満たす
ことになるわけか
LSPの原義に従うと対象外となり
拡張して考えるとLSPを常に満たす
ことになるわけか
830デフォルトの名無しさん
2024/07/13(土) 15:25:32.20ID:mV5TIlCk >>829
意味の上で考えるとしても「常に」は満たさないかと
struct MyString(String);
impl Clone for MyString {
fn clone(&self) -> Self {
Self("元の文字列と関係ない文字列".to_string())
}
}
のようにすれば、そのトレイトが期待する動作に反した型は作れるわけで
引数や戻り値のシグニチャの同一性だけに注目するならtraitに違反することはできないけど、それなら継承やインタフェースでも同じで、「LSPに違反してはならない」という原則はそもそも意味がない (常に違反できないから) ってことになるし
意味の上で考えるとしても「常に」は満たさないかと
struct MyString(String);
impl Clone for MyString {
fn clone(&self) -> Self {
Self("元の文字列と関係ない文字列".to_string())
}
}
のようにすれば、そのトレイトが期待する動作に反した型は作れるわけで
引数や戻り値のシグニチャの同一性だけに注目するならtraitに違反することはできないけど、それなら継承やインタフェースでも同じで、「LSPに違反してはならない」という原則はそもそも意味がない (常に違反できないから) ってことになるし
831デフォルトの名無しさん
2024/07/13(土) 15:38:58.70ID:MYuplL5h832デフォルトの名無しさん
2024/07/13(土) 15:50:29.46ID:mV5TIlCk >>831
例えば
fn test_clone(x: impl Clone + PartialEq) {
assert!(x.clone(), x);
}
はClone および PartialEq トレイトの振る舞いに依存したコードだけど、この振る舞いに反した型は作れるよね
トレイトは事後要件 (x.clone() == x) を定義できないし、そもそも Clone はそれを担保していないと主張することはできるけど、それならLPSって何のためにあるんだ?ってなるし
例えば
fn test_clone(x: impl Clone + PartialEq) {
assert!(x.clone(), x);
}
はClone および PartialEq トレイトの振る舞いに依存したコードだけど、この振る舞いに反した型は作れるよね
トレイトは事後要件 (x.clone() == x) を定義できないし、そもそも Clone はそれを担保していないと主張することはできるけど、それならLPSって何のためにあるんだ?ってなるし
833デフォルトの名無しさん
2024/07/13(土) 15:54:23.34ID:4hBdJvP4 「内在論理」に踏み込めば争いを解決できる説のようなものか
逆効果なのでは?
逆効果なのでは?
834デフォルトの名無しさん
2024/07/13(土) 15:55:51.56ID:mV5TIlCk 訂正
>>832 のアサート行は assert!(x.clone(), x) でなく assert!(x.clone() == x)
>>832 のアサート行は assert!(x.clone(), x) でなく assert!(x.clone() == x)
835デフォルトの名無しさん
2024/07/13(土) 15:57:24.24ID:UG7jOJ2R >>831
不変条件を弱められないルールだろう。
不変条件はシグネチャや定義域で表現できないものも含めた振る舞いの仕様全てのことで、挙動が (仕様に照らして) 望ましくなければ原則を満たさないと言える。
不変条件を弱められないルールだろう。
不変条件はシグネチャや定義域で表現できないものも含めた振る舞いの仕様全てのことで、挙動が (仕様に照らして) 望ましくなければ原則を満たさないと言える。
836デフォルトの名無しさん
2024/07/13(土) 16:03:55.44ID:E+PNnzD+ 829でPartialEq/PartialOrdを例に出したのは
この2つのtraitがsuper/subの関係にあるからで
Cloneとその実装型の関係とは別だよ
PartialEqとPartialOrdの等価判定についてのLSPを考えてる
PartialOrd: PartialEqとする以上
PartialOrdの比較はPartialEqの等価条件を保存すべき←LSP?
みたいな
この2つのtraitがsuper/subの関係にあるからで
Cloneとその実装型の関係とは別だよ
PartialEqとPartialOrdの等価判定についてのLSPを考えてる
PartialOrd: PartialEqとする以上
PartialOrdの比較はPartialEqの等価条件を保存すべき←LSP?
みたいな
837デフォルトの名無しさん
2024/07/13(土) 16:10:18.20ID:MYuplL5h838デフォルトの名無しさん
2024/07/13(土) 17:43:27.19ID:mV5TIlCk >>831
意味でなく形式に拘るなら「事後要件を弱めてはいけない」などのルールは、要件がプログラム等の形式で表現されない限りLSPの評価の土台にすら上がらないってことにならない?
Cloneトレイトは公式のドキュメントに
// Required method
fn clone(&self) -> Self;
Returns a copy of the value.
とあって、exampleでは実際に assert_eq を使って説明しているので、この説明を元にCloneトレイトを実装する型の妥当性を判断して良いように思う
これでもまだ「それは意味論上のものでしかない」というなら、逆にそれをクリアしてクラス間の振る舞いを示している現実的な例を教えてくれ
意味でなく形式に拘るなら「事後要件を弱めてはいけない」などのルールは、要件がプログラム等の形式で表現されない限りLSPの評価の土台にすら上がらないってことにならない?
Cloneトレイトは公式のドキュメントに
// Required method
fn clone(&self) -> Self;
Returns a copy of the value.
とあって、exampleでは実際に assert_eq を使って説明しているので、この説明を元にCloneトレイトを実装する型の妥当性を判断して良いように思う
これでもまだ「それは意味論上のものでしかない」というなら、逆にそれをクリアしてクラス間の振る舞いを示している現実的な例を教えてくれ
839デフォルトの名無しさん
2024/07/13(土) 22:57:22.69ID:ZTGyFNne >>838
それは単純な例だから上手くいってるように思い込めるんじゃないかな
例えばclassの場合はもっと複雑な例になってもsuperclassのコードと挙動が実際にあり
それとsubclassの挙動や(必要なら)コードと照らし合わせて判定できるよ
しかしtraitにはそれがないからドキュメントや付加assertなど一段上のメタ情報を用いなければ何も進めることができない
したがってLSPの枠組みと似てる面はあっても別物
それは単純な例だから上手くいってるように思い込めるんじゃないかな
例えばclassの場合はもっと複雑な例になってもsuperclassのコードと挙動が実際にあり
それとsubclassの挙動や(必要なら)コードと照らし合わせて判定できるよ
しかしtraitにはそれがないからドキュメントや付加assertなど一段上のメタ情報を用いなければ何も進めることができない
したがってLSPの枠組みと似てる面はあっても別物
840デフォルトの名無しさん
2024/07/14(日) 04:00:15.58ID:xmUtANA3 知らんけど
JavaとかC#の世界でも、interfaceが実装者に要求する条件を実装者が実際には満たさない、って場合にLSP違反って言われるの?
ならRustのtraitでも同じこと言ってよさそうだけど、多分言わんよな
JavaとかC#の世界でも、interfaceが実装者に要求する条件を実装者が実際には満たさない、って場合にLSP違反って言われるの?
ならRustのtraitでも同じこと言ってよさそうだけど、多分言わんよな
841デフォルトの名無しさん
2024/07/14(日) 05:23:41.72ID:QaC7oPd0 継承なしのカプセル化だけなら普通のC言語でもできるし、再コンパイルの問題(変更を加えたファイルだけを再コンパイルすればいいという原則の破れ)も発生しない
それがそのままライブラリやオブジェクトの単位になったんじゃないの
それがそのままライブラリやオブジェクトの単位になったんじゃないの
842デフォルトの名無しさん
2024/07/14(日) 06:49:30.82ID:ma8dE8UE 文系:xとは未知のもの
厨房:いや未知のものはyやろ
理系:未知のものはfですdf/dx=g(f)を解きます
厨房:いや未知のものはyやろ
理系:未知のものはfですdf/dx=g(f)を解きます
843デフォルトの名無しさん
2024/07/14(日) 07:37:29.94ID:iqWqiKXK >>841
Rustのtraitにはクラスのような継承はないけど、抽象的なコードを継承できるよ
Rustのtraitにはクラスのような継承はないけど、抽象的なコードを継承できるよ
844デフォルトの名無しさん
2024/07/14(日) 07:37:59.13ID:iqWqiKXK 例えば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
}
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
}
845デフォルトの名無しさん
2024/07/14(日) 07:39:51.02ID:iqWqiKXK 未知のIteratorであっても重複コードを書くことなく自動的にこのfoldメソッドが使える
846デフォルトの名無しさん
2024/07/14(日) 07:40:10.97ID:iqWqiKXK クラスのメソッド継承との決定的な違いは、このコードにメンバー変数は一切登場せず、つまりいかなる構成の型からも独立した抽象的なコードであること
847デフォルトの名無しさん
2024/07/14(日) 09:23:36.10ID:JssLuzWj fold って next とどうちがうん
848デフォルトの名無しさん
2024/07/14(日) 10:13:20.02ID:aq5pPuoi >>847
nextはイテレーターを一つ進めるもの、foldやreduceはイテレーターに対して畳み込みを行うもの
例えば「配列内の全ての数値を足し合わせる」とか「全ての数値を掛け算する」「配列内の文字列を全て連結する」いった操作を行うものだよ
この類のものは他の言語でも使われるし、簡潔なコードを書けるようになるから知っておくと良いよ
配列等のコンテナに対して一般に map, filter, reduce と呼ばれる操作があって、そのうちreduceは「要素を畳み込んで1つの値にする」もの
畳み込む方法を関数で渡すもので、概念的には [1, 2, 3].reduce(add) や [1, 2, 3].reduce(multiply) のような形になる
渡す関数は関数のほかクロージャ (言語によってはラムダ式とも) も使える
こんな感じに抽象化するとfor文を使わなくて済むし、何をやってるかが明確になる
nextはイテレーターを一つ進めるもの、foldやreduceはイテレーターに対して畳み込みを行うもの
例えば「配列内の全ての数値を足し合わせる」とか「全ての数値を掛け算する」「配列内の文字列を全て連結する」いった操作を行うものだよ
この類のものは他の言語でも使われるし、簡潔なコードを書けるようになるから知っておくと良いよ
配列等のコンテナに対して一般に map, filter, reduce と呼ばれる操作があって、そのうちreduceは「要素を畳み込んで1つの値にする」もの
畳み込む方法を関数で渡すもので、概念的には [1, 2, 3].reduce(add) や [1, 2, 3].reduce(multiply) のような形になる
渡す関数は関数のほかクロージャ (言語によってはラムダ式とも) も使える
こんな感じに抽象化するとfor文を使わなくて済むし、何をやってるかが明確になる
849デフォルトの名無しさん
2024/07/14(日) 10:32:15.39ID:iqWqiKXK 言語によって呼び名や使い分けが微妙に異なるけど
Rustでは2種類をこう呼び分けています
foldは初期値を別途指定する万能型の畳み込み
reduceは初期値が最初の要素となる畳み込み
Rustでは2種類をこう呼び分けています
foldは初期値を別途指定する万能型の畳み込み
reduceは初期値が最初の要素となる畳み込み
850デフォルトの名無しさん
2024/07/14(日) 10:33:24.33ID:iqWqiKXK そして万能型の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))
}
このような特定の型の構造に依存しない抽象的なコードが
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))
}
851デフォルトの名無しさん
2024/07/14(日) 11:05:51.89ID:iqWqiKXK なぜ二種類あるのか?というと
長さ0だと最初の要素すらないため
reduceはOption型が返る特徴があります
例えば和を求める場合でも
長さ0だったらNoneになってほしいならば
reduce(|sum, n: i32| sum + n)
長さ0なら和が0となってほしいならば
fold(0, |sum, n: i32| sum + n)
と使い分けることができます
ちなみに後者はsum()メソッドが用意されています
長さ0だと最初の要素すらないため
reduceはOption型が返る特徴があります
例えば和を求める場合でも
長さ0だったらNoneになってほしいならば
reduce(|sum, n: i32| sum + n)
長さ0なら和が0となってほしいならば
fold(0, |sum, n: i32| sum + n)
と使い分けることができます
ちなみに後者はsum()メソッドが用意されています
852デフォルトの名無しさん
2024/07/14(日) 11:33:51.37ID:iqWqiKXK853デフォルトの名無しさん
2024/07/14(日) 12:47:51.97ID:JssLuzWj854デフォルトの名無しさん
2024/07/14(日) 12:50:40.22ID:JssLuzWj855デフォルトの名無しさん
2024/07/14(日) 12:54:55.73ID:JssLuzWj >>850
python の reduce は初期値を [0] にするのも任意に設定するのも
同じ reduce という名前でいけるのが
Rust だと reduce と fold で使い分ける必要があるということね
Rust が面倒だと言うことは理解した
python の reduce は初期値を [0] にするのも任意に設定するのも
同じ reduce という名前でいけるのが
Rust だと reduce と fold で使い分ける必要があるということね
Rust が面倒だと言うことは理解した
856デフォルトの名無しさん
2024/07/14(日) 13:21:58.79ID:iqWqiKXK >>855
そういうことではないよ
RustではOption型やResult型でエラーや異常値を含めて正しい状況を値として得られるんだよ
例えば長さ0で初期値なしの時に
Pythonだとエラーだよね
Rustは常に値として返してくれて今回はOption<Self::Item>型
そういうことではないよ
RustではOption型やResult型でエラーや異常値を含めて正しい状況を値として得られるんだよ
例えば長さ0で初期値なしの時に
Pythonだとエラーだよね
Rustは常に値として返してくれて今回はOption<Self::Item>型
857デフォルトの名無しさん
2024/07/14(日) 14:06:11.77ID:CpW1/GRz858デフォルトの名無しさん
2024/07/14(日) 14:15:44.82ID:iqWqiKXK Rustならrev().fold(...)だね
859デフォルトの名無しさん
2024/07/14(日) 15:28:53.80ID:QaC7oPd0 テンプレートが出てきたあたりからC++の勉強をやめたのだけど
これは「型を引数に取ってインスタンス化する」ということでおk?
それがトレイトをまたいだ場合、いつどこで誰が何してるか分からなくなる
ファイルをまたぐインライン関数みたいにソースレベルでなされること?
これは「型を引数に取ってインスタンス化する」ということでおk?
それがトレイトをまたいだ場合、いつどこで誰が何してるか分からなくなる
ファイルをまたぐインライン関数みたいにソースレベルでなされること?
860デフォルトの名無しさん
2024/07/14(日) 16:59:00.63ID:Q38o8Kq2 >>840
JavaとかC#の世界でも、interfaceが実装者に要求する条件を実装者が実際には満たさない、って場合にLSP違反って言われるの?
言われるよ
リスコフ本人が書いたJavaの本にも書いてある
JavaとかC#の世界でも、interfaceが実装者に要求する条件を実装者が実際には満たさない、って場合にLSP違反って言われるの?
言われるよ
リスコフ本人が書いたJavaの本にも書いてある
861デフォルトの名無しさん
2024/07/14(日) 17:32:49.60ID:Q38o8Kq2 >>839
>ドキュメントや付加assertなど一段上のメタ情報を用いなければ何も進めることができない
一段上のメタ情報であるspecificaitonを使いなさいというのがリスコフの教え
それがBehavioral SubtypingってものでLSPが伝えようとしてる原則だよ
>ドキュメントや付加assertなど一段上のメタ情報を用いなければ何も進めることができない
一段上のメタ情報であるspecificaitonを使いなさいというのがリスコフの教え
それがBehavioral SubtypingってものでLSPが伝えようとしてる原則だよ
862デフォルトの名無しさん
2024/07/14(日) 20:15:07.35ID:QaC7oPd0 ああ、なんだ
クレート=ELFファイルだと思ってたけど違うのね
クレート=ELFファイルだと思ってたけど違うのね
863デフォルトの名無しさん
2024/07/14(日) 23:33:04.31ID:jL63bGYb もちろんクレートはコンパイルしてELFに出来得る
865デフォルトの名無しさん
2024/07/15(月) 01:06:24.34ID:qZQFNGwo LLVMのバックエンドにCOFFもあるよ
866デフォルトの名無しさん
2024/07/15(月) 01:09:28.33ID:RXziJOxB LLVMの役割
ELFもCOFFもXCOFFもいける
ELFもCOFFもXCOFFもいける
867デフォルトの名無しさん
2024/07/15(月) 01:55:53.37ID:S6UfnUI4 >>860-861
なるほどね、本当に特定の言語処理系の型システムの実装が云々というところからは離れたところにある概念なんだ
あえて関連付けるなら、型システムの部分型付け関係がbehavioral subtypingにもなるように定義すべきであると
上位型が具体型であるために暗黙の条件が多数想定される状況では特にLSPを意識すべきだが、それに限定される概念ではないと
なるほどね、本当に特定の言語処理系の型システムの実装が云々というところからは離れたところにある概念なんだ
あえて関連付けるなら、型システムの部分型付け関係がbehavioral subtypingにもなるように定義すべきであると
上位型が具体型であるために暗黙の条件が多数想定される状況では特にLSPを意識すべきだが、それに限定される概念ではないと
868デフォルトの名無しさん
2024/07/15(月) 02:35:13.63ID:fmM+TfOR supertypeの実装がない場合は
LSPの不変条件・事前条件・事後条件などsubtypeの実装と比較しようがなく
LSPの対象になりようがないよね
LSPの不変条件・事前条件・事後条件などsubtypeの実装と比較しようがなく
LSPの対象になりようがないよね
869デフォルトの名無しさん
2024/07/15(月) 03:42:20.85ID:csp8v2ux docs.rs の左上のRマーク
今話題のRen4のマークに似てるね
今話題のRen4のマークに似てるね
870デフォルトの名無しさん
2024/07/15(月) 09:46:03.12ID:kpV4D65H コレクションしないんだから狭義には参照カウンタはGCとは言えない。
広義には含めてやってもいいが。
広義には含めてやってもいいが。
871デフォルトの名無しさん
2024/07/15(月) 11:20:28.28ID:qZQFNGwo ライブラリは.rlibまたは.rmetaで、これもELFやCOFFとは別物
ふむ
ふむ
872 警備員[Lv.1][新芽]
2024/07/15(月) 11:29:04.89ID:omk2e105 たしかにRマークってRustから周りのやつ外したような感じじゃん
873デフォルトの名無しさん
2024/07/15(月) 11:58:24.83ID:K85WsTqt Ren4のRマークはsans-serifのゴシック体だからRustのロゴとは全然違うだろ
本人のやる気、こだわりのなさをフォントで表現してるんだから
RustのRと一緒にしたら双方に失礼
本人のやる気、こだわりのなさをフォントで表現してるんだから
RustのRと一緒にしたら双方に失礼
874デフォルトの名無しさん
2024/07/15(月) 13:14:40.10ID:ZO/EZAih 単に好みの問題だけど
ウィルスっぽくて気持ち悪い
好きじゃない
ウィルスっぽくて気持ち悪い
好きじゃない
875デフォルトの名無しさん
2024/07/15(月) 14:14:44.43ID:ko+PCaVU >>874
元々サビ菌がモチーフやからしゃーない
元々サビ菌がモチーフやからしゃーない
876デフォルトの名無しさん
2024/07/15(月) 18:49:44.14ID:GgRIn2WF 独裁者にも見た目がダサい奴がよくいるけど言っても無駄だ
デザインの力とは全然違う別の力でねじ伏せてくる
デザインの力とは全然違う別の力でねじ伏せてくる
877デフォルトの名無しさん
2024/07/15(月) 19:16:07.61ID:Vjas5sQD ダサいという指摘に理由を説明しても、ダサいことは変わらないんだよな
言語がダサければ信者もダサい
うだうだ言いながらダサい服着てそう
言語がダサければ信者もダサい
うだうだ言いながらダサい服着てそう
878デフォルトの名無しさん
2024/07/15(月) 22:03:42.65ID:e+J3OGv0 イテレータ要素をヒープに格納するにはこれでいいんか
.fold(Vec::new(), |mut v, t| { v.push(t); v })
.fold(Vec::new(), |mut v, t| { v.push(t); v })
879デフォルトの名無しさん
2024/07/15(月) 22:12:32.29ID:S6UfnUI4 またイテレータの話してる
880デフォルトの名無しさん
2024/07/15(月) 22:50:12.36ID:9YaXaz6n >>878
collectしろや
collectしろや
881デフォルトの名無しさん
2024/07/15(月) 23:25:29.58ID:wT4qVw/w >>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<_>>();
分かって書いてるかもだけど一応
let v = (0..10).collect::<Vec<i32>>();
コンテナにまとめるならこんな感じに collect を使う
例えば文字を走査するイテレーターをStringにcollectするようなことも可
型パラメーターは推論が効くのでそれに任せても良い
左辺に情報があるならcollectの型パラメーターはいらない
let v: Vec<i32> = (0..10).collect();
要素の型が分かるなら、右辺のコンテナの中身は_で推論させても良い
let v = (0i32..10).collect::<Vec<_>>();
882デフォルトの名無しさん
2024/07/15(月) 23:35:20.09ID:nug4GWMJ クロージャにキャプチャさせれば既存ベクタへ格納も追加もできる
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<_>>();
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<_>>();
883デフォルトの名無しさん
2024/07/16(火) 23:25:36.51ID:ab19AXDr Foo::from_iter(iter)でもいいね
例えばVec::from_iter(iter)
特にIntoIteratorな時にinto_iter()を省けて見やすいよ
例えばVec::from_iter(iter)
特にIntoIteratorな時にinto_iter()を省けて見やすいよ
884デフォルトの名無しさん
2024/07/17(水) 18:51:22.39ID:Hw1cPZyQ イテレータをcollectしたい場合と
イテレータではないIntoIteratorを別の構造体に変換したい場合とは文脈が違うでしょ
from_iterを直接呼ぶのは基本的に後者
前者の場合にターボフィッシュ書かなくてもいいという理由で
from_iterを直接呼ぶのはidiomaticではない
イテレータではないIntoIteratorを別の構造体に変換したい場合とは文脈が違うでしょ
from_iterを直接呼ぶのは基本的に後者
前者の場合にターボフィッシュ書かなくてもいいという理由で
from_iterを直接呼ぶのはidiomaticではない
885デフォルトの名無しさん
2024/07/17(水) 21:48:43.22ID:3eay5eeN 前者のケースでfrom_iterを直接呼んでても分かるから別にいいよ
自分で書くときはcollect使うけど
自分で書くときはcollect使うけど
886デフォルトの名無しさん
2024/07/17(水) 23:54:54.61ID:zgRAxdKk これは短い方がいい
let x = HashMap::<_, _>::from_iter(vec);
let x = vec.into_iter().collect::<HashMap::<_, _>>();
let x = HashMap::<_, _>::from_iter(vec);
let x = vec.into_iter().collect::<HashMap::<_, _>>();
887デフォルトの名無しさん
2024/07/17(水) 23:55:29.92ID:zgRAxdKk これはほぼ長さ変わらないからどちらがわかりやすいか
let x = HashMap::<_, _>::from_iter(iter);
let x = iter.collect::<HashMap::<_, _>>();
let x = HashMap::<_, _>::from_iter(iter);
let x = iter.collect::<HashMap::<_, _>>();
888デフォルトの名無しさん
2024/07/18(木) 01:10:31.87ID:CNIyJc+8 どちらも一度変数で受ける形になるので型アノテーションが必要なら
let x: HashMap<_, _> のように基本的には左辺に書く
HashMapなら型パラメータ部分も推論に頼らず
明示的に書くことのほうが多いかもしれない
イテレータをcollectしたい場合というのは
イテレータのメソッドチェーンで各種処理をしてから
最終的にcollectする形になることが多いから
from_iterの直呼びじゃなくcollectが好まれる
let x: HashMap<_, _> のように基本的には左辺に書く
HashMapなら型パラメータ部分も推論に頼らず
明示的に書くことのほうが多いかもしれない
イテレータをcollectしたい場合というのは
イテレータのメソッドチェーンで各種処理をしてから
最終的にcollectする形になることが多いから
from_iterの直呼びじゃなくcollectが好まれる
889デフォルトの名無しさん
2024/07/18(木) 02:40:28.19ID:0QBRSK+b ところでchronoって、しょっちゅうAPIが変わるし
やたら冗長な書き方になるし結構クソじゃない?
やたら冗長な書き方になるし結構クソじゃない?
890デフォルトの名無しさん
2024/07/18(木) 12:05:40.95ID:WL/aeG4d 書き方が気に入らないならtime-rsを試してみたら?
891デフォルトの名無しさん
2024/07/18(木) 21:07:48.37ID:2m7Ost/Q なるほど
trait Iterator {
type Item;
fn collect<B: FromIterator<Self::Item>>(self) -> B
where
Self: Sized,
{
FromIterator::from_iter(self)
}
}
trait Iterator {
type Item;
fn collect<B: FromIterator<Self::Item>>(self) -> B
where
Self: Sized,
{
FromIterator::from_iter(self)
}
}
892デフォルトの名無しさん
2024/07/18(木) 23:31:33.62ID:GQ1B8wHA 代数的データ型ってなんかすごいけど知名度がモナドより低いな
893デフォルトの名無しさん
2024/07/19(金) 02:03:52.09ID:MUvBupZH >>890
使ってみたけど、time-rsいいね
いつのまにかダウンロード数でchronoを上回る競合があったとは知らんかった
タイムゾーンの扱いがやや簡略化されてるけど、夏時間のない日本人的には問題ない
月を直接intで指定できないのが英語仕様やな……ってちょっと気になる
使ってみたけど、time-rsいいね
いつのまにかダウンロード数でchronoを上回る競合があったとは知らんかった
タイムゾーンの扱いがやや簡略化されてるけど、夏時間のない日本人的には問題ない
月を直接intで指定できないのが英語仕様やな……ってちょっと気になる
894デフォルトの名無しさん
2024/07/19(金) 03:51:08.70ID:riLGg6QV >>891
この各収納先への移譲と両側のトレイト境界が汎用化の肝
trait FromIterator<A>: Sized {
fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self;
}
この各収納先への移譲と両側のトレイト境界が汎用化の肝
trait FromIterator<A>: Sized {
fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self;
}
895デフォルトの名無しさん
2024/07/19(金) 06:06:24.35ID:LryDU6eW Rustはジェネリックとトレイト境界と抽象的なデフォルト実装のおかげで
安全で利便性の高いコードの汎用共通化に成功していますね
安全で利便性の高いコードの汎用共通化に成功していますね
896デフォルトの名無しさん
2024/07/19(金) 23:21:36.34ID:rC6z5NUh cloud strike のはテロルやね
897デフォルトの名無しさん
2024/07/19(金) 23:30:11.35ID:rC6z5NUh898デフォルトの名無しさん
2024/07/19(金) 23:52:20.75ID:8WlCJE3Q >>897
エラーとなりますた
エラーとなりますた
899デフォルトの名無しさん
2024/07/20(土) 00:12:48.41ID:bNknJoN/ >>896
ウィルスバスター以来の快挙やね
ウィルスバスター以来の快挙やね
900デフォルトの名無しさん
2024/07/20(土) 14:16:49.05ID:F167yFzL901デフォルトの名無しさん
2024/07/20(土) 23:38:20.92ID:6EAP68vq902デフォルトの名無しさん
2024/07/21(日) 01:48:23.56ID:eUhj6//q ★┷┓
┃D┃
┃D┃
┃K┃
┃で┃
┃も┃
┃r┃
┃u┃
┃s┃
┃t┃
┃が┃
┃使┃
┃え┃
┃ま┃
┃す┃
┃よ┃
┃う┃
┃に┃
┗━★
┃D┃
┃D┃
┃K┃
┃で┃
┃も┃
┃r┃
┃u┃
┃s┃
┃t┃
┃が┃
┃使┃
┃え┃
┃ま┃
┃す┃
┃よ┃
┃う┃
┃に┃
┗━★
903デフォルトの名無しさん
2024/07/21(日) 09:43:03.00ID:QhoywuRk904デフォルトの名無しさん
2024/07/21(日) 10:14:17.60ID:TGGT0XLq とあるライブラリに変な癖があるという話は
どの言語でもあるからそういう話ではないだろ
どの言語でもあるからそういう話ではないだろ
905デフォルトの名無しさん
2024/07/21(日) 10:29:10.85ID:U3c7smqS イテレータ使ったことない
906デフォルトの名無しさん
2024/07/21(日) 10:35:28.58ID:W0nR4Dwz >>903
Rustはその点シンプルでクセもなく覚えやすい
基本的に複数の要素ならFromIterator
VecでもHashMapでも何でもいける
複数のcharやstrなどからString作成もいける
複数のstrやStringやPathなどからPathBuf作成もいける
Fromは基本的に単独要素や配列(=静的固定長)から他へ変換
Rustはその点シンプルでクセもなく覚えやすい
基本的に複数の要素ならFromIterator
VecでもHashMapでも何でもいける
複数のcharやstrなどからString作成もいける
複数のstrやStringやPathなどからPathBuf作成もいける
Fromは基本的に単独要素や配列(=静的固定長)から他へ変換
907デフォルトの名無しさん
2024/07/21(日) 11:03:59.33ID:BMrg5vDt908デフォルトの名無しさん
2024/07/21(日) 11:04:04.35ID:xuKRyHnL >>903
それくらいchatGPTで教えてもらえるだろ
それくらいchatGPTで教えてもらえるだろ
909デフォルトの名無しさん
2024/07/21(日) 11:14:46.17ID:BMrg5vDt >>908
俺もそう思って試してみたけど駄目だね
エラーの簡単な原因とcollect使えみたいな代替案は出してくるけど
根本的な理解につながる答えを返せないだけでなくいろいろと間違った情報を返してくる
俺もそう思って試してみたけど駄目だね
エラーの簡単な原因とcollect使えみたいな代替案は出してくるけど
根本的な理解につながる答えを返せないだけでなくいろいろと間違った情報を返してくる
910デフォルトの名無しさん
2024/07/21(日) 11:48:09.12ID:W0nR4Dwz from_iter(array)で済むのに
なぜ配列からHashMapへのFromがあるのか理由はおそらく
配列からmoveするinto_iter()が数年前までなかったためだと思う
今は配列を含めて要素が複数なら→イテレータ利用→FromIteratorと覚えればよいかと
なぜ配列からHashMapへのFromがあるのか理由はおそらく
配列からmoveするinto_iter()が数年前までなかったためだと思う
今は配列を含めて要素が複数なら→イテレータ利用→FromIteratorと覚えればよいかと
911デフォルトの名無しさん
2024/07/21(日) 11:54:05.33ID:9I2odrUJ そもそもイテレーターとコンテナの概念を勘違いしてる可能性ありそう
別種のコンテナ同士の変換は (特別な対応がない限り) 直接的には無理で、イテレーターを介して中身の要素を走査すれば渡せるということ
みかん箱を冷蔵庫に変換することはできないけど、箱の中のみかんを1つずつ取り出して、それを冷蔵庫型に纏める (collect) ことはできるような感じ
別種のコンテナ同士の変換は (特別な対応がない限り) 直接的には無理で、イテレーターを介して中身の要素を走査すれば渡せるということ
みかん箱を冷蔵庫に変換することはできないけど、箱の中のみかんを1つずつ取り出して、それを冷蔵庫型に纏める (collect) ことはできるような感じ
912デフォルトの名無しさん
2024/07/21(日) 12:08:53.38ID:QhoywuRk 今回は >>910 さんをベストアンサーとさせて頂きます
みなさんご協力ありがとうございました
みなさんご協力ありがとうございました
レス数が900を超えています。1000を超えると表示できなくなるよ。
ニュース
- 小野田紀美・経済安保担当相「何か気に入らないことがあればすぐに経済的威圧をする国への依存はリスク」 ★2 [Hitzeschleier★]
- 日本行き空路49万件キャンセル 中国自粛呼びかけ 日本行きチケット予約の約32%に相当 ★2 [ぐれ★]
- 【中国局長】両国関係に「深刻な影響」 首相発言の撤回要求 [蚤の市★]
- 外務省局長は無言で厳しい表情…日中の高官協議終了か 高市首相“台湾”発言で中国が強硬対応 発言撤回求めたか…★3 [BFU★]
- 【卓球】早田ひな、「総額100万スられた」「ずっと憧れていたスペインとイタリア…」ヨーロッパ旅行で悲劇 スリ被害を告白 [muffin★]
- 【インバウンド】中国人観光客の日本での消費額は年間約2兆円超…中国政府は公務員の出張取り消し [1ゲットロボ★]
- 産経新聞「高市早苗の答弁さぁ……思慮が足りてなくね?官僚と詰めずに思いつきで話しているでしょ」 [175344491]
- 【実況】博衣こよりのえちえち歌枠🧪
- 【高市速報】日本人の3割「中国への武力行使に踏み切る必要がある」ANN世論調査 [931948549]
- 【雑談】暇人集会所part18
- 高市早苗「支持者の理解を得られないので台湾発言を撤回できない」 [931948549]
- 外務省局長、よくわからないまま帰国へ [834922174]
