Rust part27

■ このスレッドは過去ログ倉庫に格納されています
1デフォルトの名無しさん
垢版 |
2024/12/02(月) 22:32:50.31ID:D+1pIyvG
公式
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 part26
https://mevius.5ch.net/test/read.cgi/tech/1726838318/

ワッチョイスレ
プログラミング言語 Rust 4【ワッチョイ】
https://mevius.5ch.net/test/read.cgi/tech/1514107621/
2024/12/04(水) 20:50:21.75ID:H1WoIidK
>>48
C++が悪いということ?
2024/12/04(水) 21:15:04.07ID:9m5UuMRD
Webページ毎に別なので
アリーナ的管理により循環参照があろうと一気に解放するためリークが起きようがない
2024/12/04(水) 22:53:20.36ID:mxpvKjAM
メモリリークと脆弱性の混合物なら急を要するが完全に分離されたから意識低くなった
52デフォルトの名無しさん
垢版 |
2024/12/04(水) 23:26:00.62ID:dIFgKrXU
>>48
悪いっていうより、自由が利きやすいんじゃない
53デフォルトの名無しさん
垢版 |
2024/12/05(木) 21:10:58.63ID:qJrgBNQF
iterator traitのnextでiteratorの中のデータの参照を返すことがどうしてもできません
教えてください
2024/12/05(木) 21:32:40.26ID:xceXpzKh
>>53
コードで出して。
2024/12/05(木) 21:37:09.52ID:nBO5q7w2
>>53
lending iteratorでググるといい
2024/12/05(木) 23:37:21.58ID:cvEJUy50
// まず、データを保持する構造体を定義
struct DataHolder {
items: Vec<String>,
}

// イテレータ構造体を定義
// ライフタイムパラメータ 'a を使って、参照の寿命を明示
struct DataIterator<'a> {
data: &'a DataHolder, // データへの参照
index: usize, // 現在の位置
}

// DataHolderにイテレータを作成するメソッドを実装
impl DataHolder {
fn new() -> Self {
DataHolder {
items: vec![String::from("one"), String::from("two"), String::from("three")],
}
}

// イテレータを返すメソッド
fn iter(&self) -> DataIterator {
DataIterator {
data: self,
index: 0,
}
}
}
2024/12/05(木) 23:38:23.20ID:cvEJUy50
// Iteratorトレイトの実装
impl<'a> Iterator for DataIterator<'a> {
// 返り値の型を&'a Stringと指定
type Item = &'a String;

fn next(&mut self) -> Option<Self::Item> {
if self.index < self.data.items.len() {
let item = &self.data.items[self.index];
self.index += 1;
Some(item)
} else {
None
}
}
}

// 使用例
fn main() {
let holder = DataHolder::new();

// イテレータを使用
for item in holder.iter() {
println!("{}", item);
}
}

やりたいことはこんな感じ?
58デフォルトの名無しさん
垢版 |
2024/12/06(金) 07:47:51.83ID:tRnxKL09
こんな感じです
struct It<'a>{
i: &'a mut i32
}

impl<'a> Iterator for It<'a>{
type Item= &'a i32;
fn next(&mut self)->Option<Self::Item>{
Some(self.i)
}
}
2024/12/06(金) 10:39:26.47ID:zw4qy2EX
mut いらん
2024/12/06(金) 10:45:37.08ID:7cNjBV3c
iter()が作りたいのか、iter_mut()が欲しいのかどっちかな?
あとこれだと無限に続くイテレータになるけど終了条件は?
61デフォルトの名無しさん
垢版 |
2024/12/06(金) 12:04:36.97ID:tRnxKL09
struct It<'a>{
i: &'a mut i32
}

