Rust part24

レス数が950を超えています。1000を超えると書き込みができなくなります。
2024/05/27(月) 06:41:26.82ID:T4AFD1f4
公式
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/
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)
 }
}
2024/07/18(木) 23:31:33.62ID:GQ1B8wHA
代数的データ型ってなんかすごいけど知名度がモナドより低いな
2024/07/19(金) 02:03:52.09ID:MUvBupZH
>>890
使ってみたけど、time-rsいいね
いつのまにかダウンロード数でchronoを上回る競合があったとは知らんかった
タイムゾーンの扱いがやや簡略化されてるけど、夏時間のない日本人的には問題ない
月を直接intで指定できないのが英語仕様やな……ってちょっと気になる
2024/07/19(金) 03:51:08.70ID:riLGg6QV
>>891
この各収納先への移譲と両側のトレイト境界が汎用化の肝
trait FromIterator<A>: Sized {
 fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self;
}
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:rC6z5NUh
>>886
let x; HashMap::<_, _> = vec.try_into()?;

>>889
+1
2024/07/19(金) 23:52:20.75ID:8WlCJE3Q
>>897
エラーとなりますた
2024/07/20(土) 00:12:48.41ID:bNknJoN/
>>896
ウィルスバスター以来の快挙やね
2024/07/20(土) 14:16:49.05ID:F167yFzL
>>898
; が : の間違いかな

>>899
暴落予想
note.com/asset_n_ichi/n/nceaa6f318b1e
2024/07/20(土) 23:38:20.92ID:6EAP68vq
>>897
HashMapとVecにTryFromが実装されていないから無理
FromIteratorが実装されているのでそれを使う
2024/07/21(日) 01:48:23.56ID:eUhj6//q
★┷┓
┃D┃
┃D┃
┃K┃
┃で┃
┃も┃
┃r┃
┃u┃
┃s┃
┃t┃
┃が┃
┃使┃
┃え┃
┃ま┃
┃す┃
┃よ┃
┃う┃
┃に┃
┗━★
2024/07/21(日) 09:43:03.00ID:QhoywuRk
>>901
こういうのが「Rustは学習コストが高い」って言われる原因なんだろうな
答えを知ってる人は判ってても答えを知らない人は判らない
答えを調べるのにコストがかかりすぎる
2024/07/21(日) 10:14:17.60ID:TGGT0XLq
とあるライブラリに変な癖があるという話は
どの言語でもあるからそういう話ではないだろ
2024/07/21(日) 10:29:10.85ID:U3c7smqS
イテレータ使ったことない
2024/07/21(日) 10:35:28.58ID:W0nR4Dwz
>>903
Rustはその点シンプルでクセもなく覚えやすい

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

Fromは基本的に単独要素や配列(=静的固定長)から他へ変換
2024/07/21(日) 11:03:59.33ID:BMrg5vDt
>>903
>>897のはコンパイルエラーの内容が読めればすぐわかる
エラーの内容が読める程度の基礎力は最初に勉強して身につける必要がある
そもそもtry_intoでどういうケースならエラーにして欲しいのか考えればおかしいことに気付く

サードパーティライブラリの学習コストは他の言語に比べると顕著に高いが
基本的な言語機能や標準ライブラリは言うほど高くない
JavaやC#あたりと比べるとむしろ学習コスト低いんじゃないかと思う
908デフォルトの名無しさん
垢版 |
2024/07/21(日) 11:04:04.35ID:xuKRyHnL
>>903
それくらいchatGPTで教えてもらえるだろ
2024/07/21(日) 11:14:46.17ID:BMrg5vDt
>>908
俺もそう思って試してみたけど駄目だね
エラーの簡単な原因とcollect使えみたいな代替案は出してくるけど
根本的な理解につながる答えを返せないだけでなくいろいろと間違った情報を返してくる
2024/07/21(日) 11:48:09.12ID:W0nR4Dwz
from_iter(array)で済むのに
なぜ配列からHashMapへのFromがあるのか理由はおそらく
配列からmoveするinto_iter()が数年前までなかったためだと思う
今は配列を含めて要素が複数なら→イテレータ利用→FromIteratorと覚えればよいかと
911デフォルトの名無しさん
垢版 |
2024/07/21(日) 11:54:05.33ID:9I2odrUJ
そもそもイテレーターとコンテナの概念を勘違いしてる可能性ありそう
別種のコンテナ同士の変換は (特別な対応がない限り) 直接的には無理で、イテレーターを介して中身の要素を走査すれば渡せるということ

