Rust part8
■ このスレッドは過去ログ倉庫に格納されています
Docs.rsのメソッドの引数の見方がわからん 具体的には https://docs.rs/image/0.23.2/image/struct.Frames.html の pub fn new(iterator: Box<dyn Iterator<Item = ImageResult<Frame>> + 'a>) -> Self iteratorを受け取ってSelfを返す。 iteratorは各要素がImageResult<Frame>のもの Box<dyn …>してるのはコンパイル時にTrait ObjecのSizeが決まるようにするため (Generics使えば不要) ‘aはiteratorのlifetimeをSelfのlifetimeにするため >>380 解説ありがとう 上二行は理解できたんだが他がイマイチ・・・ >>381 dyn は C++ で言う抽象クラスみたいなもんだよ。 トレイトオブジェクトというのは実際にはそのトレイトを実装している様々な型の可能性があって、 それら全てを格納可能な大きさはわからない。 Box は C/C++ でいうポインタみたいな用途で使われる。 大きさがわからなくてもオブジェクトの場所を指すことは出来る。 「そのトレイトを実装している型ならなんでも」と「そのトレイトを実装している型のいずれか」というのは違う意味で、 ジェネリクスは後者。 言い換えると、実行時にディスパッチされる多相とコンパイル時にディスパッチされる多相ってこと。 コンパイル時に型がわかるのなら大きさもコンパイル時にわかる。 大きさがわかるなら Box を経由しなくていい。 ライフタイムの 'a は Frames の型引数の 'a と同じだから、 new の返り値 (Self) の寿命は iterator の寿命と同じになる。 Boxと&dynの違いって参照元がヒープかスタックかの違い? >>381 大前提として変数や関数の引数や戻り値はコンパイル時にサイズが決まってないといけない Iterator Traitを実装してる型を引数として受け取りたいからといって `pub fn new(iterator: Iterator<…>) -> Self` と書くと Iterator Traitのサイズがコンパイル時にはわからないのでコンパイルエラーになる `let foo: str;`でエラーになるのと同じ Box<dyn Trait>か&dyn Traitの形にすれば Iterator Traitへの参照(=Trait Objectというfatポインタ)になって 受け渡しするサイズが固定されるのでエラーにならない ジェネリクスを使って `pub fn new<T: Iterator<…>>(iterator: T) -> Self` と書いた場合は 実際の呼び出しに使われているTの型ごとにコンパイラがバイナリを生成するので コンパイル時にTのサイズが決まってる (impl Trait使った場合も同じ) >>382 も書いてるように前者は動的ディスパッチ、後者は静的ディスパッチなので 異なる型が混在するコレクションを使いたい時やバイナリサイズを小さくしたい時以外は ジェネリクスを選ぶほうが一般的 あーなんとなくわかってっきた ジェネリクスと同じことがトレイトオブジェクトでも実現できて、その書き方がBox<dyn...>ということか そもそもRustはかなり型のサイズに厳しいけどなんで? コンパイラの最適化のため? >>388 他言語なら暗黙的に参照として扱われるようなものも 明示的に&を付けたりBox化することを求めるから厳しく感じるんだと思う 明示的に求めるのはowned/shared/mutableの3つを 一貫性を持って区別して書くようにっていう設計選択じゃないかな >大前提として変数や関数の引数や戻り値はコンパイル時にサイズが決まってないといけない ↑これ他言語でも常識かもしれないけど自分はRustやるまで意識したことなかったよ > pub fn new(iterator: Box<dyn Iterator<Item = ImageResult<Frame>> + 'a>) -> Self 入力にimpl Traitってまだ無理なんだっけ? >>386 同じではない。 ジェネリックスはパラメトリック多相の事だから静的ディスパッチになるけどtrait objectは動的ディスパッチそのもの。 >>388 そう。 リージョンでメモリ管理するときリージョンのサイズが事前に決まるなら リージョンはヒープじゃなくてスタックに確保できるからrustは型システムが サイズが事前に決まる事を強制してる。 rustでは 途中で送ってしもた。 rustでは当たり前に見えるけどこんな事してるのrustくらいでヒープが必要ならクロージャさえも自分でbox化する必要がある。 スタック上に長さ不定のデータが作れるとバグの温床になる。 他の言語だと大体の値がヒープに乗せること前提で動いているんで気にしたことが無いのだと思われる。 C/C++でも非推奨なんだけど、初心者向け釣りサイトでは平気でやってることがあるし、できちゃうから面倒 配列サイズが決められてないかつ、関数内で配列生成するけど返り値はサイズ固定のスライス記法の書き方するようにする方法ってない? つまりはVecのアロケートが嫌な場合 fn name(v: Vec<A>) -> Vec<A> { v.iter().map(***).collect } これだとスタック確保できるけど無駄なデータ入ってるし、動的なサイズの配列を返せない fn name(v: Vec<A>) -> [i32; 10] { let mut arr = [0; 10]; for (i, x) in v { arr[i] = x} arr } こういうスライスのスタック版みたいな感じのことがしたい fn name(v: Vec<A>) -> [A] { let mut arr = [0; v.len()]; for (i, x) in v { arr[i] = x} arr } >>390 impl Traitは引数にも使えるよ >>393 [A]だとサイズがコンパイル時に決まらないから&[A]か&mut [A]を返すのはできる ただ入力がVecで長さが不定なので 出力の参照元にその長さの配列を使うのは無理じゃないかな あと関数内部で配列生成したら そのlifetimeが関数内に閉じるので参照も返せないね やるとしたら 外側のスコープで固定サイズの配列をバッファとして作っておいて 関数ではバッファを満たして返すイメージ C言語でいうところの if ( (c=foo()) == bar) { ...(cを使う処理) みたいなことやりたいんですがどうすればいいですか? fooが結構重くて2回呼び出したくないのですが、 let c = foo(); if c == bar {... とやるしかない? matchとifガード使えば似たようなことは出来る >>396 何かしらのライブラリでなんかないかな? static使うぐらいなら素直にVec使うわ... >>397 @ bindingってのを使う https://play.rust-lang.org/?version=stable& ;mode=debug&edition=2018&gist=b2a16356c2c790985ddd937ccc2ca826 >>398 match foo() { c if c == bar => { .. }, _ => (), } こういう感じでしょうか。この場合だと記載量としてはかなり微妙ですが何かに使えそうなので覚えときます。 ありがとうございます。 >>399 今回の場合はfoo()がboolじゃないのと、barが変数なのでシャドーイングされてうまくいかないようです・・・。 if let foo @ bar = foo() { ... みたいなことやろうとしましたがダメでした。 https://play.rust-lang.org/?version=nightly& ;mode=debug&edition=2018&gist=d580f91c98f26cf52a23791489914ec3 >>390 うーん難しいな プログラムの動作としては同じになるんじゃないのか Vecとかのコンテナ系の使い方は大分変わるよ 例えばイベント駆動の何かを作るときには考えた方が良いかと思う struct XEventSource { listeners : Vec<Box<dyn Handler>>, ... } trait Handler { fn handle(ev: &XEvent) -> () } impl XEventSource { fn addLisnter(&mut self, listener : Box<dyn Handler>) -> () { self.listeners.push(listener); } fn emit(&self) -> () { XEvent ev = ...; for listener in listeners.iter() { listener.handle(&ev); } } } みたいに作ると、利用者が好きに作った構造体でもHandlerをimplすればlistenersに足せる ジェネリクスだとイベントリスナの実際の型1つしかaddできないので不便 >>402 実行時に型を振り分けるとなると仮想関数テーブルを辿る必要があるんで実行時コストが少し増えるよ。 (Rust では仮想関数って言わないのかな? 正確な用語がわからん。) トレイトを実装している型を実際には一種類しか使わないのだったら、 実行時間を除けば見かけ上の動作で違いはないかもしれんな。 でも基本的にはやりたいことを出来る範囲で制約は厳しい方がいい。 間違いの検出される可能性が高まるから。 制約をどのように表現するかというのはプログラミング言語の設計においては重要なトピックで、 構造化プログラミングが提唱されたのも goto だと制御をどこへ移動するのか制約を付けられないってのがある。 さらにそれを発展させた形として型で制約を付けようってのが色々と考えられてきたし、 Rust では更にオブジェクトの寿命に制約を付けようという考えが実現された。 その関数では何ができるのか、そして「何をしてはいけないのか」ってのを考えると Rust らしいプログラムが出来ると思う。 APIサーバーでJSON受け取るときに値の型が違ったりオーバーフローするときってどうしてる? serde_json::from_str で構造体の属性でエラーメッセージとかつけれたらいいのにな from_strの結果そのまま使ってるけどダメなの シンタックスエラーとか含めると大変じゃない 海外向けサーバーだったらいいけど日本向けサーバーの場合は? serde_jsonのエラーメッセージcustomizableじゃないから辛い serde_json::Error を見ると行と列と大雑把な原因はとれるみたい 細かくやるなら置換するしかなさそうだね reached the configured maximum number of stack frames でスタックフレームの制限にかかるんだけどオプションとかで変えれる? impl<'_, T> Drop for std::collections::vec_deque::Drain<'_, T> こういう風にちゃんとパス書かれたのもあれば、デフォルトインポートされてないのに省略されてる型あるけどどうなってるの? https://doc.rust-lang.org/std/ops/trait.Drop.html フルパス書かなくてもいいように mod.rsに指定されてるものとされてないもの それが必要な理由は?ここはお前の便利帳じゃねーんだから 有益な使い方が有れば紹介してから聞け >>412 Yコンビネータ Rust で適切に型がつけられるかどうか知らんけど >>413 データ入ったVecと各種定数とメモ化用のmutなHashMap使ったDFSするときとか、引数がむっちゃ長くなるんです >>414 全然わからんのであきらめます・・・ Copyでの関数呼び出しとポインタ作成ってコスト的にはプリミティブのどの型からが処理重い? ここらへんCSの知識ないからわかんない Rust仕事で使ってる人〜 ウチはコロナの影響でプロジェクト吹き飛んだよん( ;∀;) 組み込みで試験的に導入したけどムズイ まあ慣れの問題もあるのだろうけど ATS2ってRust以上にドキュメントが少なくてHaskell以上に難解なアレじゃないですかやだー! Rust界隈で一番貢献度高いのってAlexとかになるかな? Microsoftに期待してるんだが今はそれどころじゃ無さそう 勉強がてらこちらの二分探索木を真似してみたのですが、コンパイルエラーが出てしまいます。 https://codereview.stackexchange.com/questions/133209/binary-tree-implementation-in-rust playgroundで試してみた結果がこれです。 https://play.rust-lang.org/?version=stable& ;mode=debug&edition=2018&gist=fc1fe0d2a4c39c6b28d017539419fa2a どうやら古いRustならコンパイルが通るようなのですが、今のRustでコンパイルを通すにはどうすればよいのでしょうか? 非常に良いと思います。flagの意図を読み解くのが少し難しいくらいです。 確かにflagが読みづらいからコメントは欲しいかな 個人的にはuse Exp::*;とExp::V => Exp::Valueにするのとテストケース増やしてmod testsにするかな let exp = Value("MITSU").add(Value("MITSU")).add(Value("MITSU")).eql(Value("CORONA")); let solver = Solver::new(exp); // prints solved exp solver.solve(); 最初のインスタンスは読みにくいからこうするかも、それかマクロかビルダー作るか トレイトって機能を追加するときどういう機能であるかの特徴を一見して分かりやすくするためだけのもの? >>433 とりあえずはJavaやC#のインターフェースっぽいものとして捉えておけばいいんじゃないのかな やってるうちに違いも分かってくる思うので これライフタイム記述を省略できないのなんで? https://git.io/JfL6t 省略してコンパイラ通るけどstableは無理なん? 関数内で同じ一連の処理を複数回実行するときマクロにまとめるのが一般的?それともクロージャ? 他にやりかたある? https://play.rust-lang.org/?version=stable& ;mode=debug&edition=2018&gist=30449f979231232b68016cab5cd1fb1e https://play.rust-lang.org/?version=stable& ;mode=debug&edition=2018&gist=e5fc7f66785bb3794df19104d5c479ff >>438 関数 あとサンプルだからかもしれないけど spilt_whitespace()とかでイテレータ使ったほうが読みやすい https://play.rust-lang.org/?version=stable& ;mode=debug&edition=2018&gist=b03bef5cb6f98821032c5fb1cce618a1 そのコードは実際に使うコードじゃなくてさあ、変数が何個もあったりすると関数切り出しは引数が地獄になるじゃん その例でマクロかクロージャの二択ならクロージャだけど >>438 のは外側の変数をキャプチャすることで複雑化してるから&tangoを渡すようにする https://play.rust-lang.org/?version=stable& ;mode=debug&edition=2018&gist=ec760be4190e2ad4ab21fbea3c84b0ed そうすると結局クロージャも関数と同じように適切なシグニチャを考える必要があるから 関数化に比べて楽ってことはないんじゃないかと思う 公式のGithubにrustlingsっていう簡単な練習問題がある The Bookを読んだ後に基本文法をおさらいしたい人向け https://github.com/rust-lang/rustlings ↓Vecだと動くのに配列にするとコンパイルできないの何で? https://play.rust-lang.org/?version=stable& ;mode=debug&edition=2018&gist=6321129e5cc3853ef1421d706e19a136 配列にinto_iterしてもmoveされずに参照が返るから rustいつのまにか蟹のイメージになってるけど、オライリーの影響?それとももっと前から何かあるのかな? let mut heap = BinaryHeap::new(); heap.push(10); heap.push(9); heap.push(20); for x in &heap { println!("{:?}", x); } これでバイナリヒープすると 20 9 10 ってなるんだけどバグ? >>448 配列のIntoIteratorは &[T; N]と&mut [T; N]に対して実装されてるが[T; N]に対しては実装されてないのでmove不可 対してVecのIntoIteratorは &Vec<T>と&mut Vec<T>だけでなくVec<T>に対しても実装されてるので moveが必要なコンテキストならIntoIterator for Vec<T>が選択されmove可能 >>448 配列でやりたい場合はFooにClone実装してfoo.clone() https://play.rust-lang.org/?version=stable& ;mode=debug&edition=2018&gist=8fdb065f764ac7a0be3a3de161bfa984 学術の巨大掲示板群 - アルファ・ラボ ttp://x0000.net 数学 物理学 化学 生物学 天文学 地理地学 IT 電子 工学 言語学 国語 方言 など PS 連続と離散を統一した! ttp://x0000.net/topic.aspx?id=3709-0 配列のIntoIteratorにmoveが実装されてないの何で? >>458 詳しいことはよくわからないけど実装が難しかったみたいよ 興味あればこのissue読んでみて https://github.com/rust-lang/rust/issues/25725 nightly使えばmoveできる機能はあるみたい https://play.rust-lang.org/?version=nightly& ;mode=debug&edition=2018&gist=6a22ab054f5ec52ea942a1186710a516 >>457 型制約見ればええんやで。 `pub fn iter(&self) -> Iter<T>`は`impl<T> BinaryHeap<T>`。 `impl<T> BinaryHeap<T> where T: Ord,` に`pub fn into_sorted_vec(self) -> Vec<T>`てあるやろ。 rustのOrdは全順序や! この場合はifを使うのとmatchを使うのとどっちがおすすめ? if nanika_shori().filter(hoshiimonokana).is_some() { hoge(); mitsukatta(); } else { fuga(); mitsukaranakatta(); } match nanika_shori() { Some(butsu) if hoshiimonokana(butsu) => { hoge(); mitsukatta(); } _ => { fuga(); mitsukaranakatta(); } } >>461 後者は関数型言語風ってだけでしょ 関数型言語で is_some() にあたる関数は存在しなかったり、有るけど使うなって扱いだったりする テレワーク中なのか連休入ったせいなのか知らんけど猛者が全部回答してくれるから助かるわ >>461 match nanika_shori().filter(hoshiimonokana) { Some(x) => {…}, None => {…} } か if let Some(x) = nanika_shori().filter(hoshiimononanoka) {…} else {…} か boolを返す関数作ってif else fn are_aruka(hoshiimono: Hoge) -> bool { match nanika_shori() { Some(x) if x == hoshiimono => true, _ => false } } filter(...).is_some() って形はかなり読みにくい ようは設計が悪い ResultやOptionが複数ネストしたやつをイイカンジにmapとかやれるか Rustやる前に軽くScalaとかHaskellやっとけば コレクションライブラリ見たときに「あっ、これ進研ゼミでやったところだ!」って なるから理解が早いよ このコードがコンパイル通って実行できて期待した実行結果にならない https://play.rust-lang.org/?version=stable& ;mode=debug&edition=2018&gist=4472067bedcd681b8154620b3023f278 HashMapでキーを参照にしたときキーがアドレス値にならないのなんで? https://play.rust-lang.org/?version=stable& ;mode=debug&edition=2018&gist=9f33505748c782a7b5a2cd22481e5b68 >>473 &strのEqはアドレス比較じゃないから >>471 酷いAPI stdがどうなってるかぐらい見たほうがいい Rustは、Releaseモードでも、Runtimeをstatic linkする場合は、61MB、 dynamic linkする場合は、8.2MBになるらしい。 dynamic linkで、さらにサイズ重視最適化した場合、4.6MB、strip した場合、 3.1MBになる。 でも、C++に変わる言語を標榜するにしては大きすぎる。 https://www.quora.com/Why-are-the-Rust-and-Go-binaries-so-large-compared-to-C-or-Pascal >>476 >Rustは、Releaseモードでも、Runtimeをstatic linkする場合は、61MB、 >dynamic linkする場合は、8.2MBになるらしい。 Debugモードが61MB Releaseモード(デフォルト設定)が8.2MB って書いてるよ それにlinkするのはRuntimeではない もう少しちゃんと読もう >>476 デフォルトでサイズが大きいという結論は間違ってないけど もうちょっと英語ちゃんと読んだ方がいいと思う…。 あとその回答には書いてないけど、頑張ればCにサイズで勝つことは可能だったはず。 ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.4 2024/05/19 Walang Kapalit ★ | Donguri System Team 5ちゃんねる