impl<'a> Iterator for It<'a>{
type Item= &'a i32;
fn next(&mut self)->Option<Self::Item>{
self.i+=1;
Some(self.i)
}
}
こんな感じなのでmutはいります
本当はiter_mutが作りたいけれど難しそうなので
iterを作ろうとしたけれどどうしても出来ません
初心者です教えてください
62デフォルトの名無しさん
垢版 |
2024/12/06(金) 12:07:14.30ID:tRnxKL09
すいません*つけわすれました
63デフォルトの名無しさん
垢版 |
2024/12/06(金) 12:08:12.03ID:tRnxKL09
>>60
終了条件は25です
2024/12/06(金) 12:19:03.26ID:B3lagOoh
結局毎回同じ参照返すならイテレータじゃなくてよくね
2024/12/06(金) 12:49:52.12ID:B2jbh63z
自分の可変参照を返したいならGATでこうする
use lending_iterator::prelude::*;

fn main() {
let mut v: Vec<String> = ["a", "b", "c", "d", "e"].into_iter().map(str::to_string).collect();
my_iter_mut(&mut v)
.skip(1)
.take(3)
.for_each(|s| s.push('x'));
assert_eq!(v, ["a", "bx", "cx", "dx", "e"]);
}

fn my_iter_mut<'a, T>(slice: &'a mut [T]) -> MyIterMut<'a, T> {
MyIterMut { slice, index: 0 }
}
struct MyIterMut<'a, T> {
slice: &'a mut [T],
index: usize,
}

#[gat]
impl<'a, T> LendingIterator for MyIterMut<'a, T> {
type Item<'next> where Self : 'next = &'next mut T;
fn next(self: &'_ mut MyIterMut<'a, T>) -> Option<Item<'_, Self>> {
if self.index < self.slice.len() {
self.index += 1;
Some(&mut self.slice[self.index - 1])
} else {
None
}
}
}
2024/12/06(金) 17:58:05.19ID:B2jbh63z
>>65
自己レス
即興で作って冗長な表記があったため
next()関数はこれで

fn next(&mut self) -> Option<Item<'_, Self>> {
(self.index < self.slice.len()).then(|| {
let nth = &mut self.slice[self.index];
self.index += 1;
nth
})
}
2024/12/06(金) 18:45:17.16ID:OtZyNvR4
>>61
next()で返された不変参照r1(&i32)が生きてる間に次のnext()が呼ばれたら
r1の参照先の値が変わることになるからこの形はIteratorだと実現できないな
同じ値に対する&Tと&mut Tが共存できないルールに引っかかる

next()の戻り値にIt自体のライフタイム(&'b mut selfの'b)を含めて
戻り値の参照が存在してる間は次のnext()を呼べない形にしないといけないけど
Iteratorはそういう制限を想定してない
2024/12/07(土) 00:37:25.75ID:MlZHBv1+
Vecなどを作れて逆順にもできるイテレータとは性質が異なる
異なるものを、どっちも同じだと頑なに主張し続ける必要はない気がする
2024/12/07(土) 02:06:00.13ID:TKfUhpHo
67は一般的なイテレータの概念じゃなくstd::iter::Iteratorの話
このtraitを実装すると例えばIterator::max()も自動的に使えるようになるけど
この実装はSelf::Itemの暫定の最大値を保持しながら次のnextを呼ぶ必要がある
前の値を解放しないと次のnextを使えない状態だと
std::iter::Iteratorが使用者側に保証してる条件を満たせないし
安全なコードの範囲でimpl Iteratorのコンパイルも通せない