みかん箱を冷蔵庫に変換することはできないけど、箱の中のみかんを1つずつ取り出して、それを冷蔵庫型に纏める (collect) ことはできるような感じ
2024/07/21(日) 12:08:53.38ID:QhoywuRk
今回は >>910 さんをベストアンサーとさせて頂きます
みなさんご協力ありがとうございました
2024/07/21(日) 12:17:32.86ID:rbHgMj6q
>>911
それは単に抽象度の違いであって勘違いでも何でもない
2024/07/21(日) 12:17:32.92ID:QhoywuRk
>>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);
}
2024/07/21(日) 12:21:47.94ID:QhoywuRk
なぜ Vec から HashMap は from が使えないのか?
の問いに GPT は答えてくれない
2024/07/21(日) 12:29:53.31ID:+gih9iRs
>>910
順番が逆
arrayにIntoIteratorが実装された方が先で
From array for HashMapのほうが後
2024/07/21(日) 12:32:17.29ID:BMrg5vDt
>>915
そこはFromのimplがないからと答えてくれる
coherenceの制約を先回りして答えてくれるかどうかは質問次第
2024/07/21(日) 13:57:28.77ID:W0nR4Dwz
>>916
ありがと
調べたらその順だね
そうなるとFrom<配列>だけを特別に用意した理由は配列が基本型だからだろうか
HashMap::from(array)のコードを見ると
HashMap::from_iter(array)とFromIteratorの実装を呼び出すだけなので
2024/07/21(日) 16:06:46.61ID:nMuf3u03
MapやSetのリテラルがないけどリテラルに近い感覚で初期化したい場合の代替策として用意されたのがFromの実装
2024/07/21(日) 16:20:17.13ID:BJsLblxy
_iterの5文字が節約できるメリットだけか
2024/07/21(日) 16:39:36.83ID:u5tRysNp
>>920
タイプアノテーションの要不要があるのでもっと節約できるよ
2024/07/21(日) 16:43:19.24ID:BJsLblxy
>>921
不要になる例を出して
2024/07/21(日) 17:05:45.63ID:QAZ3DYjh
FromがあるとIntoが使えるからHashMap返すときとか引数で渡すときに
HashMap::from([..])
の代わりに
[..].into()
で書ける

型を明記するletだと大差ないかも
let map: HashMap<K, V> = [..].into();
let map = HashMap::<K, V>::from([..]);
2024/07/21(日) 17:22:33.98ID:BJsLblxy
>>923
そこでタイプアノテーションが不要になる例はないよな
関数の引数型か返り型に書いている

into()と書ける件も
collect()と書けるから
FromIteratorに対してFromもあるメリットは3文字節約できるだけか
2024/07/21(日) 21:02:32.72ID:eUhj6//q
dyn traits以外にinto使うなよ。変換するんだから

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

じゃなくて

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

だろ。
2024/07/21(日) 21:07:32.49ID:BUmQiTHC
は?
2024/07/21(日) 22:10:59.79ID:kEjkNYpd
>>922
use std::collections::HashMap;

fn main() {
let xs = [(1, "a"), (2, "b"), (3, "c")];
let map = HashMap::from(xs);
println!("{:?}", map);
}
2024/07/21(日) 22:23:54.17ID:vNf5wQaP
>>927
HashMap::from_iter(xs)で十分じゃね
2024/07/21(日) 22:30:45.10ID:kEjkNYpd
>>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
|
2024/07/22(月) 12:16:14.88ID:7a9cZObY
配列からの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> { ... }
2024/07/22(月) 12:18:01.98ID:7a9cZObY
つまりFromは重いデフォルトハッシャーに固定されてしまっている
FromIteratorを使えば自由に速いものを利用できる
let xxx = HashMap::<_, _, FxHash>::from_iter(array);
2024/07/23(火) 01:07:15.84ID:XvQFw5Nb
HashMap::from(配列)の場合は
デフォルトハッシャーで困るユースケースは稀だから
APIのエルゴノミクスのために意図的にRandomStateに固定してる
そのおかけでタイプアノテーションなしで書ける