自前のIteratorトレイトを用意してもいいけど
それだとstd::iter::Iteratorが要求される処理には使えなくなる
2024/12/07(土) 08:46:15.51ID:4WGAo47f
>>68
Vecを作れるのも逆順も全て別の話
それぞれ別の要件を備えていないと一般的なイテレータではどちらも不可能
例えばイテレータ「1..」はVecを作れない&逆順に呼ぶのも無理
std::iter::repeat(1)はVecを作れないがDoubleEndedIteratorを実装しているのでメソッドrev()が使えて逆順に呼べる!
自己可変参照を返す>>65のMyIterMutはスライス&mut [T]を内部に持っているため逆順呼び出しrev()メソッドの実装が可能
2024/12/07(土) 09:01:24.50ID:4WGAo47f
>>69
そのmax()は自動的に全てのイテレータに使えるわけではない
Self::Itemがstd::cmp::Ordを実装している時のみ使える
前の値を保持したままにできるか否かの性質についてもmarker traitを用意することで同じ枠組みに組み込めた可能性がある
それを出来ていないのがstd::iter::Iteratorの欠陥なので他を併用するのがRustでは当たり前になっている
2024/12/07(土) 09:28:12.85ID:4WGAo47f
イテレータの前の値を保持できるか否かのどちらが優れているかといえば
より効率的な機能を提供できる点で「前の値を保持できない」方が優れた機能を提供できる
例えばstd::io::BufReadのlines()を考えてみよう
毎回新たなStringを返してくるので前の値を保持できる仕様となっている
しかしlines()の利用で前の値なんて不要なことも多いからその観点からは無駄な仕様ともいえる
一方で「前の値を保持できない」性質にも対応出来ていたとしたら同じStringを使い回すことが出来て明らかに効率が良い
このような例は多数あり自己参照返しイテレータが別途必要とされて使われている理由である
2024/12/07(土) 12:31:06.78ID:MlZHBv1+
>>70
長さが有限でも実行時にメモリが足りなければVecもreverseもないけど
「実行時に」という要件は備えなくて良いというルールがあるんだよね?
2024/12/07(土) 12:55:43.06ID:TKfUhpHo
61(初心者)が実現できないimpl Iteratorで詰まってるんだから
できない理由を分かってもらうのが優先でしょ
イテレータの優劣とか代替案はその後でいい
2024/12/07(土) 13:24:25.81ID:4WGAo47f
>>73
rev()メソッドのtrait DoubleEndedIteratorはゼロコスト抽象化
逆順に並べ替えることはしないのでそのためのメモリは必要ない
既にある任意の構造を後ろからたどる、あるいは、後ろから計算するだけ
2024/12/07(土) 13:35:30.31ID:4WGAo47f
>>74
それならば別の条件が必要となるIterator::max()を事例に出すのはよろしくないかな
説明するためには単純にこれだけでいいよ
let first = iter.next();
let second = iter.next();
println!("{first:?} {second:?}");
2024/12/07(土) 14:11:16.76ID:TKfUhpHo
>>76
next2回呼ぶだけだとstd::iter::Iteratorと関係なくなるだろ
自分がそういう使い方をしなければ問題ないってなるだけ

maxはstd::iter::Iteratorの実装に求められる条件の分かりやすい例として挙げた
別の条件まで気にするならmax_byでもいいけどそれはそれで初心者には余計なノイズが増える
2024/12/07(土) 14:52:07.98ID:MlZHBv1+
コピーもcloneもできないデータの存在自体がノイズだね
本当はcloneできるんだけどゼロコストではできないとか言ってるのもノイズだ
2024/12/07(土) 15:42:48.47ID:YxUwNEYs
結局>>53は何がしたかったのか
2024/12/07(土) 16:58:02.14ID:ikP3bVWr
>>67
stdのIterator::nextの&mut selfのライフタイムはnextメソッドを抜けるところまで
(次のnextが呼ばれるまで生きてない)

つまりstdのIteratorでは&mut selfのライフタイムに依存するような参照を返すことはできないということ
そういう参照を返したいならlending iterator
逆に言えば&mut selfのライフタイムに依存しない参照であればstdのIteratorでも返せるということ
2024/12/07(土) 17:27:34.95ID:4WGAo47f
>>77
max_byも同じ
Ord実装型そのものかOrd実装型に変換してOrd::cmp()できる時のみ利用できる
それらを持ち出さなくてもSelf::Itemの条件なくcollect()すなわち収納型へのFromIteratorが適用される
つまりfirst要素とsecond要素が同時に存在することになると矛盾の説明で十分となる
そのため自己参照を返すイテレータはstd::iter::Iteratorがカバーする範囲になく別途必要となる話をしてきた
2024/12/07(土) 17:32:25.17ID:4WGAo47f
>>78
イテレータが返すのはデータ値自体とは限らず参照も返す
特に今回の質問者が返したい可変参照は明確に!Cloneが定義されていてもちろん!Copyでもある
それでも可変参照をイテレータが返すことができてVecへ収容することも可能なのはCloneもコピーも行われないためだ
さらにそれらと全く独立した話としてイテレータ自体への参照/可変参照を返す場合はstd::iter::Iteratorで扱えないためLendingIteratorを使うという話が本題
2024/12/07(土) 18:53:41.33ID:MlZHBv1+
そんなに移動がしたいならこれでいい