タイプアノテーション無しの場合はデフォルト指定の型を優先的に使うよう
Rustのコンパイラが改良されればこの辺の差はなくなる
2024/07/23(火) 01:10:26.97ID:XvQFw5Nb
>>931
>let xxx = HashMap::<_, _, FxHash>::from_iter(array);
FxHashのところはFxBuildHasherだね
let xxx = FxHashMap::from_iter(array);と書いたほうがいろいろ親切

親切設計のライブラリなら
let xxx = AHashMap::from(array);
のようにFromIteratorだけでなくFromも使える
934デフォルトの名無しさん
垢版 |
2024/07/23(火) 01:31:49.01ID:Rfg4Mjqa
tupleをiteratorしたいんだが無理?
2024/07/23(火) 02:50:50.92ID:l+hNtTPE
こういう意味?
let t = ("abcde", "fghijkl", "mno", "pqrstuvw", "xyz");
assert_eq!("abcdefghijklmnopqrstuvwxyz", Into::<[_; 5]>::into(t).into_iter().collect::<String>());
2024/07/23(火) 09:22:40.63ID:iSDzXJU2
同じ型だけの要素で構成されるtupleならいけそうだけど
色んな型ば混ざってるtupleはエラー出そう
2024/07/23(火) 11:25:10.18ID:ijWLrFq+
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}");
 }
}
2024/07/23(火) 17:24:06.93ID:hqmWVJB3
またFizzBuzzイテレータ書いてる……
939デフォルトの名無しさん
垢版 |
2024/07/23(火) 21:36:57.26ID:1jhTJKzb
>>936
Haskellだとタプルって構造体代わりだから、色んな型が混ざってる方が普通だけど…。
(ともすれば関数も入れるし。同じ型だけってのはリストのイメージ)

Rustじゃ用途違うん?
2024/07/23(火) 21:58:12.50ID:joaeWjir
タプルは型の制限なくバラバラでいいよ
今回はそれを>>934「iteratorしたい」なので
同じ型に揃えるためにdynかenumを使う
2024/07/23(火) 23:07:54.81ID:tKFzmUCx
ほとんどの言語でオブジェクトを返す時にヒープを使うから
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}");
 }
}
942デフォルトの名無しさん
垢版 |
2024/07/23(火) 23:38:39.26ID:QoNSkCmh
「tupleでイテレートできないの?」という質問に「こういうイテレータなら異なる型を混ぜられるよ」と回答するあたりがいかにもな感じ
率直に「できる/できない」で回答した上で補足として書けばいいのに
2024/07/23(火) 23:40:03.74ID:38zrS1+w
トレイトオブジェクトをdynと呼ぶのは複オジだけ
2024/07/23(火) 23:40:30.32ID:38zrS1+w
>>942
それな
2024/07/23(火) 23:49:18.56ID:lLea54if
Rust 2018 editionからdyn必須に変わった
2024/07/24(水) 00:02:23.05ID:QMkBbV1F
できる/できないで言えばできるよ

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

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

本当にタプルで管理するのが望ましいのか
タプルで管理しつつイテレータで回すのがベストなのか
まずはよく考えたほうがいいと思う
2024/07/24(水) 00:15:33.28ID:sAqPevwn
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),
 })
}
2024/07/24(水) 00:35:21.34ID:UKniupNy
リフレクションのサポートとかにもっと力入れてれば普通にできるんだろうけど、しゃあなし
Rustはそういうの好かない言語だから
2024/07/24(水) 00:44:54.58ID:djH/Nw1D
rustって流行るかな
950デフォルトの名無しさん
垢版 |
2024/07/24(水) 03:12:39.74ID:s3z853Sv
>>940
タプルをイテレーションしたい…。

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