first = into_next(iter); // iterはもう値を所有しない
second = into_next(first) // firstはもう値を所有しない
2024/12/07(土) 19:21:07.13ID:8M4lSePd
>>83
それによって新たにできるようになることや新たに生じるメリットは何?
2024/12/07(土) 21:52:51.51ID:MlZHBv1+
C++でもRustでも変わらないメリットはcloneとdropをしなくてすむことだが

そういえば、Rust固有のメリットは'aが出てこないことと
'staticも出てこないことだな
2024/12/08(日) 15:04:28.36ID:vgRddWB1
全然話変わるんだけどPinky Crush新曲のlowercase lifetimeってRust関係あるのかな
87デフォルトの名無しさん
垢版 |
2024/12/08(日) 22:46:56.54ID:y6R7+MXT
>>61
mutでないiterも出来なくて困ってるとのことなので
スライスのiter()と同じものがLendingIteratorを使わずに書けるよ

struct MyIter<'a, T>(&'a [T]);

fn my_iter<'a, T>(slice: &'a [T]) -> MyIter<'a, T> {
MyIter(slice)
}

impl<'a, T> std::iter::Iterator for MyIter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
if let [first, rest @ ..] = self.0 {
self.0 = rest;
Some(first)
} else {
None
}
}
}

fn main() {
let a = ["foo", "bar"];
let mut iter = my_iter(&a);
assert_eq!(iter.next(), Some(&"foo"));
assert_eq!(iter.next(), Some(&"bar"));
assert_eq!(iter.next(), None);
}
2024/12/09(月) 08:04:13.18ID:kf5GINDJ
組み込みFW屋さんなんだけどRustやってみようかな…
組み込み屋視点でRustはC++の何を解決してると思う?
組み込み屋なんて古いシステムばかりだからすぐに取って代わることは無いとは思うけど
年々複雑な製品を求められるから選択肢としては持っておきたい
2024/12/09(月) 09:11:23.41ID:bWuDC7pJ
zulip行けば?
ここにはカスしかおらん
2024/12/09(月) 09:29:03.77ID:1L49Pn1/
>>88
ダングリング参照を発見出来るだけ……とは言えそれが重要ではあるのだけど。
C++ は結局は人が気を付けなきゃならないことだらけで、複雑になると手におえない。
知ってることでも複雑に絡み合った状況では間違う。
C++ よりは機械的に検証可能な範囲を広げてるだけでもありがたいものだよ。
2024/12/09(月) 09:59:55.51ID:kf5GINDJ
>>90
え?マジ?
俄然興味湧いてきた
さっさと定時で帰って環境整えるか
2024/12/09(月) 10:35:05.93ID:URePCLgA
ビット幅気にするようなケースだと
数値型の暗黙の型変換がないとか演算時のオーバーフローの扱いを明示的に書けるとかが結構ありがたい
93デフォルトの名無しさん
垢版 |
2024/12/09(月) 13:24:01.49ID:wWCmXoxS
科学 + 5ch

【AI】AIはわずか2時間の対話で人間の性格をコピーできる [すらいむ★]
https://egg.5ch.net/test/read.cgi/scienceplus/1733576027/

コメントに面白いことが書かれている
94デフォルトの名無しさん
垢版 |
2024/12/09(月) 13:32:22.31ID:elhM3R9g
>>92
たしかに基礎的なことではあるがC/C++ではうっかり数値型の自動キャストでハマることもあるし
何よりも未定義動作が多くてこれも沼にハマる原因だな
それらを無くしたRustは賢明だ
95デフォルトの名無しさん
垢版 |
2024/12/09(月) 13:59:10.18ID:uh4vUAM3
釣れますか?
2024/12/09(月) 20:25:44.95ID:MZPPSq7i
struct RefMutex<'a, T>(&'a Mutex<T>);
impl<'a, T> Iterator for RefMutex<'a, T> {
type Item = std::sync::MutexGuard<'a, T>;
//略
}

try_lockが失敗したらループが止まります
マルチスレッドならランダムに止まります 知らんけど
2024/12/09(月) 20:57:28.00ID:bWuDC7pJ
FnMut() -> Option<T>っぽいあらゆる処理を全部Iterator化しようという気概を感じるな

近寄らんとこ
2024/12/09(月) 22:22:52.93ID:FjJr0oeZ
イテレータが勝手にループすることはない
ループするよう別途コードを書かなければならない
Option<T>を返す関数をfとすると
while let Some(x) = f() { ... } で十分である
つまりイテレータ実装する意味がない
イテレータメソッドに繋げたい!という反論もあろう
それなら std::iter::from_fn(f) で十分である
2024/12/10(火) 01:03:26.70ID:EhFU+3MS
Iteratorの話は、lifetimeの棍棒で殴られたという文脈で出てきただけだな

構造体のメンバーが&'a Mutex<T>なら
reborrowではなくmoveで取得した値に対しderef_mutが使える
moveなら殴られない
2024/12/10(火) 12:58:54.26ID:maUGvQsb
>>88
c++使ってる組み込みって組み込みLinuxとかじゃねーの?
あんまり組み込み特有の制限ないだろ
好きに組めや
101デフォルトの名無しさん
垢版 |
2024/12/11(水) 12:00:23.09ID:FLapvbLS
これはポリシーというか戦略が違ってて、「今より少しでも改善するなら採用」だからじゃないかと
従来型の「最低限のクオリティに達するまではreject」へのアンチテーゼでもあるから
そして(文句あるかもしれんが)crates開発者は元々のエンジニアの質がそこそこ高かったからそれでも何とかなったものの、
同じ事をGitでやったからあの「ぼくがおもいついたすごいcrates」の山になったのだと思う
交通整理すらやる気無かったわけだ

とはいえ、「使われなくなったcratesは、いつしか動かなくなった事すら認識されなくなり、死んでいく」という、
Gitコマンド内でのライフゲームをやるつもりなら、ありなんだろうさ
2024/12/12(木) 23:08:54.89ID:qS1eLhOO
C/C++からRustへ:Googleが示すファームウェア進化の道筋
https://xenospectrum.com/google-revamps-firmware-with-rust/
2024/12/14(土) 11:03:48.81ID:mSSbYcoF
読み終わった

>>102
具体的なアプローチは以下の通りである:
(1) 段階的なRust導入:
 略
(2) 既存のCコードベースとの統合:
 略
(3) ベアメタル環境への対応:
 略
(4) ビルド最適化とパフォーマンスの考慮:
 略
2024/12/15(日) 23:03:38.24ID:ehGoRf8d
Rustで連番IDを発行する関数はこれでいい?

fn new_id() -> Option<usize> {
thread_local! {
static ID: Cell<usize> = Cell::new(0);
}
ID.get().checked_add(1).inspect(|&new_id| ID.set(new_id))
}
2024/12/15(日) 23:37:25.98ID:YS3isBj8
mutableなRange(0..)をIteratorとして使う小技があるけど
オーバーフローは意識したことないな

fn new_id() -> Option<usize> {
use std::cell::RefCell;
use std::ops::RangeInclusive;

thread_local! {
static ID: RefCell<RangeInclusive<usize>> = RefCell::new(0..=usize::MAX);
}

ID.with_borrow_mut(|ids| ids.next())
}
2024/12/15(日) 23:49:49.46ID:ehGoRf8d
>>105
Cellで済むところがRefCellになってしまってメリットがよくわからないです
2024/12/16(月) 00:17:21.21ID:QlO1DQXb
合わせたつもりだったけど104の実装だと最初のidは1か
2024/12/16(月) 00:32:53.11ID:QlO1DQXb
0から開始できる形でCellにこだわるなら↓みたいな実装もありそう