Python,RubyのリストとHaskellのそれみたいに、そもそもの意味が違う可能性もありますし…。
951デフォルトの名無しさん
垢版 |
2024/07/24(水) 03:25:04.27ID:sCVmnNU/
>>935
let t = ("abcde", 123, "mno", "pqrstuvw", 456);
for e Into::<[_; 5]>::into(t).into_iter() {
println!("{:?}", e)
}
無理ポorz
952デフォルトの名無しさん
垢版 |
2024/07/24(水) 03:30:03.16ID:sCVmnNU/
>>946
それっぽいクレートがあるけどよう判らん
これはどんな感じ?
https://crates.io/crates/tuple-iter
2024/07/24(水) 03:57:10.87ID:yTLgnmif
これは典型的なXY問題だから相手にするだけ無駄
質問者は本当に解決したい元の課題Xを素直に話すべき
自分の思い込みで勝手に判断して進めた二次的な課題Yについて質問しているからそれについては相手にしなくていい
2024/07/24(水) 04:42:12.08ID:sCVmnNU/
>>946
imple IntoIterator for (&str, u64, &str, &str, u64) {
...
}
で出来るかと思ったけど
this is not defined in the current crate because tuples are always foreign
2024/07/24(水) 05:38:42.31ID:U0F2g2Py
dynやenumにしろと本質的なアドバイスをもらえているのに対応しようとしない人
2024/07/24(水) 07:25:15.81ID:Py4dd1Kh
たしかにXY問題だな
「異なる型が入り乱れてイテレートしたい」←何のために?
「異なる型が入り乱れてタプルがある」←どうやってそれが出来た?
957デフォルトの名無しさん
垢版 |
2024/07/24(水) 08:43:52.20ID:NUYI7xpt
・タプルは型を混合できる
・タプルはイテレートできない
・異なる型でのイテレートがしたいなら、タプルの代わりに Box<dyn Trait> のような動的型かenum (直和型) の配列を使う
で良いんじゃない?
2024/07/24(水) 08:43:57.79ID:sCVmnNU/
とりあえず出来ました
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()
}
}
みなさんありがとうございました
959デフォルトの名無しさん
垢版 |
2024/07/24(水) 08:50:34.05ID:NUYI7xpt
XY問題だとか言うけど、上のFizzBuzイテレーターなんかはXとYのどちらとも関係ないでしょ
既にあるデータに対してイテレートする方法でなく、FizzBuzを0から生成するだけだから
それをしつこく何度も書くあたりが本物
2024/07/24(水) 09:24:46.95ID:eaHzhPzb
>>959
それな
2024/07/24(水) 09:30:08.78ID:+W2StRcH
意味のないFizzBuzzを散々書いておいて答えられなくなったら急に質問者を攻撃する複オジくん草
2024/07/24(水) 12:35:19.94ID:qFVR7Ywl
必要な個数のタプルを配列に変換するコードでいいんじゃないかな
これは長さ自由に機械的にマクロで生成できそう

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()
 }
}
2024/07/24(水) 12:36:33.67ID:qFVR7Ywl
あとはタプルに登場する型を列挙して
例えばこんなコードを機械的に自動生成させてしまえばいいね

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}"),
  }
 }
}
2024/07/24(水) 12:38:12.03ID:qFVR7Ywl
そうするとタプルの中の型の順番は任意でよくて
タプルをラッパーにかませるだけで利用できるよ

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}");
 }
}
2024/07/24(水) 12:43:52.56ID:mjGiit/q
効いてる効いてるw
2024/07/24(水) 12:49:36.37ID:TJmYfYAi
「XY問題だから相手にするだけ無駄」と言い放っておいてからの〜〜
2024/07/24(水) 17:04:11.48ID:1Kw3Uuff
もっと建設的な話題はないの?
2024/07/24(水) 19:14:00.84ID:UKniupNy
5chより建設的なコミュニティを列挙し移住を検討するのが目下最も建設的な話題である
969デフォルトの名無しさん
垢版 |
2024/07/24(水) 21:00:33.77ID:bzm5y73f
最近出た便利クレートの話とかすれば良いんじゃね?
2024/07/24(水) 22:25:44.31ID:mF9Tvkg9
ベストな日付処理クレートについて議論しよう
2024/07/25(木) 08:45:26.25ID:q/t9CUhu
おすすめクレートの話はしてほしいな~
2024/07/25(木) 10:09:56.78ID:P+cFrEvf
クレートの話をしてくれー、と
973デフォルトの名無しさん
垢版 |
2024/07/25(木) 22:41:22.06ID:zdgCFOr2
クレートではないけれど今日リリースのRust 1.80でLazyCell, LazyLockが安定版に入ったよ
グローバルな変数を外部クレート無しで書きやすくなる
2024/07/25(木) 22:49:30.69ID:9YYk7vP+
>>973
それ、OnceCell使ってたコードは全部置き換えた方がいい奴?
975デフォルトの名無しさん
垢版 |
2024/07/25(木) 23:18:37.32ID:zdgCFOr2
>>974
自分はそれを言えるほど詳しくないけど、必ずしも必要ではないと思う
依存クレートを減らせる点で嬉しいし、今から書くコードでは新しいものにして良いと思うけど、今使ってるものをすぐに置き換える必要があるとまでは思わない
特にライブラリを作ってる場合は、rustcを今日リリースされたばかりの最新バージョンに上げないとライブラリをビルドできなくなるということなので、もう少し待った方が良いかもしれない
2024/07/26(金) 00:25:09.02ID:/65SSmn2
OnceLockからLazyLockへ移行すると
変数宣言と初期化関数が離れていた可読性の問題が解決するとともに
例えばget_or_initを一箇所にするために一つ関数を用意したりするなどしていた手間も省けるようになるね
そして何よりも最大のメリットはDerefによりアクセスできる利便性
2024/07/26(金) 23:32:15.42ID:/65SSmn2
とりあえず定番のこのあたりを置き換えた
static RE: LazyLock<Regex> = LazyLock::new(|| Regex::new("...").unwrap());
static SE: LazyLock<Selector> = LazyLock::new(|| Selector::parse("...").unwrap());
2024/07/27(土) 11:02:49.38ID:WfV9QQMJ
LazyLockよさそうね
2024/07/27(土) 18:38:25.11ID:U5WpGSyZ
俺の今日のハマりポイントを紹介

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