fn new_id() -> Option<usize> {
thread_local! {
static ID:Cell<Option<usize>> = Cell::new(Some(1)); // ←0開始ならSome(0)
}
ID.replace(ID.get().map(|i| i.checked_add(1)).flatten())
}
2024/12/16(月) 01:08:38.61ID:KPayFncJ
スレッド単位の連番て何やの?
2024/12/16(月) 12:39:36.29ID:pEIdxfnL
>>104をマルチスレッド対応するなら
まず初心者入門向け版としてはCellをMutexに変更で動く

fn new_id() -> Option<usize> {
static ID: Mutex<usize> = Mutex::new(0);

let mut id = ID.lock().unwrap();
id.checked_add(1).inspect(|&new_id| *id = new_id)
}
2024/12/16(月) 18:51:07.44ID:gawhGp3+
inspectの間違った使い方
2024/12/16(月) 19:41:56.01ID:NChejl3+
正しいようだが何を問題視してる?
ちなみにRustではmatch(またはif let)で書いた時に
次のようなパターンになる場合に
わかりやすく短くメソッドにして繋げることができる

and_then(f)
 | Some(x) => f(x),
 | None => None,

map(f)
 | Some(x) => Some(f(x)),
 | None => None,

inspect(f)
 | Some(x) => { f(x); Some(x) }
 | None => None,

or_else(f)
 | Some(x) => Some(x),
 | None => f(),

unwrap_or_else(f)
 | Some(x) => x,
 | None => f(),

ok_or_else(f)
 | Some(x) => Ok(x),
 | None => Err(f()),

など
113デフォルトの名無しさん
垢版 |
2024/12/17(火) 10:28:51.72ID:hEkGaD6x
全然判り易くないぞ
語彙に直交性が全く無い
2024/12/17(火) 12:02:56.17ID:PdC61IaM
語彙の問題もあるのかもしれないけどasyncの問題もあって中の人たち含めみんな昔ほどコンビネータで書かなくなった
2024/12/17(火) 12:27:03.59ID:QsDK8zUE
Optionを自然に真偽値ベースで英語で読むと判り易くなっている
例えばunwrap_or_elseは
真ならunwrapすなわちSome(x)→x
orは前提が偽つまりNoneの場合がfの対象でNone→f()

似ているor_elseは
Some(x)→Some(x)となる部分だけ違うとすぐわかる

その逆は当然and_thenとなり
andは前提が真の場合がfの対象でSome(x)→f(x)となる

通常の動詞1つの時は真つまりSome(x)の時が対象で
mapは値を写像してSome(x)→Some(f(x))
inspectは値を変化させずに実行Some(x)→{ f(&x); Some(x) }
filterも値は変化させずに実行して偽なら捨ててNone
Some(x)→if f(&x) { Some(x) } else { None }
2024/12/17(火) 13:56:28.23ID:fyM5pHAa
現状追認オジの意見ほど意味のないものはない
2024/12/17(火) 13:58:12.78ID:8t1OBzHL
バカでも読めるコードが正解なんだよ
2024/12/17(火) 14:25:44.95ID:QOGj4SRI
コボラーがそんな事言っていたなw
2024/12/17(火) 15:37:01.20ID:k3aNgl34
あほくさ。
そこらの医学でも物理でも法律でもいいが適当な論文が単語や言い回しだけ平易にすればバカでも読めるようになるか?
前提知識がないとどうせ意味なんかわからん。
プログラミングも同じ。
理屈が理解できるだけの能がなければ表現ばかり平易にしても無意味。