コンストラクタを抜けたとき、C++とちがってRustは値をムーブしちゃうので
struct内部を参照したポインタが変なところを参照してバグる
980デフォルトの名無しさん
垢版 |
2024/07/27(土) 19:30:58.99ID:s18eFGvS
C++も部分的に使えるとはいえ、FFIするならCのAPIにしておく方が無難な気はする
2024/07/27(土) 20:04:50.53ID:U5WpGSyZ
>>980
bindgenはFirefoxがプロダクトでたくさん使ってるって聞いて、いけると思ったんだ
Firefoxは大半がC++だから
982デフォルトの名無しさん
垢版 |
2024/07/28(日) 15:27:45.35ID:v6kdbv5j
>>978
LazyLockさようなら
に観えた
2024/07/28(日) 15:29:40.57ID:v6kdbv5j
>>979
RustとC++は相性最悪
RustとCは相性良いバッチリ
2024/07/30(火) 01:24:35.90ID:xgbf/AIH
>>979
この件って、RustはC++と比べて無駄にムーブするから遅いってこと?
2024/07/30(火) 06:04:09.29ID:RHAjweCG
無駄な移動は消える
cargo asmで生成コードを見ることでそれを確認できる
移動前と移動後のアドレスを表示させて最適化を阻害することで元は別々となる例も確認できる
986デフォルトの名無しさん
垢版 |
2024/07/30(火) 12:06:12.26ID:tiWzrJ23
>>984

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

って書いてるのに、読解力無い人?
2024/07/30(火) 19:02:27.28ID:dzXOiSL/
>>985
移動じゃなくてムーブね
ここまでのレスで使われてる述語を踏襲すればいいよ
2024/07/30(火) 20:13:33.28ID:VUdF4pDl
>>985
最適化のかかり具合でバグが消えたり現れたりする嫌なパターンだな
2024/07/30(火) 20:41:43.84ID:+5mpqNgW
>>986
Rustを使えばそんなバグは起きない
参照のライフタイムは参照先より長くなることがコンパイル時点で保証される

>>988
Rustならばそこでバグは起きようがない
990デフォルトの名無しさん
垢版 |
2024/07/30(火) 22:41:22.15ID:GjQxUZ/0
>>989
本人じゃないのに出しゃばらせて頂きますが…。

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

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

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

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

これはRustに限らず、後続の言語全てが抱えている問題です。
レス数が950を超えています。1000を超えると書き込みができなくなります。
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

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