不必要に難解にする意味はないが、言い回しだけ過度に平易にする意味もない。
2024/12/17(火) 15:40:38.28ID:8t1OBzHL
特定のプログラミング言語を使えることを物理医学レベルと思ってるのは思い上がり
2024/12/17(火) 15:52:02.93ID:k3aNgl34
>>120
どこをどう読んだらそんな風に読めるんだ?
言語は当然にそれで表現すべき何事かがある (書く人はそれを理解している) という話なんやが。
2024/12/17(火) 15:54:52.82ID:8t1OBzHL
>>121
自分はバカだと自覚したほうがいいぞ
ソフトウェア開発するならな
2024/12/17(火) 16:01:39.84ID:k3aNgl34
>>122
それは大変によくわかる。
自分で書いたものすら意味わからんようになるのは普通のことだからな……。

だから意図を表現することが大事で、小さなロジックの断片にでも名前を付ける。
その状況を表すための名前 (専門用語) こそが大事。
訓練されていない人にとって平易であることとは違う。
2024/12/17(火) 16:33:22.09ID:bLYSKCYG
>>116
現状追認主義なのに推奨されてる用量・用法は守らず動くだけのコードを披露したがるのは理解できないんだが
2024/12/17(火) 17:43:30.54ID:SHc5Q5Oi
ママに褒めてもらいたい幼児の心理だよ
わかりやすいだろ
2024/12/17(火) 20:27:48.43ID:QsDK8zUE
>>117
「ごっちゃに書いて見通しの悪いコードにはせずに、
高階関数のメソッドチェーンにして、
各々のメソッドで個別に関数またはクロージャで処理を指定する。」
ここまでは共通認識でいいんだよね?
万が一これにも反対の人がいるならばまずは代案を明示的に出してほしい

以上の共通認識の上で
語彙の問題という話が出ているからメソッド名の付け方に問題があるということなのか?
それともメソッドが多すぎる(機能が多すぎる)またはメソッドの分別の仕方に問題があるということなのか?
まさか高階関数がわかりにくいという話ではないと思うが
2024/12/17(火) 21:50:43.67ID:dgkTZZrK
なんでもメソッドチェーンで繋げればいいわけでもなければ
なんでも分割して書けばいいわけでもない
ケースバイケース

一番ダメなのは慣習や暗黙の了解を無視したコード
>>104>>110はその一番ダメなやつ

つかこんな基本的なことから説明させようとするなよ
2024/12/17(火) 22:05:47.16ID:ecWnwmom
>>127
んでお前ならどう書くんだ?
Rust使った新システムで慣習や暗黙の了解はまだない時に自分で考えてソース書くときはどうするんだ?
2024/12/17(火) 22:08:10.40ID:e6YSkvhC
>>127
また自分勝手な慣習や思い込みの暗黙の了解かよ
130デフォルトの名無しさん
垢版 |
2024/12/17(火) 22:18:10.64ID:zSkWZLKX
vecs.iter().map(|x| x.iter()).flatten().filter(...)

みたいなのは書いてて気持ち良いけど、全員が賛同するわけではないよな
Rustの公式のドキュメントだって関数型スタイルの書き方と手続き型スタイルの書き方の両方を紹介してるわけだし
そういう「高度な書き方」をバッサリ切り捨ててるGO言語が人気というのもそう
2024/12/17(火) 22:20:51.38ID:QsDK8zUE
>>127
具体的に何を問題視してるのかわからん
Mutexを使わずに効率よく実装できるケースのようにみえるが
初心者入門向けと書かれてるからMutex利用もアリだろう
2024/12/17(火) 22:42:34.79ID:e6YSkvhC
>>130
そのコード自体はともかく
そういうメソッド連鎖は標準ライブラリや有名クレートのソースにいくらでも出てくるぜ
まずはソース読んでみな
133デフォルトの名無しさん
垢版 |
2024/12/17(火) 23:29:57.24ID:zSkWZLKX
>>132
自分も好みとしては関数スタイルを使うよ
だけど >>126 のような「それが正しい形であり、みんなそちらを使うべき」みたいな言説はあほらしい
有名どころのOSSのコントリビューターだって、利用者からの質問への回答やチュートリアルでは 「for文で一つずつ要素を Vec に push_back で詰める」コードを示すことも実際にある

Rust開発者は関数スタイルを好む人も多いと思うけど、それは好みの域を出ないと思う
2024/12/18(水) 09:42:19.11ID:w442kBzm
まあ存在する以上はユースケースがあるってことだからな。
2024/12/18(水) 12:59:18.01ID:RrhqiCIc
コードゴルファーのために存在してるわけじゃないからな
2024/12/18(水) 13:17:46.53ID:3HdOm/G7
そろそろitertoolsを標準ライブラリ化する話はないのか?
2024/12/18(水) 18:37:10.88ID:C5X2cUVY
個別に取り入れられてる
まとめて標準化はない
棲み分け
2024/12/18(水) 19:09:54.98ID:MW322kuv
>>127
そのマルチスレッド対応コードに
指摘の「慣習や暗黙の了解を無視したコード」とやらが見当たらないのだが
そもそも慣習や暗黙の了解とはどういう意味で使ってる?

>> マルチスレッド対応するなら
>> まず初心者入門向け版としてはCellをMutexに変更で動く
>>
>> fn new_id() -> Option<usize> {
>> static ID: Mutex<usize> = Mutex::new(0);
>>
>> let mut id = ID.lock().unwrap();
>> id.checked_add(1).inspect(|&new_id| *id = new_id)
>> }
139デフォルトの名無しさん
垢版 |
2024/12/19(木) 11:45:17.60ID:p9TYuGiM
こういう C のコードを Rust で描く場合どうやればいい?
https://www.youtube.com/watch?v=n2Q1Sp7iew4
もちろん unsafe 利用 ok として
2024/12/19(木) 11:55:22.77ID:953TTIIh
型のキャストは
std::mem::transmute
2024/12/19(木) 12:16:13.05ID:H/9JfOm9
assert_eq!((3.14_f32).to_bits(), 0b1000000010010001111010111000011_u32);
assert_eq!(f32::from_bits(0b1000000010010001111010111000011_u32), 3.14_f32);
142デフォルトの名無しさん
垢版 |
2024/12/20(金) 15:29:01.33ID:raronLtC
JAIST、「並行量子通信プロトコル」の完全な自動形式検証を実現
http://news.mynavi.jp/techplus/article/20241220-3090485/
2024/12/22(日) 22:27:16.01ID:K7zRdssG
>>138
中級者向けにはこれでええんかね

fn new_id() -> Option<usize> {
static ID: AtomicUsize = AtomicUsize::new(0);

let mut old_id = ID.load(Relaxed);
while let Some(new_id) = old_id.checked_add(1) {
match ID.compare_exchange_weak(old_id, new_id, Relaxed, Relaxed) {
Ok(_) => return Some(new_id),
Err(updated_old_id) => old_id = updated_old_id,
}
}
None
}
2024/12/23(月) 22:20:47.40ID:GhTcJSaR
Rustに興味出てきたからとりあえず、とほほさんのサイトに目を通してみたんだけど
…もしかしてあの方、非同期処理と並列処理をごっちゃに理解している?

https://www.tohoho-web.com/ex/rust.html#async-await
2024/12/23(月) 22:54:25.61ID:OG1FFUyc
>>143
lock freeはそう
今回のアルゴリズムはRelaxedでも大丈夫だがmemory orderingに注意を要する

>>144
executor (runtime) とそこでの使い方次第
single thread で並列(parallel)なく並行(concurrent)のみも可能であるし
それをmulti threadで並行並列も可能であるし
blockさせて並行なく専属並列も可能
2024/12/28(土) 15:51:05.67ID:SGU/9qSb
Rustしか勝たん
2024/12/28(土) 17:09:23.73ID:IXmLUnxX
こういうアホが湧いてきたときがピークだな
2024/12/28(土) 17:20:50.92ID:T6F1mfjg
WebAssemblyはRustが主流なイメージだけど実際どんなもんだろ
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

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