Rust part12
レス数が1000を超えています。これ以上書き込みはできません。
前スレで循環参照なんて初心者でもすぐ作れてしまうとの意見もあったけど
Rc型を使うだけの初心者には原理的に不可能
内部可変性を与えるRefCell型も併用しないと循環参照は作れない
一つの可変参照&mutか複数の不可変参照&のどちらかのみ許されるコンパイル時確認ルールを実行時確認ルールで行なうのがRefCell型
それにより明示的に可変参照を得ることで内部可変性を持てるようにしたもの
そしてRcと組み合わせてRc<RefCell<T>>を使うことで既にあるリンクを書き換え出来るようになりようやく循環参照を作れる
もちろん自分でunsafeすればやりたい放題てすがunsafeせずともメモリ安全性ルールの元に使えます
ここまで出来る人なら強参照Rcだけでなく弱参照Weakも併用できますから循環参照を避けることも出来るでしょう マーフィーの法則
失敗する余地があるなら、失敗する テンプレートがやたらたくさん入り乱れる言語は嫌いだわ
可読性めちゃくちゃ悪いよな >>7
そこまでできてやっとRust初心者という見方もあるかもしれない 直接関係ないけど、RefCellは借用チェックが実行時段階でのチェックになって
しまうんだってな。 RefCellの借用チェックが実行段階にまで持ち越されるのは、循環参照とは全く別の話。
それはつまり、「ゼロコスト」ではないということ。 >>7
Rc<RefCell<T>>じゃなくてRefCell<Rc<T>>だね
気持ちはよく分かる >>14
どっちもあるけど通常はRc<RefCell<T>>だよ >>983
なるほどサンクス
リージョン理論に線形論理を上手く組み合わせて、cycloneとかの欠点を克服したrustってすげーなあ
とはいってもそもそも二重開放してエラーになるというのがピンとこない
free(a);
free(a);
は二重解放しているように見えて合法だろ?
一度目のfreeでaにNULLが代入されて、二度目のfreeでは引数がNULLの場合はそのままreturnって処理されるんだから、理論上は何度free使ってもエラーにならないじゃないか >>16
なぜRustのスレに書いているのか不明だけど
当然NULLにならなかったよ
キャスト警告無視で
#include <stdlib.h>
main() {
char *ptr = malloc(1024);
printf("ptr(1): %x\n", ptr);
free(ptr);
printf("ptr(2): %x\n", ptr);
free(ptr);
printf("ptr(3): %x\n", ptr);
}
実行結果
ptr(1): ea8f72a0
ptr(2): ea8f72a0
free(): double free detected
core dump >>11
静的にチェックできないような使い方を実現するためのものなんだから
実行時チェックになるのは当然では
オーバーヘッドが気になるなら UnsafeCell を使えばよい
>>16
C には参照はないので free(a) という呼び出しで a の値が書き換わることはなく malloc で獲得した領域のアドレスがそのまま残る
領域自体は free で解放済みになっているため、アクセス (free 呼び出し含む) した場合何が起きるか分からない
このような解放済みの領域へのアクセスは use-after-free と言われるもので、脆弱性の原因として有名 >>18
なるほど
free内で代入されるのではなく
自分で代入しないとNULLにはならないのですね。
ありがとうございました。 uaf防ぐのってぶっちゃけ簡単ですよね?freeしたあとにNULL代入するのを鉄則化するだけですよね? ポインタコピーすることないの?
加減算することないの? int* p1 = malloc(sizeof(int));
int* p2 = p1;
free(p1);
p1 = NULL;
free(p2);
極端に書くとこうかなあ? >>22
1つのオブジェクトを複数のポインタで挿している場合にそういうわけにはいかない。 >>25
複数のポインタにそれぞれNULL代入したらいいだけの話ですよね?
難しい話ですか? >>23
加減算考慮するとなんかやばいんですか?
本当に素人なので教えてください!! >>24
p2=NULL;すればいいだけの話ですよね? >>27
プログラミングをしたことがなく
頭の中での思考実験もできないのか
プログラマーに向いていない 手で書くと効率は落ちないが、実行段階で自動的に NULL を入れようとすると
効率が落ちるという意味ね。時間とメモリーの両方で。
NULLが入っているか判定して error にするなどの処理も必要となったりする。 >>32
すみません。
おっしゃるとおりかも知れないです。。 >>36
参照カウンタ方式は、自動的に関連するポインタを巡ってNULLを入れるよりは
効率が良いのでプログラマーの裁量で選択できるようになっている。
しかし、それでも僅かに効率が落ちるのでなるべく使わないでプログラムする
方が良いと思うプログラマーが多いということだよ。 プログラマーならば、まず思考実験、それで解決しなければコーディング
その上で問題点を尋ねる
それをしない人はプログラマーではないから、このスレの邪魔 >>38
そんな僅かな効率の低下でも忌避されるんですね!!
わかりました!! 手作業で書く場合は、1つのオブジェクトを削除する場合、それを参照する
全てのポインタに NULL を入れるのは効率が良い。だから、多くのC/C++
プログラマはかつてそうしてきたし、今でもそうすることも多い。
ところが自動でそれをやるには静的解析は難しいので実行段階でも
余計なメモリーを追加で消費して行うことになる。それが効率が悪い。
そして、NULLが入っているかどうか分からないのでその参照を
使う場合には、いつも最初にNULLが入ってないことを確認してから
作業をする必要があり、その判定に 2 クロックくらいかかる。
この2クロックが忌避される。 >>7
言ってる事はかねがね同意ですが、プログラムが共同作業の為にRefCell<Rc<List>>とA氏が定義してあるものに
違う人B氏が何も考えずにRc::clone(&a)で循環を入れてしまう事は十分あり得るでしょう。
状況次第ですが循環参照を考慮してないA氏が悪いのか、Rc::clone(&a)でぶち込んだ人が悪いのかは要件次第ですが
これを簡単と言わずに(あなたは言っていませんが)難しいと表現するのは違和感がありますよ >>42
詳しい解説ありがとうございますm(_ _)m
メモさせていただきます。 >>37
嘘を教えたらあかんやろ
N人の人が自分を指しているとして
まずそのN人をどうやって知る? >>45
自力で数えればいいんではないでしょうか? >>40
まあ、そういうこと。
というのは、参照カウンタも、1つのヒープノードに対して必ず1つ必要になるので、
ノード数が多いときには膨大なメモリーの無駄になるから。
それとノード数が多いときに参照カウンタを 0 クリアしたり、1足したり
する作業も馬鹿にならないと考えるプログラマが多い。
なぜかというと、そういう自動化を行わなくても、人が頭で考えて手作業で
NULLを入れても十分に安全にプログラムできるプログラマが多かったからだよ、
少なくとも昔のCプログラマには。
手作業でやってもとくに危険を感じないので、効率を落としてまで自動化する
必要が無いと思われている。
手作業でNULLを入れるのは難しくない。
ところが、コンパイラが自動で効率を落とさずにそれをやるのはめちゃくちゃ難しい。
それは人間の脳がそれだけ優秀だということだよ。 >>45
手作業で人間が頭で考えたら、難しく感じないプログラマが多かった、という
ことだよ。
難しく感じるプログラマも居る。
数学の才能だと思う。 コピーしたポインタを別スレッドに転送とかしてたら、いつNULL代入すべきかすら分からんしなぁ >>48
ああ、自動化の効率面の話か。
凄く効率が落ちるわけではないよ。
リンクで辿るだけだから。 >>47
違うだろ
ある時点でNヶ所から指されているとして
そのNヶ所をどうやって知る?誰がどのようにNヶ所を管理する? >>51
静的解析はコンパイラには難しいが、動的なら簡単。
人間にも、「一般性を持って」は分かる方法は無い。 言っておくが現実世界では俺は天才だと言われているから、俺が簡単だと
思うことは、大部分のプログラマには難しいと思うかもしれないがな。 >>52
データ構造は入出力の変化に伴いどんどん変化していく可能性がありますから人間は覚え追いきれないよね
さらに一つのmalloc毎にそれぞれそこをポイントしている利用者の数も利用者数も異なりますよね
それらのデータをどこでどうやって管理するつもりですか? まず前提が誤りです
変化を追えば覚えられます
思考実験できないんですか? >>56
利用者リストを覚えておくためにメモリが必要やね
それもmallocするか
mallocで取ってきたメモリ管理のために更にmallocが必要となってしまったぞ
利用者が増えてきたら利用者リストの領域が足りなくなる
またmallocするか
全てにNULLを入れるためだけに大がかりになってきたな
この方法は本当に大丈夫なのか? データが育っていったら100か所からリンクされるとか普通によくあるわけだが
その100か所にNULLを代入しにいくために100か所の場所をリストで持つのか
しかもmallocした各データ毎にリストを持つのか
全てにNULL代入はあきらめた方がいいんじゃね? アクセスするとたちまち例外発生するぬるぽにはどんなデータが格納されているのだろうか int* p1 = malloc(sizeof(int));
int* p2 = malloc(sizeof(int));
int* p3;
if (なんかの条件) p3 = p1; else p3 = p2;
free(p1);
p1 = NULL;
// p2はまだまだ使う
こういうときp3はどうするのかっていう すべてのヒープを**ptrで管理すればできなくもない気がする
参照するたびに有効かチェックしないといけないから激しく面倒だけど >>61
なるほど
参考になります
回答してくださってありがとうございました。 >>62
その**ptrの格納領域の確保がデータ事に発生
しかも伸長してしまいますね https://twitter.com/cpp_akira/status/1430779310885859330
最近はC++の発表資料を公開すると「Rustでいいじゃん」というコメントがたくさんつくのか…。Rustへの言及とか一文字も書いてないのに。
普及活動だと思うけど、さすがに嫌がらせチックに見える。
↓の資料公開した時の話っぽいんだけど、Rustでいいじゃんって言われてるソースが見つからない・・・
https://speakerdeck.com/faithandbrave/opunhua-gajin-muc-plus-plus-falsexian-zhuang-tozhan-wang
言われててもおかしくないとは思うけど、実際のところどうなんすかねえ
アロケータ回りがまだ弱いから少なくともゲームは10年後もC++のが強そう
https://twitter.com/5chan_nel (5ch newer account) >>27
まだ利用者がいるのに全てへNULL代入しにいく時点で破綻
つまりまだ自分以外の誰かが利用中かどうかを知らないといけない
つまり利用者リストを管理する必要がある おまえらスレチがすぎるぞ
まとめてどっかいってくれ >>66
Rust はメモリ安全性を保証することが論文で示されているので
どうしてもC++でないと出来ないこと(=まだRustが対応してないこと)であることを示さないと
「Rustでいいじゃん」となってしまうのは仕方ないかも Rustは言語仕様が未確定なのが懸念事項かな
実用上は大して困らないからどうでもいいんだけど
期待してたRust Foundationは何故かディレクター探し始めてるしw >>70
2018editionに2019のasync/awaitゼロコストサポートで言語としては完成でしょ? >>70
それを期待するならFoundationよりこっちかな
https://ferrous-systems.com/ferrocene/
2022年末にASIL-B認証が目標 >>71
まだOpenなRFCいくつあると思ってるんだ でもSchemeとか言語仕様も形式意味論も定まってるし とりあえず
https://doc.rust-lang.org/stable/reference/
のWarningを消してくれるだけでいいんだ
2018版だけでも確定できないのかな 確定できないというよりメンテする人がいないんじゃないかな
言語仕様に詳しいけどコード書くよりドキュメント書きたいっていう奇特な人が要求されるわけで ferroceneみたいに具体的な目標があって企業が投資してるなら進むだろうけど
リファレンスの更新とかあまり需要もないじゃない? 第三者が処理系を作れるレベルで言語仕様が固まれば普及が進むと思うんだけどね
Rust Foundationにはそういう方向性を期待してたけど想像以上に何もしなかった Foundationはもともと裏方に徹する組織だと言ってたし
その通りに動いているのでは
最近だとgccrsのライセンス絡みの知財チェックとかやってたかと 言語仕様が固まるってのは新機能の追加をやめるということ? 言語仕様とコンパイラのバージョンが一体化しているようではミッションクリティカルな領域で採用されない >>84
厳密に運用するなら機能を追加するときは言語仕様のバージョンも上げる
固めるのは言語仕様の1つのバージョンってだけで言語の進化をとめるわけじゃないよ >>84
現状では「今そのように動いている処理系」と「処理系の (不十分な) ドキュメント」がある状態で、
それのどこからどこまでが言語仕様として満たすべき要件なのか保証されている動作なのかがわからない。
追加するも何も今の時点でどうなっているのかわからん。
どこかにはあったりもするんだろうけど、開発者向けの議論の中などに分散していて「仕様書」としてまとまってないんだ。 安全性は型システムによるところが大きいから、仕様書が無いと使えないというのは無いと思うがね コンパイラだってバグがない保証なんてないんだから
テストするしかないね LLVMの中間表現に依存してる時点で、言語仕様をまともに設定するのは無理。
だから他のコンパイラが作られることもない。 仕様書、仕様書言っている人はOSやライブラリのAPIとかシステムコールとかはどう考えているんだろうね
MSDNだって盲信できるほどの信頼性はないし、OSS系なんてソースコードが仕様書状態だろ
もっと言えば処理系だってオプティマイザの仕様などは文書化されていなく、実際に調査しないと判らない事も多いよな こんな状態じゃc++の置き替えなんて夢のまた夢だな。 完全な仕様書wがないのが問題だ思うなら使わなければいいだけ
クッソ無駄なやりとりでスレ消費すんな 少なくともC++はもっとずっと細かな仕様が書いてある。
例で説明する時でも、変な例で説明せずに数学の教科書の様な粒度の細かい例で
説明されているで、数学の教科書の様な雰囲気を持っている。
Rustの場合、ライフタイムの説明をとってみても、ちゃんとした数学的説明になってない。 時々プログラミングは文系でも出来るという人が居るが、そういう人には、
数学的な説明とは何かがぴんと来ないかもしれないので、良い仕様書も
書けないかもしれない。Rustのbookの著者ももしかしたらそうなのかも。
本人は頑張って書いているつもりでも数学的な論法になってない。 高校数学レベルで言えば、ベクトルの和の定義は図で例を使って説明されるが、
3つの矢印で、c = a + b が説明される。
これは最も粒度が細かい説明で、これ以上簡単に説明できない。
ところがRustのライフタイム注釈の説明は、説明に使われている例が不適切で
とても長いが本質が説明し切れてない。
本来は、「ライフタイム注釈とは何か」を数式や擬似命令などを使ってせいぜい2ページ以内で
説明できるはずだ。
ところが実際の説明は、変な例を使って長々と説明されている。
数学的な説明になっていないので応用が効かない。
数学的説明とはほとんどの場合「パターン」だ。パターンになっているから応用が効く。
パターンとして説明されてないと応用が効かない。 コンパイラが一つしかない状況は現状メリットでしかない
C++のようなレガシー言語の轍を踏まない賢い選択 数学的説明にしたいなら、
「仮定」を置く。
「入力」と「出力」を明確にする。
「最も粒度の小さい例を書き、パターン」にする。
集合論や論理学の「かつ」「または」「積集合」「和集合」「背反集合」「区間の積」
などの言葉を使って書く。
ところが、Rustのbookはこのようなことが全く出来てない。 >>98
仕様書が数学的(パターン的、自動機械的)に書いてないので、厳密な
仕組みや仕様が分からず、他の人がコンパイラが作りにく。
だから、「Rustは実験してみないと分からない」。
ところが、CやC++やRuby,Java,C#,Pythonなどは実験しなくても分かる
ようになっている。それはなぜかというと、仕様が粒度が細かく説明されて
いるから、パターンになっており「パターンの一部への代入」や「当てはめ」
が出来るので頭の中だけで全てプログラミングできてしまうから。 ちょっと難解だが高速なスクリプト言語としては使えるとは思う。
でもC++の置き換えは難しいな。
なぜならC++で出来ていたことがRustには移植できないから。 なんやいつぞやのパターンマッチングの規格についてゴネてた子か ・Fortran/BASICからCへの移植は容易。単純なパターンが存在する。
アルゴリズムの変更は不要。
・C++からJavaやC#への移植は容易。単純なパターンが存在する。
アルゴリズムの変更は不要。
・C++からRustへの移植は困難。単純なパターンは存在せず。
アルゴリズムを根本的に変える必要がある場合がある。 嫌なら使うなでおわり
現状嫌でも使うしかないくらいまでのシェア獲得してないし 個人としては使いたいけど組織として導入するには仕様の確実さというのは必要なんだわ。 C++ドロップアウターがOOPを学び直すには良いんでないの 大手IT企業たちの方針
プログラミング言語「Rust」のための「Rust Foundation」設立 -- AWS(Amazon)、Microsoft、Google、Mozilla、Huaweiが創設
https://japan.zdnet.com/article/35166267/
Facebookが「Rust Foundation」に参加
https://japan.zdnet.com/article/35170192/ >>108
仕様の確実さってどういうの言ってる?
Rustでの具体例を1〜2個あげてみて? >>112
関連じゃわかんねーわ
Lifetime Elisionとかは分かりやすく仕様定義されてるっしょ で、それはどこにあるっていうんだ。
これについての仕様はこっちに有ってあれについての仕様はあっちに有って
詳細はブログのここにあって……でもこれは議論のための暫定的なまとめで……
みたいなのじゃ組織の中で話を通せんのよ。
「Rust の仕様はこれです」「これを満たした処理系は (少なくとも今のところは) Rust と呼べます」
というのが仕様書であって、そういうのが欲しいわけよ。 その論法は流石に違和感が強い
GAFA級の組織(のどこか)では採択されるのにその組織では通らないというなら、その組織か説得者が外れ値なだけでは? >>115
そのレベルの大企業というのは策定側で関与しうるし
投機的な技術的投資にも貪欲だから
「大企業は動きが遅い」「稟議が厳密」という感覚ではない。
グーグルが大規模なサービスを開始からそれほど間を置かずに畳んだことなんて何度もあるだろう。
ぽんっとやって駄目だったらポイッと捨てられるんだよ。 そういう考え方ならISO標準でもできてから検討すればいいよ
時期尚早で時間の無駄 実際のところC++みたいに委員会とかが仕様がっちり決める言語ってどんくらいあるの?
そもそもC++だって仕様は決まってもコンパイラが微妙に準拠しきれてない気がするんだが
gccとclangは実用上困らんレベルだとは思うが ISO標準のある言語で一番新しいのがRubyくらいか
もっと新しいのあったっけ?
やはりリリースから10年以上はかかる感じかね 今の時点ではアーリーアダプタが使う言語なんだという立場でやってるならそれでもいいんだけど、
個別には割と (どこかには) まとまってるっぽいからもったいねーなという感覚がある。 GAFAMだけでなく
日本でもNTTやTOYOTAなどもRustを採用しているわけで
まともな企業ならば支障なくRust採用を決定していってるでしょう 権威でものを判断したり
権威を借りて発言したり
頭ワリーわ
正気になれ >>125
「権威に訴える論証」という人間の性質なんだよ。
けっこう効果あるから詐欺師とかマスゴミが良く使う。 あの松下もわが社の製品を採用しているんですよ〜
情弱「ほほう、じゃうちも採用率するわ!」 メモリ開放の意味が解らない馬鹿に合わせるための言語なんだよな
馬鹿に合わせるとロクなことがない気がするんだけど わかってても間違えるのが人間なんだよ。
ヒューマンエラーを防止するのに「注意する」とかで対策を済ませちゃうわけ? >グーグルによればAndroidに存在した深刻なセキュリティー脆弱性の70%近くがメモリー安全に関するバグに起因するという。
>同様にマイクロソフトも、同社製品に存在したセキュリティー脆弱性の70%がメモリー安全に関するバグに起因すると述べている。
>C/C++を使う限りセキュリティー脆弱性を根絶するのは不可能と考えて、Rustを採用するに至ったというわけだ。
https://xtech.nikkei.com/atcl/nxt/column/18/00692/042700054/ C++で苦しんできた連中は
Rustのやろうとしたことは分かるし
例え失敗に終わっても責める気にはならん
どうころんでもしょせん死屍累々
Rustは人類の明日への尊い礎になるだけ >>125
そいつが権威主義的思考なのは確かなんだが
新興言語は大手の技術力ある会社がスポンサーにいて
継続的な投資が行われることが確実視されてるかどうかはすごく重要なこと >>123
二つともわけの分からん企業だな。
自動車と電話会社。 人々の関心の高さは感じるけどな。twitterとか見てると。 でもtwitterでは、Pythonも活況だし、KotlinもRustと似たり寄ったりの数、検索される。
なぜかQtやRailsは検索されにくい。Djangoは沢山検索される。
cplusplusは僅かに検索される。C++やC#は直接的にはそもそもtwitterでは検索できない。
Rustの話題性がPythonやKotlinやDjangoと比べて取り立てて多いということではないようだ。 The Bookは読まないくせにどうでもいいTwitter検索ばっかりしやがって
あーあのTwitterで独り言つぶやき続けてるひとだっけ?
忘れてた とにかく仕様が必要ならC++使えばよいのでは。主要メンバーがC++標準理解しているようなすごい人ばかりなんだろう >>138
自分達が「完全な仕様」と思えるものが存在することが重要視なんであって理解している必要はないんでしょ
ある種の宗教上の理由だよ 実際は、Rails : Laravel = 8:2。
Django は、0
どこの学校・サロンもほぼ、Ruby on Rails 確実にinline展開する方法ってある?
手動で書く?
マクロだとどうにかなる? >>134
自動車の制御はわからんでもない
即応性と安全性の両立を図らなければならないのだから #[inline(always)]でも100%ではないんだっけ? >>138
把握してないから必要なときにそれを調べればいいというようなまとまったものが必要なんだよ。 Rust以外で高信頼性指向だとAdaとかMISRA Cとか? >>143
実装はわからんけど、スペック的にはalwaysも飽くまでヒントらしい >>145
MISRA Cは言語じゃなくてコーディング規約みたいなもん
組み込み以外では厳しくて準拠してられないと思う ファッション感覚のバカしかアピールしてない言語だわ。
c++理解してない奴がライフタイムをまともに理解できるとも思わん。
それもわからんバカがcをバインディングなんかしたら事故しか起きんわ。
安全性もクソもない。 組み込み向けRustって1冊本が出たみたいだけど
実際のとこ、見込みありそうなの?
ただのホビー? >>148
C++ はわかっててもミスるんだってば。 C/C++知らないと〜と言う人には型理論知ってる?って聞きたくなる
コンパイルが通れば大体ちゃんと動くようになってるって感覚はhaskellとかOCaml寄りだと思う Haskell の型システムは好きなんだけど
さすがに副作用 (Haskell 的にはアクションだが……) の扱いがしんどすぎるし
元から C++ には慣れてるので C++ (というか C) 風な文法や意味論と
組み合わせた言語があったらいいなぁと思ってたので
Rust の台頭にはばんじゃーい ∩( ・ω・)∩ >>151
お前こそ型理論知らんだろ。。
型理論てのは結局どれだけ簡易な計算でエラーチェックするかってだけの話なんだよ。
正しく示すだけならただ単に全実行するのが一番良い。 ガファムがファッションでプログラミングしてるとは知らなかった twitterでRustは話題性があるように見えるが、ためしにLISPやSchemeや
Clojure(言語)を検索してみてもRustと似たり寄ったりの書き込みがあった。
Haskelが次代を担う言語だ、的な書き込みすらある。 今のgoogleじゃまともなc++プログラマもだいぶ減ってるわな。。
kumagiとかイキってるだけでまともに理解してねーじゃん。 >>156
Haskellの型システムをRustは受け継ぎつつCG無しでメモリ安全性を達成しているので
Rustが実用的なプログラミング言語として現実に機能していますね >>145
MISRAに従ってコーディングするの辛いぞ。 次のようなloop文のプログラム(可動)を
while文やfor文に書き換えてわかりやすくしたいのですが
上手く値をbreakできないので助けてください
fn main() {
let a = [3, 5, 1, 6, 9, 4];
print_first_even_else_zero(&a);
}
fn print_first_even_else_zero(a: &[i32]) {
let mut i = a.iter();
let even = loop {
if let Some(&n) = i.next() {
if n % 2 == 0 {
break n;
}
} else {
break 0; // not found
}
};
println!("{}", even);
}
例えばwhile文なら let even = while let Some(&n) = i.next() { となりそうで
さらに可能ならfor文で let even = for &n in a { となるかと思うのですが let even = a.iter().find(|n| *n % 2 == 0).unwrap_or(&0); >>164
当然それはわかりますが、for式やwhile式ではどうなるのか、という質問です 前スレより
625 デフォルトの名無しさん 2021/08/16(月) 09:44:36.63 ID:MZWGbmHz
loop式はbreakで指定した値を返せるのに
なぜwhile式やfor式は値を返せないの?
Option型にしてbreakで値を指定した時だけSome(値)としてそれ以外はNoneとすれば便利なのに
630 デフォルトの名無しさん sage 2021/08/16(月) 14:32:54.40 ID:ebJKRLr3
手間かけて機能拡張するほどのメリットがないってことだろうね
https://github.com/rust-lang/rfcs/issues/1767#issuecomment-292678002 そうでしたかすみません
forとwhileは値を返さないのでご想像のようにはなりません >>166
なるほど
そこでの議論を読むと一番の肝が、
「for式が()を返さないと、最後がfor式で終わる関数の返り値で互換性が無くなる」
というところにあるようですが
「break;」が()を返すことにすれば特に問題ないように見えます
実際にloop式で値なしのbreakだと()を返しています
つまり
・「for/while/loop式が返す型」は「break式の型」とする
・「値指定のない『break;』の型」は()とする
・「break式がない場合の型」も()とする
ここまでは現状と同じになりますね
問題はfor/while式はbreakせずともループを抜けるので、値を返すには、
・「『break 値;』があるfor/while式」は「else節を取ってbreak式と同じ型を返す」
という単純ルールだけで済むように見えます
何か見落としがあるでしょうか? >>169
なるほどありがとうございます
ところで現状のRustで>>163の例のloop式をfor式で行おうとすると
即時関数を使ってbreakをreturnに置き換えることで
let even = (|| {
for &n in a {
if n % 2 == 0 {
return n;
}
}
0
})();
と実現できることを思いつきましたが
この方法は表記コストはともかく実行コストもかかってしまいますか?
ちなみにこの「最初の偶数を見つけるコード」はあくまでも例として単純化したものを出しているだけで
実際には様々な例でこのパターン(=forやwhileで値を返せると便利)が出てくるので簡略な例題として話をしています >>168
イテレータのコードのほうが遥かにわかりやすい上に簡潔なので
新しく文法を拡張する価値がないと開発陣は考えてる点を見落としてる。る?
特にPythonの失敗例を鑑みれば機能追加される可能性は限りなくゼロ >>171
現実にはfindより複雑なことでも使うだろうし
async関数呼び出して判断もあるだろうし
イテレータでは無理なことも多いのでは? Rustに限った話じゃないけど新しめの言語だとイテレータで記述可能な
ループは、出来るだけイテレータで記述するのが主流じゃね
forだのwhileはループ条件の誤りから簡単にバグが生まれるし
使わないで済むならそれに越したことはない
CやCの派生系言語がメインの人には理解しがたいかもしれないが C++ だとテンプレートの組み合わせで回すのも一般的だけど
Go だと凝ったことするよりなんでも愚直にループを回したほうがいいというのは
基本的なスタンスになってるよね。 >>172
説得力のある実例を出せば今みたいにRFCが即closeされることはないんじゃない?
状況によってはイテレータを拡張したほうがいいという判断も有り得るし
今のforやwhileループみたいにmutで定義した変数を更新するのでも十分かもしれない >>173
なるほど
出来るだけイテレータで記述する質問です
コマンドライン引数の数字の和をイテレータでpanicさせずに求める場合
これよりもっと短く出来ないでしょうか?
fn main() -> Result<(), std::num::ParseIntError> {
println!("Sum: {}", std::env::args().skip(1).map(|s| s.parse::<i32>()).collect::<Result<Vec<i32>,_>>()?.iter().sum::<i32>());
Ok(())
}
以下のように正しく実行できているのですがコードが長いのが気になっています
$ cargo run 10 20 30 40 50
Sum: 150
$ cargo run 10 20 XX 40 50
Error: ParseIntError { kind: InvalidDigit } twitterで「Rust過激派がルール違反と判断された」
「CやC++のこと書いてた人にRustの話吹っかけて迷惑かけてた怖い人たち」
という話を見たが、誰の事?
どういうことなんだ? >>178
c++テンプレートテクニックの著者のことか? >>61
int* p1 = malloc(sizeof(int));
int* p2 = malloc(sizeof(int));
int* p3;
if (なんかの条件) p3 = p1; else p3 = p2;
free(p1);
p1 = NULL;
if (なんかの条件) p3 = NULL;
// p2はまだまだ使う
こうすればいいだけの話だろ?ガイジか?
このコードの後 p2またはp3どちらかをfreeしても二重開放にならんよ
このぐらいも考えられないのかガイジは(笑) いちいち差別的な用語を使わないとレスもできないのか
プログラマとしては一流なのかもしれないが、人間としては最低だな >>177
このcollectしてから再びiterするところを何とか出来ないものかなと
println!("Sum: {}", std::env::args().skip(1).map(|s| s.parse::<i32>()).collect::<Result<Vec<i32>,_>>()?.iter().sum::<i32>());
イテレータだけを使う限界?
同じことをfor文を使うと短くなってわかりやすくなります
let mut total = 0;
for s in std::env::args().skip(1) {
total += s.parse::<i32>()?;
}
println!("Sum: {}", total); std::env::args().skip(1).map(|s| s.parse::<i32>()).sum::<Result<i32, _>>()? ParseIntError返しても処理しないんだから
unwrap_or(0)みたいなので十分じゃないの?
fn main() {
let args = std::env::args().skip(1);
let sum: i32 = args.map(|s| s.parse().unwrap_or(0)).sum();
println!("Sum: {}", sum);
}
入力、計算、出力で分けてる >>184
非整数は飛ばす仕様になってる
エラーはエラーだと示すべきかな
あとエラー処理コードがないのは質問の本質じゃないからかと println!("{}", std::env::args().skip().try_fold(|sum, s| Ok(sum + s.parse::<i32>()?))?);
try_fold使うと?演算子の入る場所が変わらずに済むっぽいな >>183
なるほど!
sum()もcollect()のように様々な形の集積方法が指定できるのですね
i32整数一覧が入力に来るのにsum::<i32>()とi32型指定をしないと怒られた理由がようやくわかりました
sumとcollect以外にもそういう仕様のメソッドはありますか? いちいち固有のiterator使うとか可読性悪くなるだけって場合も多い >>186
素晴らしい!
少し修正して以下で上手く行きました
std::env::args().skip(1).try_fold(0, |sum, s| Ok(sum + s.parse::<i32>()?))?
fold()は知っていたのですがtry_fold()でOptionやResultの形でfold()できるとは便利ですね
ここまでまとめると
sum計算はResult型を返せるsum()があるので>>183でも行けて
このtry_fold()ならばsum計算以外にも汎用的に使えますね >>185
エラーだと示したいなら結果をハンドリングすればいいんじゃないの?
type Result<T> = std::result::Result<T, std::num::ParseIntError>;
fn main() {
let args = std::env::args().skip(1);
let sum: Result<i32> = args.map(|s| s.parse::<i32>()).sum();
match sum {
Ok(sum) => println!("Sum: {}", sum),
Err(e) => println!("Error: {}", e),
};
}
引数ゼロ個とかエラーは1種類じゃまかなえない
ハンドリングしたいならエラー設計がもう少し必要になるだろうね >>190
もちろんそんなことは皆わかっていて、最後のResultのErr処理は枝葉末節だから略して議論してるのだと思う
あとmain()でResult返してErrなら勝手にエラー表示してくれるみたいで便利
で、>>185で指摘したことは、>>184のunwrap_or(0)使用はエラーが消えるからマズいよね、ということでした >>191
何をそんなにカリカリしてるんだ?
main()でResult返したいなら別にそれでもいいんじゃない?
fn main() -> Result<()> {
let args = std::env::args().skip(1);
let sum: Result<i32> = args.map(|s| s.parse::<i32>()).sum();
println!("{}", sum?);
Ok(())
} >>192
皆がわかりきったことしか書いていなくて何をしたいのかわからないけど
Resultはエラー型も示さないとそのコードでは動かないよ 今回はargs部分も枝葉末節なので外してまとめ直すと
『数値と思われる文字列の配列が与えられた時に非数値があればエラーを返すとして』
let a = ["1", "3", "5", "7", "9"];
和の場合はmap()でResultのままsum()に渡してResultを返せる
let sum = a.iter().map(|s| s.parse::<i32>()).sum::<Result<i32, _>>()?;
和だけでなく積などもtry_fold()を使えばResultを返せる
let sum = a.iter().try_fold(0, |sum, s| Ok(sum + s.parse::<i32>()?))?;
let mul = a.iter().try_fold(1, |mul, s| Ok(mul * s.parse::<i32>()?))?;
今回はparse()で文字列→数値のResultだけど一般的にResultを返す関数なら応用可能
皆さんありがとうございました >>179
指摘している人も、加害者もエピステーメー氏とは全く関係ない人だと思う。 >>195
えぴすめーてーじゃないほうの共著者のほうでしょ ローマ字で takaha... の人のことか。
Ukic...の人も何か言ってるんだけどどういう相関関係なのか。。 >>174
Goは確かにその方針だけど、イテレータというか高階関数を受ける型が総称では無いから.collectや.mapなんて
型ごとに定義しないと使えないから。Go2になってくれば違ってくると思う
一方でPythonだとfunctools.reduceなんかより、リスト内包表記が使われるのは局所性で速度が速いからだけど
ループで書かずにかなり長い表現をこれで書かれると保守しずらい。
Rustでもイテレータを何回も取り出してcollectしたり、foldしたりをドットで繋げられるのはあまり読み易いとは
言えないと思う。普通にiter()を何度も呼ぶのなら、let it = a.iter();して欲しい collect()したやつに.iter()は確かにやめてほしい
終端操作するなら何か変数に入れた上でやってほしい AdapterとConsumerは必ず分けろってこと?
もちろん分けたほうがいい場合もあるだろうけど
別に一緒でもいいと思うんだけどな >>201
中間変数を使うか否かだけの問題だからどうでもいい話
言語自体やその利用方法に本質的な問題があるわけではない
一方で>>199のGoの問題は深刻
Rustがトレイトで解決している分野だ 上にあるコードでcollect()した後にiter()してるやつのことか
それなら分かる >>204
それコードを改善したいという相談やんけ
しかも最終的には>>194のコードへと短くわかりやすくなったのだからRustはよく考えられてるなあとしか >>206
だからこそcollect()した後にiter()してるコードは改善したほうがいいよって話だろ? 和も積も求めたい時はどうすればいいかな?
文字列から数値への変換を二度するのを避けるとして
一つの方法はこのように一旦collectとして数値のVecを作ってしまう
fn main() -> Result<(), std::num::ParseIntError> {
let input_numbers: Vec<i32> = std::env::args().skip(1).map(|s| s.parse::<i32>()).collect::<Result<_,_>>()?;
println!("和: {}", input_numbers.iter().sum::<i32>());
println!("積: {}", input_numbers.iter().fold(1, |mul, n| mul * n));
Ok(())
}
それともcollectせずにイテレータのままで止めておいて使う? >>208
foldで和と差の2要素のタプルをとりまわせば良いだけ こうかな
println!("和: {}", std::env::args().skip(1).map(|s| s.parse::<i32>()).sum::<Result<i32,_>>()?);
println!("積: {}", std::env::args().skip(1).map(|s| s.parse::<i32>()).product::<Result<i32,_>>()?);
println!("(和,積): {:?}", std::env::args().skip(1).try_fold((0, 1), |(sum, mul), s| { let n = s.parse::<i32>()?; Ok((sum + n, mul * n))})?); >>209
確かにこんな特徴的な勘違いをするやつが同時に二人出現するわけないわな >>214
C++ vs Rustスレでやれと何度言っても聞かずにここでイライラしてるよな 上のイテレータ関連の質問に便乗ですが、
二次元vecの各要素をv[i][j]としたときに、
jごとの総和を計算するやつをイテレータできれいに書く方法ありますか?
例えばこういうやつです
let v = vec![vec![0; n]; m];
// (vの各要素を設定)
let mut result = vec![0; n];
for i in 0..m {
for j in 0..n {
result[j] += v[i][j];
}
} >中間変数を使うか否かだけの問題だからどうでもいい話
Rustの場合、ライフタイムとオーナーシップの関係で
中間変数を使うか否かは結構重要な問題だったりする >>220
mapしてsumすればいいだけでは?
きれいかどうかは知らんけど >>212
これ競プロ用でしょ
一般的なプログラミングとは観点が違うから最初に競プロ用だと書いておいたほうがいいぞ >>222
mapとsumで書けます?
iごとの総和なら単純に
v.into_iter().map(|v| v.into_iter().sum()).collect()
みたいな感じでいけるとおもうのですが、jごとだとちょっとわからないです
>>223
そうですね(実はもともとの発端は競プロではなかったりするのですが (0..n).map(|j| (0..m).map(|i| v[i][j]).sum()).collect()
2重forをの親子を逆転してイテレータメソッドチェーンに変換しただけという感じ
こんなことよりもっと意味のあることに頭使ったほうがいい
イテレータでとあったから上を書いたが現実にはndarray入れてsum_axis使うのがいいだろう
https://docs.rs/ndarray/0.15.3/ndarray/struct.ArrayBase.html#method.sum_axis こんなかんじかな
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=e302c841c8dd709418f923ea1ad07868 >>225-226 インデックス自体のイテレータを作るって発想がありませんでした、ありがとうございます
競プロ用ではないしndarray使うのも考えてみます 汎用的には縦横入れ替えのtransposeを作っておけば色んな操作が楽かもね
イテレータ作成はサボってとりあえず関数版
fn transpose<T>(v: &Vec<Vec<T>>) -> Vec<Vec<T>> where T: Copy {
(0..v[0].len()).map(|j| v.into_iter().map(|vv| (*vv)[j]).collect::<Vec<T>>()).collect()
}
fn main() {
let v = vec![vec![1,2,3], vec![4,5,6], vec![7,8,9], vec![10,11,12]];
let w = transpose(&v);
println!("{:?}", v); // [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
println!("{:?}", w); // [[1, 4, 7, 10], [2, 5, 8, 11], [3, 6, 9, 12]]
} transposeみたいな関数用意すべきかは配列の要素数次第かなあ
たかだか1度しか読まないデータのためだけに配列全体をコピーするのはもったいないケースはありそう 性能気にするなら Vec<Vec<_>> の形で数値格納するのではなく
Vec<_> に格納して (i, j) -> j*n+i みたいにインデックスを変換してくれるラッパーを被せた方がよさそう >>223
競プロではむしろ回答時間や処理速度のほうが重要なので、
あえてこういうのをイテレータで実装しようとしないよ
おれなら間違いなくforで回す。わざわざイテレータで回そうと考える時間が無駄
だけど、後から振り返って、これをイテレータで1行で簡単に表示できるんじゃないかな?と思うことはよくあるんよ。
そして、ドキュメントを見返したり、他人のソースを見て、ああこういうやり方もあるんだなと学習する
競プロは実際のコーディングに役立たないという人もいるけど、
普段、自分が利用しないメソッドや方法を発見すること、実務で役立ちそうなアルゴリズムがあることを知る
という意味では意味があると思う >>235
競プロに対する君の考えを急に述べられましても・・・
誰も興味ないよ >>236
逆にいうと、君が競プロはこういうものだろうという勝手な解釈で意見を言うことにも意味がないということよ
それこそ誰も興味がない たまにLKMLのURL貼られるけどURLだけ貼られてもなんもわからん >>235
最適化まで考えるならforなんだろうけど、iterやcollectなんかが最適化が効かないのは今昔で、いずれは
最適化されるんじゃないだろうかと希望的観測を述べてみたり。実際gccなんかだとリンク時の最適化なんて
オプションあるし、あんまり凝ったiter/map/collect/foldだと理解に時間が掛かることはいなめない ぼくのかんがえた最強のコードが見下されたと思って悔しかったんだろうな
図星だったからこそ競プロでは逆にこんな書き方しないとか競プロは役に立つとか自己正当化に必死になる
追い越されたらバカにされたと思って煽り運転をする人と心理と同じなのでどちらの側も少し気を付けたほうがいい forよりイテレータのメソッドチェーンのほうが処理速度速かった気がするんだが やっていることが同じなら (最適化などによって) 結果のコードもおおよそ同じところに着地するよ。 せやな。 素朴なコンパイラならともかく
いまどきの最適化能力を期待できるなら
ポインタはエイリアス解析を困難にするから
むしろ足を引っ張る要素になる。 >>244
ポインタは適切に使えばデータ構造やアルゴリズム自体が根本的に変えることが
できるので使わない時と比べて計算オーダー自体が劇的に変化することがあり、
プラシーボではない。
Rustはその点でC/C++に勝てない事がある。 例えば、動的配列であるところのVectorはポインタでアクセスしても余り
効率は良くならないが、LinkedListは構造的にポインタで連結されており、
首尾一貫して添え字アクセスを使わずに必ずポインタでノードを識別する
ようにすれば、Vectorに比べて劇的に効率アップできることがある。
それはRustではほぼ不可能。ベンチマークはこの点が反映されてない。 >>240
最適化ではなくて、forを利用してindexで回さないとできないことが山ほどあるんだよね
例えば、二分探索や三分探索とか
foreach(a in vec)で順繰りに回せる処理ならいいけど、
そういう処理ではできないこともあるので、
forで回す前提で考えたほうが、あとから修正する余地があるので、どうしてもforでindexで回すことになる
これは、イテレータのほうがループが速いというのと、また別の問題 rustのforは他言語でいうforeach(a in vec)やろ for each 的なループで書いたものを二分探索に直す時点でプログラムとしては別物になりそうなんだけど
元のコードを iter じゃなく index アクセスするコードにしておくことでこの書き換えがどれほど楽になるのかね
まあここまでくると個人の好みの話なのでお好きにどうぞとしか言えないが Rustのfor式を理解してなかったんかーいっ!!! >>250
それは違う
まず1点目
リスト対するfor文をforeachと書かずforと書く言語の方が非常に多く一般的
C++もJavaもJavaScriptもPythonもRubyもAwkもshもリストに対してfor文
次に2点目
Rustのfor文はIterator loopと明確に書かれてるようにリストや配列に対してではなくイテレータ正確にはIntoIteratorを実装するものに対して >>254
恥かいたので頑張って調べましたってレスなんだろうけど何一つ理解できてないぞ
もう一回調べ直してこい 調べたのにfor式を理解できんかったんかーいっ!!! Rustのforで二分探索ってどうやるのか気になる どうせ自分で二分探索なんか実装しないだろ
気にするな
標準ライブラリ使え >>258
for _ in 0..log2(n) as usize 的に回せばいいんでは?
まずやらないけど >>260 それでどうやるかわかんねーんすけど
少なくとも>>249が言ってるforでindex回すってのとは違うような >>254
もちろんRustのforはVecや配列に適用じゃなくてイテレータに適用
だからリスト処理しかできない言語のfor/foreachよりはRustのforは適用範囲が広い
しかし
>>258
for以前に確定しているデータしかイテレータ内で使えなくて
これはforの中で算出されたデータを借用規則によりイテレータに反映させられないためで
forの中でif分岐などする形で二分探索は無理と思う
しかし
元々の>>249が言う
「forを利用してindexで回さないとできないことが山ほどある。例えば二分探索とか」も間違い
このforはC言語などのfor (index初期値; index条件判定; index更新)を指しているが
二分探索はindex更新が状況により増減変化するためfor(;;)文を使えない
無理やりにforを使っても更新項がないため最初からwhile文を使うのが正解
つまりCでもRustでも同じでforではなくwhileが使われる こんな感じ?
fn binary_search<T>(array: &[T], target: T) -> Option<usize> where T: std::cmp::PartialOrd {
let mut left = 0;
let mut right = array.len() as i32 - 1;
while left <= right {
let mid = (left + right) / 2;
if array[mid as usize] == target {
return Some(mid as usize);
} else if array[mid as usize] < target {
left = mid + 1;
} else {
right = mid - 1;
}
}
return None;
}
Cで書いてもほぼ同じコードになるね
同じコードで任意の型に楽に対応できるRustの方が有利かな >>262
常識的なことを盛大に勘違いしてるので
>>254と同一人物なのモロバレだぞ
自分の書いたレスに他人のフリして間違いを指摘しようとするのは控えめに言っても病気 >>249
お、249は俺だ。
言われてみれば確かに二分探索でforはないなww
while max-min > 0 とかそんな感じだった。飲んで書いてたからすまんすまん
でも、イテレータでなくてindexでやるほうが便利なことのほうが多いのは事実なのよ
動的計画法で現在の参照している配列の前後の内容を参照する時とか indexが便利なことの "方が" 多いの?
indexが便利なこと "も" 多いならわかる 自分は競プロでRustを使ってるけど、その範囲では圧倒的にindex うーん、こういうのはイテレータだけでもいけるね
ttps://atcoder.jp/contests/abc138/tasks/abc138_d
static mut tree_list: Vec<(i64, i64)> = Vec::new();
static mut job_list: Vec<(i64, i64)> = Vec::new();
static mut res_list: Vec<i64> = Vec::new();
fn main() {
unsafe {
input! {
edge: i64, job: i64,
tree_list0: [(i64, i64); edge-1],
job_list0: [(i64, i64); job],
}
tree_list = tree_list0;
job_list = job_list0;
res_list = vec![0_i64; edge as usize + 1];
unsafe fn calc(index: i64, count: i64) {
res_list[index as usize] += count;
for &(a, b) in &tree_list { if a == index { calc(b, count); } }
}
for &(a, b) in &job_list { calc(a, b); }
for i in 1..res_list.len() { print!("{} ", res_list[i]); }
println!();
}
} Rustは、Tiobe index で、少し前に始めて20位に入ったが、今見たら
24位に下がってる。
このランキングの信憑性にも議論の余地はあろうが。
でも、日経の調査ではプロが使っている言語のTOPは、C/C++ということなので、
その調査とも整合はしている。
他の調査でも、CとC++を合算するとTOPか、2位になる。 https://www.rust-lang.org/ja/production/users
には、Rust公式サイト(?)で製品に使っている企業名が書いてあるが、
聞いたことが無い企業が多い。それはそういうものなのかもしれないが。 また荒らしが来てるな
ところで非同期関数を呼ぶとfuture/promiseを返すだけでそのタイミングては実行開始しない怠惰タイプのプログラミング言語はRust以外に何があります? >>275
それはそう。
C++ を使ってる企業を並べてもほとんどは知らん企業になるはずだわ。 >>279
イテレータも理解してないのに他スレでRustをバカ推しすんなよな >>269
せめてfutures::io::AsyncRead,AsyncWriteトレイトあたりで中立に互換性問題なんとかしてほしい >>283
いちゃラブ ((っ´ω`)♡(´ω`⊂ )) すればすぐわかるのにね let a = [10, 20, 130, 40];
let v = vec!a;//←これってなんでダメなんですか? >>287
そういう構文規則(syntax)だから。
二行目は、vec! はマクロ名で、直後からはマクロの引数列が続く。
そして、その引数列は決まった形式で書く必要があり、
vec!a という形式はそれに当てはまってない。 >>287
vec![]の[]は配列リテラルではなくて、一般的にマクロ呼び出しは[]か()か{}で引数を渡す
なので実はvec!(1)やvec!{1}も通るのだが、配列リテラルの見た目と合わせるために普通[]が使われる >>288
>>289
ありがとう
コンパイラの言い分もよくわかんなかったし、助かったぜ Cのvolatileって低レイヤで多用されるにもかかわらず実装依存なんだな
処理系依存の属性値的なのと同じようなもんか
Rustはcoreの中にvolatileアクセス用のメソッドが用意されている分進んでいる 何らか単純なmacroリライトとは異なるproprocessorが必要になりそうね
cとかlisp(cより遥かにまし)みたいなエラー挟み込むだけのマクロよりかは
rustのマクロはマシよね殆ど利便性は特になくcompile前にregex雑魚ver replace導入してるだけだけど
まぁ、素直なアプローチというか何というか(´・ω・`) rustの勉強のため自作のbashコマンドを、rustで書き直してるんですが、
コマンド置換( $(echo ) )はどうやればいいでしょうか?
Command::new('hoge').args......は調べたのですが、コマンド置換の方法が
どうしてもわかりません。 >>294
Command::outputでstdout取得してきてそれをコマンド列に埋め込むとか? インタプリタを作るのでなければ置換の必要性ある?
例えばこういうことが出来ればいいんだよね?
let s = format!("今日は{}曜日です", String::from_utf8(std::process::Command::new("date").arg("+%a").env("LANG", "ja_JP.utf8").output()?.stdout)?.trim_end()); >>294
rustで書き直すのにCommandは違くないか?
bashのランタイムでevalしてるだけじゃん >>298
Command は system 関数相当じゃなくて fork/exec だから shell は関与しないと思ってたんだけど違うの? >>299
fork/execだからとかそういう問題じゃなくて、
外部コマンド使うんだったら、それは単なるラッパーだろうと
要求する機能を満たすだけなら別にそれでも良いと思うが、
勉強のためにrustで書き直すというなら違和感がある
自作コマンドの内容にもよるけど >>299
もちろんshellは関与していない。
環境変数PATHに従い直接起動。
>>301
どのプログラミング言語で書いていようが、外部コマンドの呼び出しは普通にある。
それをゼロにするかどうかは様々なコストの問題。
例えば、そこがボトルネックになったら内部化など。 >>301
shell を作ってるんだから外部コマンド呼び出してなんぼだと思うんだが >>304
自作のbashコマンドを自作の bash 互換シェルと読んでコマンド置換の仕組みを作ろうとしてるのかと思ったけど
もしかして bash スクリプトで書いたコマンドのことだったりする?
それにしたって外部コマンド含めて自作する必要はないと思うが なるほど
>>296と書くのではRustで書き直したことになっていないとはそういう意味か
これでいいのかな
use locale::Time;
use chrono::{Local, Datelike};
let s = format!("今日は{}曜日です", Time::load_user_locale().unwrap().short_day_name(Local::now().date().weekday().num_days_from_sunday() as usize)); $ foo=$(bar $(baz))
↓
let foo = bar(baz()) >>294
>rustの勉強のため自作のbashコマンドを、rustで書き直し
https://github.com/uutils/coreutils/blob/master/src/uu/echo/src/echo.rs
> コマンド置換( $(echo ) )はどうやればいいでしょうか?
https://www.joshmcguigan.com/blog/build-your-own-shell-rust/
https://zenn.dev/garebare/articles/a463257c447fa9
独自shellスクリプトをbashやzshのように実行する際は標準入力を逐次読むインタラクティブシェルの
動作モードの他に第一引数のスクリプトパスを受け取り連続的に動作するようにしなければなりません。
上記のサンプルのように変数やコマンド置換を展開(子プロを作って実行結果を保持する)パーサーが
必要になります。(上の例ではリダイレクトやパイプなどしか処理していませんが)またファイル先頭の
#!/bin/shと同じようにshebangを認識するのはOSが行います。
そのほかにもifに使われるや"["もしくはtestなどは大昔はコマンドでしたが、現在は多くのシェルでは
組み込みのビルトインコマンドになっています。
また現在でもbashなどでクラッシュさせる脆弱性が発見されていますが、GNU bashの場合はパーサーは
手書きではなく、parse.yなどのyaccです 想定外。
シェルスクリプトで書かれてる日常ツール類を、高速化&練習ついでにRust化、ってのはよくある話なので、今回もそういうことかと想定してた。 grepの書き換えとか入門用テキストあるあるだしな俺もそれかと思ってたw
インタープリターみたいの作りたいなら単純に考えて$(.+)みたいの発見し次第rustで書かれたプログラムに書き換え
この際$(.+)の.+の部分にもrust書き換えプログラムを同様に適用のrecursiveな奴考えるな
match等でregex構文が扱いやすい分rust native interpreterみたいの造りやすそう
あとそうゆうのredosだかなんだかのrust os projectみたいのあるから見たら面白いんじゃね(´・ω・`) nullの可能性がある複数の参照を作りたい場合って
OptionとかRcを組み合わせるの?
縦によも横にもコードが長くなりそう Option<&T> や &Option<T>でも良いかも知れないけど状況次第
可変参照にしたいなら Rc<RefCell<Option<T>>> とかになるかも Rustの文化詳しくないけど、null objectは使わないの?
せっかく静的安全性にこだわっているのに、型無しのnullを使うのはこだわりが足りない気がするなぁ。 OptionがあるのにNullObjectいらなくないです? >>314
見当違い。 >>312 はどこも指さない参照を便宜的に null と言ってるだけで、
実際には代数的データ型を活用して区別しようとしている。 >>316
正解
ただし、Rc<RefCell<Option<T>>>とか見ちゃうと
生ポインタにしたくなってくる…… 参照をRcするような場面てあんまりないような気がする
ところでRc<RefCell<Option<T>>>は、
参照じゃなくてヒープにある(かもしれない)Tの共有になりませんか >>319
実体は必ずヒープ上
実体の構造は(強,弱,(借,(Some,T))
そしてそのヒープ上にある実体を指してるポインタはどこにあっても複数あってもよい >>319
ヒープ上にある RefCell<Option<T>> を共有することになるね
参照 (&T) ではないというのはそう >>316 >>318
サンクス。JavaのOptionalみたいなものね。
>>317
nullobjectと比較したときのメリットは?
条件分岐を強制させることができることくらいかしらん? >>322
impl<T> SomeTrait for Option<T> where T: SomeTrait { ... }
ってやれば条件分岐すら自分で書かなくていいよ >>323
それはTraitのメソッドで分岐相当のコードを書くか
chainさせるだけで分岐処理を遅延するかのどちらかなので
分岐すら自分で書かなくていいというのはちょっと違う気がする 本来はOption/Result/(Either)はRust言語的な仕組みでは無く、ライブラリの作法に過ぎないが、ランタイムが
無いはずなのに、Resultなどで宣言しているところで原則として捕捉しないpanicがあるのは納得できない人は
結構いると思う。言語の構文でmatchや?など、まさにそれのサポート構文があるのに、unwrapしたらpanicで
この話は嫌がる人が結構いるけど、OptionもResultもPanicも取っ払った最小の標準ライブラリが欲しい >>325
そこは使い分け。
エラーな時にそのままエラー吐かせても構わない場合は、main()をResult型にしてしまうし、
きちんとエラー処理する必要あるものな場合は、少なくともmain()やそれより下でmatchでResultを必ず受け止める。 >>322
比較すべきものではない
ヌルオブジェクトはインターフェースで型を隠蔽する手法
一方Optionは型をラップすることでエラーを明示する手法
似てるようで根本が違う あと後者の場合、unwrap()も基本的には使わない。
例外的に使うのはフィルタし終えて必ずSome(T)となっているものを剥がす時だけ。
つまりpanicはさせないので、その>>325の懸念事項は発生しない。 素人です、質問させてください
Rustでスマホアプリやwebアプリは作れますか?
作れるとしたら
java/kotlinやswiftやjavascriptより作りやすいですか?
アプリ制作でこれらの言語よりRustは優れてますか? Rust+JavaScriptでウェブアプリとそのためのサーバーサイドは作れる
ウェブブラウザ上ではJavaScriptが必須なのでRustだけにはできない
ただしウェブブラウザ上ではJavaScriptに加えてWebAssembly(Wasm)も動いてこれはRustで書いたプログラムが動く
なのでJavaScript部分を最小限にしてRustで書いたWasmがメインというケースもないわけではない
サーバーサイドはRustだけで全て構築できる ありがとうございました
スマホアプリを作るならKotlinやswiftってことなんですね
大変に参考になりました。ありがとうございました。 >>332
そんなことはない
スマホアプリならKotlinとSwiftの2種類を無駄に覚えずともJavaScriptだけで両OS向けスマホアプリ作成が可能
もちろんスマホでもウェブアプリが動きアプリの種類によってはウェブアプリで十分なためスマホアプリを作らないケースも出ている
一方でRustで書いてAndroid上でツワモノもいるがそれはおいとくとして
Rustをこの件で使うケースはウェブブラウザで動くWasmのプログラミングする時かサーバーサイド側
あとはGoogleがAndroid OS開発にRustを使い始めた めっちゃWasm使ってるわ、使い心地としてはgoのが良いのだが
てか絶対JS書きたくない勢以外は勧められないけどな
エントリーポイントで4〜5行JS書かざるを得ないが、そこはコピペだから俺は1行も書いてない >>335
javascriptからwasmにディスパッチする際のオーバーヘッドってどう? getopt()みたいなのでRust標準はどのクレイト? clapだけど、それを使ったさらに便利なstructoptのほうがおすすめかも clapはv3でstructoptの機能を取り込むから、今ならclapの3.0.0-beta4を使うのでもいいかも >>339
その後、structoptはどうなるの? >>339
なるほど
v2のビルダー方式に加えて
v3でマクロ多用で見やすく書きやすくすっきりしたという感じ? マクロは見やすさだけじゃなくてコンパイル時に諸々チェックされるのが嬉しい 数値の並びがある時に
その中の一番大きなものがある場所(index)が欲しいのですが
Rustではどう書くとよいでしょうか? >>343
たとえばこう
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c7a0d0459c540d7b373b124d7faf239a ありがとうございます
無しでもいけました
別の質問です
Vecにスライス(の各値のコピー)をappendしたいのですが
append()メソッドはVecしか引数に取れず困っています
どうすればいいでしょうか? >>346
append()はその名前から想像しにくい実はムーブで引数側のVecは空になるw
じゃあappendはどうすればいいかというと
1つだけappendするpush()の複数版のpush_all()が元々あって
それは名前変更で今はextend_from_slice()になった
がその中身はより一般化したExtendトレイトのextend()を呼んでるだけになったので
結論としてはv.extend(&a)が正解 faqのような気がするんだが、以下のようなコードって
どうすればコンパイル通る?
#[derive (Copy)]
struct St{
s: String
}
fn main(){
let ar = [St{s: String::from("str")}; 10];
} 参照を配列に格納するか
let st = St{s: String::from("str")};
let array = [&st; 10];
Stringじゃなく&strにするか
#[derive (Debug, Clone, Copy)]
struct St{
s: &'static str
}
かな? >>352
なるほど
勉強になりました
ありがとん >>351
Stringはヒープ上なのでstructの中でCopyは無理
>>352
そのStringも使わずにこれでいけますね
#[derive(Clone,Copy,Debug)]
struct St {
s: &'static str,
}
fn main() {
let ar = [St {s: &"str"}; 10];
println!("{:?}", ar);
} もはやご希望のものかどうかはわからんが
#[derive(Clone)]
struct St{
s: String
}
fn main(){
let ar = vec![St {s: String::from("str")}; 10];
}
CopyをCloneして配列をvecにしただけ >>355
vec!は単なるマクロでVec作ってるだけなので
それだと動的にヒープにString作って
そのVecを動的にヒープに作ってる
一方で>>354はヒープを全く使わないという差ですね >>354
>そのStringも使わずにこれでいけますね
それ>>352に書いてるのと同じじゃんw >>351
その後の用途によって7通りのやり方がある
let st = St {s: &"str"}; の場合は
let ar = [st; 10];
let ar = [&st; 10];
let ar = vec![st; 10];
let ar = vec![&st; 10]; の4通りが使い分け可能で
1番目はまとめて let ar = [St {s: &"str"}; 10];
3番目はまとめて let ar = vec![St {s: &"str"}; 10]; と省略可能
2番めと4番目が省略できない理由は参照なのに実体が変数にバインドされていないため
let st = St {s: String::from("str")}; の場合は
let ar = [st; 10]; の1番目だけは出来なくて
let ar = [&st; 10];
let ar = vec![st; 10];
let ar = vec![&st; 10]; の3通りが可能
3番目はまとめて let ar3 = vec![St {s: String::from("str")}; 10]; と省略可能
1番目が出来ない理由はヒープ上に作られるStringを暗黙的にコピーできないため 数百行程度で、Rustらしいコードの例ってありませんか? 現状はどのレベル?
とりあえず入門書は読み終わったって感じ? >>362
例えば>>3と>>4にあるRust各book十数個のうちどれくらい読んでみましたか? >>365
それはあまりにも偏った特殊ケースであることと
初心者向けではないということと
その件だとむしろ標準ライブラリとして提供されているリンクリストや双方向キューを覚えた方が実用的かなーhttps://doc.rust-lang.org/std/collections/ Rustは可読性をもう少し良くできなかったのかな
後発なのにJavaより読みにくいってのは問題だろ Javaより読みにくいとはさすがに思わんけど、
ジェネリクスが<>囲いなところとか、
そもそも中かっこ+セミコロンってのもどうなんだ、とか
Haskell並にとは言わんがもうちょっとかっこ少なくかけないのか、とか
思うところはいろいろとある >>372
ジェネリクスが<>囲いなところ、ってメジャーなプログラミング言語のほとんどがそうだよね? >>373
その通りだけどあんまり筋がよくないことでもちらほらごく一部の界隈で話題になってるような >>374
コンパイラ実装の問題なら承知した上で敢えて <> 採用してる
曖昧性の問題は turbofish で解決するなどコンパイラ実装を複雑にしない範囲で慣例的な記法に近づけている
>>375
Rubyの影響ってクロージャの記法のことかな? クロージャの記法は各言語で様々だから大して気にならないけど
こう書きたいのに書けないのが悲しい
fn make_counter_closure(init: i32) -> impl FnMut() -> i32 {
let mut counter = init;
move || counter--
}
この件はRustやRubyだけでなくPythonやScalaやSwiftなどでも同じで
Swiftでは昔は出来たのに後から削除されたようだから最近はそういう傾向なの? >>378
RubyのクロージャがSmalltalk由来だからどうなんだろ >>379
++と―はバグの温床だからそういう傾向
Swiftから削除されたのもRustでrejectされてるのも同じ理由 >>380
起源をたどればそうかもしれないけどRustが直接的に影響を受けたのはRuby ベストなジェネリクスの書き方ってなんだよ
Scalaみたいなのがいいの? Scalaみたいに[]にするのもアリだけど配列がちょっとアレになるからさすがに避けたい気がする
D言語みたいに、例えば定義時には
struct(T) Foo { foo: T }
impl(T) Foo {
fn(T) new(foo: T) { Self { foo } }
}
みたいな感じにして、使用時には
let bar = Foo!i64::new(42);
って感じにするとか・・・?
実際に書いてみるとこれはこれで微妙な気もするが >>379
そこは
{ let result = counter; counter -= 1; result }
または
{ counter -= 1; counter + 1 }
になるの? move || { counter-=1; counter }では??? 後置であるということをそもそも認識できていなかった、やっべえ >>385
初期Rustは [] だったけどまさに配列と被るからと言う理由で <> にした
C++と親和性のある構文を目指しているので <> 以外は採用されにくいと思う 型変数を明示しなきゃならないのは汎用プログラミング言語の欠点だよな let mut counter = init + 1;
move || { counter -= 1; counter }
これが普通だと思うのは俺だけか? >>395
Rubyだと普通にそういう書き方するから特に違和感はないな 配列がusizeだけなのを何とかして欲しい
i32 as usizeとかいちいち面倒 >>397
普通に開発していればむしろusizeという別の型になってるおかげでミスなどに気付けて助かったことある人多いと思う
i32と別になっていることは非常に重要 usizeだとうっかりマイナスにしちゃって死ぬことがある
デバッグビルドならぱにくって気づくけど、
テストすり抜けちゃうとやばい i32は流石にどうかと思うけど
グリッドの4-隣接とか8-隣接をforで回すときに中心からの差分で表現したくて、
isizeとusizeでガチャガチャ変換したときはちょっとウザいなーとは思った impl From<u16> for usize はあるのに u32 はないのが面倒
usize のサイズがプラットフォーム依存なのは分かるけど毎回 trt_from().unwap() したくない Rustの難しさってある程度マスターしたあとは納得の難しさなんですか?
面倒だなー。でも(メモリ安全のためには)しょうがないか〜、みたいな 補助輪なし言語でバグなしプログラム作れたらどこに行っても採用されると思うよ >>405
asでも良いけどreleaseだとオーバーフローチェックしてくれないから心許ない
constの文脈だとunwrap使えないからas使わざるを得ないけど オーバーフローの懸念がある文脈ならtry_fromはしょうがないのでは
usizeがu32以上のプラットフォームだけ想定するならasでいいように思えちゃうんだけど asを使うとu32から別の型に変更したときに修正漏れのリスクがあるのが気になってしまう
まあfrom相当のユーティリティ関数自分で用意すれば良いか >>398
じゃあunsafe時には許可して欲しい 緩く簡単に書きたい人向けの言語じゃないよね全体的に それはそう
緩く簡単に書けるせいで起きていた全てのバグを撲滅したい、的な執念を感じる IntelliJ Rust pluginの新バージョン、関数とかの補完を機械学習でやるんだってさ
すごいね
試してないけど 誰も見ていなければ海や川でも裸で泳ぐCちゃんと
温泉の女湯でも深夜一人で水着で入るRustちゃん エラーハンドリング可能な形ですっきりしたルールを定義できるならやればいいんだけど
現実にそういう上手い方法がないなら煩雑でも変換の手順を書くしかない。 低レイヤーいじる言語のエラー処理内容の粒度はそれこそプログラムごとに違うとしか言いようがない。
だから仕方ない。 >>414
泳いでるのをDQNに見つかって乱暴されるCちゃん
そもそもDQNに覗かれるような温泉には入らないRustちゃん as usize祭り絶賛開催中
unsafe fn calc(a_index: isize, b_index: isize) -> isize {
if a_index == a.len() as isize { return 0; };
let mut res: isize = 0;
for i in b_index..b.len() as isize {
if a[a_index as usize] == b[b_index as usize] {
res = res.max(calc(a_index + 1, b_index + 1) + 1);
}
}
res
} >>420
関数に定義されていない変数が使われまくり
forループの中に変動変数がなく毎回同じ実行
キチガイのコードを読むべきでなかった unsafeだしな
そして、その指摘にas usizeを擁護(容認)する意見は皆無だっていう あと祭り発生中の実況だったので稼働するコードではなく、
if a[a_index as usize] == b[i as usize] {
}
と修正した なんでunsafeなのかもわからないしなんでusizeじゃなくてisizeを受け取るのかもわからん 引数がマイナスになることもあるので条件判断の必要からisizeなんだよね
もしusizeを引数にするとしても、引数に渡すところでisize as usizeになるので、やっぱりusize祭りが大発生
お祭りワッショイワッショイ 引数がマイナスになるならチェックしないと範囲外アクセスするだろ馬鹿か? >>425
グローバル変数を使うのはありえないな
staticは使ってもモジュール内に閉じ込める
どの言語でも常識 そもそもusizeで受け取って呼び出し側でケアすべきやろ >>412
経験的に、縛れば縛るほど最終的にはラクできるようなのを皆知ってると思う
ラクに書けるような言語は一見いいのだが
人間が生まれ持って自堕落であるのを伴って
最終的には苦しみをもたらすことになるコードを書いてしまう >>420も煽りのつもりで普段書いてないrustを
イキって書いたんだろうけど
煽り返された上にクソコードが掲示板に一生残るのは辛いよなあ いきなり unsafe fn とか書いてるあたり普段からrust書いるが競プロとかでついた変な癖を引きずってる人だと思う
余計悪いが >>437
ゴミカスコード力を披露するコードだよ
Rustどうこう言うやつはこのレベルが多い usize祭り絶賛発生中
while !next_pos.is_empty() {
let mut tmp_next_pos: Vec<(i32, i32)> = Vec::new();
for &(n_yr, n_xc) in &next_pos {
map[n_yr as usize][n_xc as usize] = 2;
for (a_yr, a_xc) in around(n_yr, n_xc) {
if a_yr >= 0 && a_yr < m_yr + 2 && a_xc >= 0 && a_xc < m_xc + 2 {
if map[a_yr as usize][a_xc as usize] == 0 {
map[a_yr as usize][a_xc as usize] = 2;
tmp_next_pos.push((a_yr, a_xc))
}
if map[a_yr as usize][a_xc as usize] == 1 {
total += 1;
}
}
}
}
next_pos = tmp_next_pos;
} isize ってどういう時に使います?
添字は基本的に usize しか使いませんし符号付き整数が欲しくなったらi32かi64で大体事足りるのでいまいち使い所が分かってません 添え字に使う値を算出する途中計算で負数が必要になったら isize が妥当という場合もある。 can isize and usize be different in rust?
Can isize and usize be different? Both of them can be used for memory size, index, offset.
Since usize is used for arrays why don't we just have usize
I am new to Rust so this might be a basic question.
・usize cannot be negative and is generally used for memory addresses, positions, indices, lengths (or sizes!).
・isize can be negative, and is generally used for offsets to addresses, positions, indices, or lengths.
https://stackoverflow.com/questions/55506647/can-isize-and-usize-be-different-in-rust
意識高い系がウンコードを量産し罵倒するクソスレ そして、その結果、as usize祭りにもなる場合もある >>432
経験的に縛れば縛るほど脱法行為が横行する。 RustlingsをReplitで動かして学習したいのですが、これってrustlingsコマンドはどうやって動かすのですか?
https://github.com/rust-lang/rustlings
公式サイトが用意しているReplitの環境で学習をやりたいのです
よろしくお願いします >>446
ReplitのRustのバージョンが古くて(1.44)ビルド失敗するっぽい
見た感じローカルでやるのとそんな変わらん気がするから、
こだわりないならローカルでやるのが吉
この環境ビルドむっちゃくちゃ遅いし >>439
なぜそんなに下手なの?
配列のインデックスを取り出して配列をアクセスしてるだけなら
そのインデックスは最初からusize型にしておくだけてしょ >>445
脱法行為もなにも>>420のコードで負のindex渡されたらおかしくなるやんけ とはいえasナントカが一部のシチュエーションでめんどくさくなることはある(主に競プロ)
let (h, w) = (100usize, 100usize); // 多くの箇所ではusizeとして扱っている
let grid = vec![vec![0; w]; h]; // 横幅w 縦幅h 左上のマスの座標(0,0)のgrid
// 省略(なんかいろいろやる)
let (x, y) = some_func(); // 着目対象となるgridのマスの位置を(usize, usize)で取得
// (x, y)の上下左右のマスを対象になにかやる
for &(dx, dy) = &[(1i32, 0i32), (-1, 0), (0, 1), (0, -1)] {
let (x2, y2) = (x as i32 + dx, y as i32 + dy);
if x2 < 0 || x2 >= w as i32 || y2 < 0 || y2 >= h as i32 {
continue; // x2,y2がgridからはみ出してたら処理飛ばす
}
let (x2, y2) = (x2 as usize, y2 as usize); // できるだけusizeで処理したいので
// 省略(x2, y2を使っていろいろやる)
}
上下左右調べたいときに負の値が出てくるのがめんどくさい
一応workaroundはあって、for以下をこうする手がある
!0が2の補数的には-1として扱えるのでオーバーフローOKな足し算をする
for &(dx, dy) = &[(1usize, 0usize), (!0, 0), (0, 1), (0, !0)] {
let (x2, y2) = (x.wrapping_add(dx), y.wrapping_add(dy));
if x2 >= w || y2 >= h {
continue; // x2,y2がgridからはみ出してたら処理飛ばす
}
// 省略(x2, y2を使っていろいろやる)
} 競技プログラミングは
正しいプログラミングスタイルから離れていく悪です
競技プログラミングスタイルな人と一緒に開発したい人は存在しないでしょう 正当なスタイルが分かった上で競技としての割り切り方も分かっているなら問題ないんだけど、
競技から学ぶと変な癖が付きやすいというのは私も感じるなぁ。 >>441
off_tとかptrdiff_tの代わり
例えば <*const T>::offset なんかはisizeを引数に取る >>450
自分はだいたい座標やwidth/heightはi32で扱って
indexへの変換処理を関数に抽出してそこでusizeに変えてる
一次元配列に二次元データ入れるときも自然に書ける type off_t = i64;(64bitOS)だからisizeを使うという発想は分かる。
でも厳密にはRustにNonZeroなどがある以上は、"本来は"実装されたfnが正常に動作する数値範囲があり
プリミティブ型で数値範囲を再定義し型定義出来ると便利だけど…、Type Aliasがあるのに無いのが辛い。
別言語の例
type Natural = range[0 .. high(int)]
type RegisteredPort = range[1024..49151, int]
type SomeSignedInt = int | int8 | int16 | int32 | int64
反対だ、コンパイルが遅くなるだけだという意見も絶対に認めない!もあるが、上記のNonZeroなどを見ると
将来的には実装されるのではなかろうか、いやヌルポインタ最適化のためのNonZeroだから入らないのでは?
という意見も分かるが…
またas演算子でキャストは安全だという話だが、符号付きから符号無しへの変換は、当然、どういう結果に
なるかを知っているべきだが、基本的な事をすっ飛ばす人も多いし、負を許容するoffsetが明確かどうかは
コードをすべて追わないと分からない場合が多い。なおこれが出来ると、コード中のキャスト変換が減るので
動作も早くなると思われるし、fnにした時の引数チェックも行わなくても良い状況が期待できる。
現実的に今のバージョンならindexもoffsetもisizeで作り、負を許容できない所にチェックを入れるだけで
as usizeは使わなくて良い箇所なら使わない。 >>450
let mut test = 100_usize;
アンダースコア使うと読みやすいぞ。おぬぬめ winitのmasterでstdwebのサポートが切られてweb_sysに一本化されていた
stdwebってオワコンになりつつあるのかな? >>455
NonZeroはOptionとかのサイズ最適化やポインタの値がnullでないことを示すのが主目的なので
汎用的な範囲を組み込み型で示すのはちょっと違うかと
必要ならnewtypeパターンで自分で作ればよい 配列がusizeなのはpythonなんかのa[-1]の最後尾アクセスを見てると、なぜそんな言語仕様にしたのかと
off_tなんかを見ると不思議に思う。いずれも Index bounds checkが掛るのに。符号無し64bitの巨大な
配列が欲しかったから?でもi128とかあるし インデックスiが実行時に決まるとき
配列のアクセスを内部的には *(p + i) にしたかったからじゃないかな
マイナスのとき〜っていう分岐をそこに入れずに最速でアクセスしたかったと >>459
>符号無し64bitの巨大な配列が欲しかったから?
配列にマイナスの値は使わないんだから、そのぶんMAXの数を増やしたほうが
オーバーフローしにくいから安全だろってことらしい
でもどうせi32 as usizeとかi64 as usizeするから意味ないんですけどね! >>459
32bit環境だとisizeにするとbyte配列が2GBくらいしか扱えないからじゃないのかね
ついでに一応16bit環境もサポートしてるみたいだし 競プロの書き方を仕事でするわけないだろ
何言ってるんだ アホか
競プロと仕事、書いてる時間がどっちが長いと思ってる
競プロは趣味 仕事で書いてるほうが圧倒的に長い
競プロでの書き方が仕事に引きずられることがあっても逆はない
そういうヤツがいるとか嘘をついてまで、
競プロに難癖つける理由がまったく理解できんわ お前が競プロスタイルで仕事するかどうかの話じゃないし、競プロに難癖つけてもいない 競プロRustスレを専用に立てて分離するのがベストな解決かな。
大多数を占める普通のRustプログラミングをする人たちにとっては役に立たない、特殊な競プロのコーティング方法が書かれても、批判議論に陥りがちでお互いにメリットないと思うのです。 難癖つけてるだろ
> 競技プログラミングは
> 正しいプログラミングスタイルから離れていく悪です
からの流れだからな >>470
それ自体は合ってますよ。
もちろん各々を使い分けられる人もいるでしょう。
でもそれはその人個人の内部の話。
競プロなプログラミングスタイル自体は、正しいプログラミングスタイルから乖離しています。 なんで競プロの話になってるんですか?
usizeをasしまくるのが競プロってこと? >>472
グローバル変数を用いたりunsafeを闇雲に利用している点 >>462
>>465
その一緒に仕事してるという競プロの人は、どんな困った記述してるんですか?
参考までにコードを晒してくれると助かる
まさか仕事でグローバル変数やunsafeを闇雲に使ってるわけじゃないですよね? 闇雲にunsafeを使うどころか脳死で全部の関数unsafeにする勢いだからな asはみるけどunsafeは競プロじゃめったにお目にかかれないような これ初めて知ったんだけど
Webブラウザサイド(フロントエンド)もRustで書けるのね
html!マクロでRustソースの中にHTMLもそのまま書けて更にその中にRustコードが書けてReact.jsのJSXみたいな感じね
https://yew.rs/ja/
Yew は WebAssembly によってマルチスレッドなWebアプリのフロントエンドを作ることができる、モダンな Rust のフレームワークです。 alert使うだけでunwrap使うwebsysは使いたくない unwrapはそこらじゅうのサンプルで見かけるが、Rustクックブックでは、unwrapを許可していません。
こういう事も敷居が高い理由です crates.ioのライブラリを読んでて見つけたんですが、
traitを実装するのに、まず構造体に直接同名のメソッドをimplして、
traitの実装ではそれを呼び出すだけ、みたいな方式でやられていました
Sがstruct、Tがtraitだとしてこんな感じです
impl S {
pub fn f(&self) {...}
}
impl T for S {
pub fn f(&self) { self.f(); }
}
これってimpl T for Sのほうに直接実装するのに比べて何かメリットがあるんでしょうか? >>480
alert()って簡易テストくらいでしか使わないような
>>481
意味が不明です
>>482
例えば今適当に作った例だけど
struct S { x: i32, y: i32, }
impl S {
fn fmt(&self) -> String {
format!("({}, {})", self.x, self.y)
}
}
impl std::fmt::Display for S {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "S{}", self.fmt())
}
}
fn main() {
let s = S { x: 123, y: 456 };
println!("{}", s.fmt()); // (123, 456)
println!("{}", s); // S(123, 456)
} >>482
内部用の非公開関数は
impl S { }
の方にしか書けないから実装は全部そっちに書いて
impl T for S { }
からは呼び出すだけにした方がすっきりする場合がある >>483
これ見て思ったんだけど、
メソッド名と引数全く同じだった場合で、
構造体のメソッドがpubで、
トレイトのほう優先的に呼び出したい場合ってどうするの?
そもそもメソッド名被らせるなって話ではあるんだけど すみません、impl Sもimpl T for Sもpubは付いていませんでした……
Tがpubなので、外部にはTの実装としてのfだけが見える状態ですね
>>483
振る舞いを変えたいなら分ける意味も分かるんですけど、完全に同じなんですよね
>>484
すっきりするというのは確かに読んでて思いました
実際非公開の関数が他にもありました
結局これが最大の理由なんですかね?
>>485
こんな感じでいけますね
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=10cdbd17798b14faa5fb6619ceb0739d >>473
match お前の職場にはコーディング規約がないの? {
規約でunsafeが許されている => { ならunsafe使うの自由だろ。問題があるなら規約を改正しろ }
規約でunsafeは禁止されているが使ってるヤツがいる => { ならなんでunsafeを利用してコーディングしてるヤツがいるんだよ。そいつをなんとかしろ }
}
結論 別に許可されてるなら自由だろ
それが問題だと思うなら上司にいって禁止させるのが先 おっと最後にこれが必要か
_ => { コーディング規約ぐらい決めとけ。決められてないぐらいの組織にいるなら文句いうな。諦めるか転職しろ } 規約で禁止されていてみんな守ってる場合にコーディング規約決めろと怒られるバグ >>491
規約で禁止されてるなら単純にそいつの問題だろ
それがなんで競プロの影響になるのかまったくわからんぞ 動かないコーディング規約を作られても困るわ
どのタイミングでもいいから自動で弾く仕組みまで作らないと
…誰かgit hookの練習で作ってみない? こういうキチガイがいて邪魔だから
競プロは専用スレを立ててそこへ隔離すること rust書いたことない障がい者が騒いでるな
ゴミコード晒して叩かれたのが相当悔しかったのか
なら自分の腕を磨けよ
やってることが数人しかいない過疎スレを荒らすって
どうやったらそう言う思考になるわけ そら競プロの解答コードが規約破りまくりなの見れば関係はあるわな そもそもunsafeの利用の明確な基準って決められるのか?
利用を完全に禁止することはできるかもしないが、使ってOKな条件を担当者の最良が入り込む余地がないレベルで厳密に決めるのは難しそう >>498
例えばVecの実装にも一部unsafeが使われておりunsafeは忌避すべきものではなく有用なものであるがその使用には厳しい条件がある
@unsafeが極狭い範囲に閉じ込められており抽象化されたインターフェースによりその存在を意識せずに使えること
Aunsafeを使用することで明白にその操作の効率が良くなるもしくは低レベル操作によりその使用が避けられないこと
Bunsafeの使用部分がその関係する範囲全体の一貫性において完全に安全な操作であると確認できること
以上3点が関係者により合意確認できている場合のみunsafeの使用が認められそして上位ではその存在を気にせず安全に使うことができる >>498
unsafeのコードにはレビュアーを最低5人指定すること
とすればok 使わざるを得ないパターンを提示(この時点で滅多に無い事が分かる)、当てはまらない物は原則禁止
本来要らない箇所で使おうとする輩が湧いて出ないようにするのが目的 ノーコメントunsafeは問答無用で禁止くらいのことはしてもいいと思う
そのくらいunsafeはやばい stdのunsafe APIに関してはそうだと思うけど
crates.ioのライブラリ群にまでそういうの持ち出されると面倒だなあ clippyもpubなunsafe fnにはドキュメントコメントに # Safety のセクションがないとデフォルトで警告出すので
コメントつけるのは最低限やっておくべきラインだと思う
https://rust-lang.github.io/rust-clippy/master/#missing_safety_doc 競プロの人ってレギュレーション守れば何してもいいって考え方の人が多いよね。
規約次第ってのが正にそれ。
unsafe みたいに取り扱いが繊細な機能は基本使わない、使う時には議論した上で限定的に使うみたいな感じに取り扱うのがほとんどだろ。
規約で機械的には決められないと思うよ。 競プロでunsafeなんて使わないよ
グローバル変数おじさんなら知らんけど 久々にusize祭りキタ━━━━(゚∀゚)━━━━!!
unsafe fn calc(bit: i32) -> i32 {
if bit == 0 { return 0; };
if DP[bit as usize] != -1 { return DP[bit as usize]; };
let mut start_id: i32 = 0;
for i in 1..=K_NUM { if bit & 1 << i == 0 { start_id += C_NUM[i]; }; }
let mut res: i32 = i32::MAX;
for i in 1..=K_NUM as i32 {
if bit & 1 << i > 0 {
let mut end_id: i32 = start_id + C_NUM[i as usize];
let mut num: i32 = end_id - start_id - (SUM[end_id as usize][i as usize] - SUM[start_id as usize][i as usize]);
res = res.min(calc(bit ^ 1 << i) + num);
}
}
DP[bit as usize] = res;
res
} Rust競プロでグローバル変数(static mut)はマジでおすすめしないぞ、ほんまに
意味わからんWAの原因になりうる
https://qiita.com/qnighy/items/46dbf8d2aff7c2531f4e >>509
それはRustだけでなくcやc++でも起こることなので、注意すれば大丈夫ヽ(´ー`)ノ
Rustだから駄目、c++ならokという根拠にはならないから >>511
1%でもダメな箇所があったら全部ダメって考える人? 規約になんもないからってunsafeまみれだとぶっ叩かれるぞ
そう、actix-webの作者のように >>507 添削しました。お収めくださいまし。
1. 安易にグローバル変数を使うな。状態を引数で持つくらいやれ
2. 引数bitが負になるのかくらい考えろ。脳死でi32とusizeをコピペしてるだろテメー
暗黙のキャストが無い==明示的にキャストすればいい、じゃねえぞ
パッと見て汚いなら設計が汚えんだ。動的プログラミングだから汚えんじゃねえ、テメーが汚えんだ
…負数になる可能性がある場所はたったの1行じゃねえか!どうした?頭使ってる?
4. unsafe外す努力もしねえのか、どうした?5回deleteキー押せば外れるぞ?
5. 値とインデックスが混ざるような書き方、どうして怖がらない?ロボトミー手術でも受けたのか?
6. C/C++には無い機能も使わず、warningもlinterも無視して、一体どうしてrustで書いてるんだ?
勉強中とすら言えねえじゃねえか。
まさか、VBAスクリプトを.javaファイルにコピペして「動きません!javaはクソ!」とか言っちゃう伝説のコーダーなのか? 質問です
デフォルト値を与えるトレイトDefaultについて例えば
#[derive(Default)]
struct S { a: i32, b: i32, c: i32 } の時に
let s = S::default(); と書いても同じ結果で短いのに
let s: S = Default::default(); と書くのはDefaultトレイトのdefault()だと明示するためでしょうか?
結局deriveすると
impl Default for S {
fn default() -> Self {
S { a: 0, b: 0, c: 0 }
}
} を自動的に定義してくれるという理解であっていますか?
驚いたのは
let s = S { b: 123, ..Default:default() };
とすると残りフィールドをデフォルト値展開してくれて S { a: 0, b: 123, c: 0 } が得られることでした
そこでderiveを使わずに自分で
impl Default for S {
fn default() -> Self {
S { ..Default::default() }
}
}
と手動かつ内部をDefault::default()に任せてみたところ
再帰しているとコンパイルで警告が出て実行するとコアダンプでしたw
なぜ? >>517
Default::defaultはどこでも使えるから癖で使ってる人が多いんだと思う
S { b:123, ..Default::default() }は残りのフィールドを展開するというより、
S::default()の所有権を奪ってbだけ書き換えたものを返すという理解が正しい
, ..に続くのは構築しようとしているものと同じ型の値
例えばS { a: 123, ..s }のようにも書ける
, ..Default::default()と書けばSが期待される箇所なので, ..S::default()と同様になる
以上を踏まえれば最後のコアダンプの原因はS::defaultの無限再帰によるstack overflowだと容易に理解いただけよう >>518
なるほど!よく考えれば
let base = S { a: 0, b: 0, c: 0 };
let s = S { b: 123, ..base }; の時と同じstruct base式の構文だったのですね
結局、以下のように自分で展開したところ(当たり前ですが)上手く行きました
impl Default for S {
fn default() -> Self {
Self {
a: Default::default(),
b: Default::default(),
c: Default::default(),
}
}
} Defaultトレイトのdefaultと明示するため、で合ってるよ
Arc::cloneにもそのような文化がある >>513
1%のダメな箇所で他の言語の文句言ってるのはrust信者の方ですけどね。 まあ、100%良いものなんてないんだし、子供達がせっかく作ったものを評価し、使ってやるというのも、年長者の優しさってものだろう。
今までどれだけ色々な言語が作られ、流行る、主流になると言われては下火になっていったことかと思えば、Rustもまたいずれ他のものにとってかわられるのが世の流れではあるだろうが、それならそれで良いじゃないか。
諸行無常 >>522
Rustを置き換えるにはコンパイル時点でのメモリ安全性保証を実現しないといけない
Rustは諸問題を解決してしまったので代わりの言語は数十年出てきそうにない
もし出てきたときには手続き型ではなくなってるだろう >>524
ボンクラPGは排除できるから意外と良い選択かもw みずほはもっとマクロなレベルでの設計の問題じゃないの知らんけど 昔の 1% は (注意を払うという対処法で) なんとかなったが現代のコード規模の 1% は深刻だという話なんだよ。 静的チェックでその1%が埋まると思ってるのがお気楽だなと思うわ。 usize祭りコネ━━━━(゚д゚;)━━━━!!
let mut dp = vec![i32::MAX; n_list.len() + 1];
for &i in &n_list {
for j in 0..dp.len() {
if dp[j] > i {
dp[j] = i;
break;
}
}
}
let mut cnt = n - dp.iter().filter(|&x| x != &i32::MAX).count(); vscodeでセーブした時に、ifに付けちゃった括弧を外して欲しいんだけど、何をどう設定すればいいの? 処理系の勉強をかねてRustで
ttps://www.sigbus.info/compilerbook
これをやってみようと思う
序盤で二分木&再帰・・・うへー >>532
二分木はむしろ非再帰で組めといわれたら罰ゲームなんですよ‥‥ なんかこのスレ競プロの厄介な人に乗っ取られた?
クソコードを延々と貼り付けてるあたり開き直ったか 競プロは別スレ建てて分離しましょう
競プロの件はいずれもRustを利用&学習する人々にとって役に立たない有害なものばかりでこのスレと別件ですから >>535
いやRustで競プロをする人もいるじゃんね
Rustを使用している人は、仕事だけの人、競プロだけの人、仕事でも競プロで使う人、のそれぞれの合計
ということは、そこから競プロを排除するってことは、より少ない人数だけを対象にするスレを立てるってことだから、
競プロの話題を禁止したい人が、「Rust原理主義者スレ」とでもして、自分たちが別スレをたてて
原理主義者たちだけで移動するのが論理的かつ合理的ヽ(´ー`)ノ >>537
あなたはまず何の説明も無しにコード貼り散らかして祭りだとか言うことの目的を教えなさいよ ブログトップにキモい自撮り写真貼ってるやつを見てから
競プロ臭のくっさいコードはスルーすることに決めてる >>538-540
スレッドは知識の集合知である場所だと思うから、
B木を考えても、情報が細分化される場合には、
携わる人数(情報)が少ないほうを葉にするのが妥当だと思うけど
>>539
Rustにはメリットもあるし、デメリットもある
様々な側面から、こういうことがあり得るとか、こういうこともできるとか
そういう情報がプラスになるんじゃないかと思っている
仕事のみの人にとっては競プロの書き方は我流だと思うだろうし、
競プロでも書いている人は、別に仕事で競プロの書き方はしてないが
直感的にやりたいことができないこともあるという思いもある
そのあたりの折り合いを付けるのが正しいRustスレなんだと思うんだよね。個人的に。
だから競プロ以外の話をしたいなら、原理主義スレを立てればいいし、
競プロだけの話をしたいなら、競プロスレを立てればいい。
ただし、ここはRustのrootだと解釈している ってことで以降は競プロ禁止
やりたい人は競プロのスレで >>542
そういう強権的なやり方は嫌われると思う >>541
要はフィードバックが欲しくてソース貼ってるのか?
ならせめて入力仕様と出力仕様くらいは書こうな
競プロなら問題へのリンクでもいい codeLLDBを消去しやがるからavastアンインストールしてやったわ >>541 添削しました。お納めください。
1. Cをそのままコピペしただけじゃねえか
Rustの機能を試すだぁ?enumもtraitもパターンマッチも使えないのに何が検証だ馬鹿野郎
「Cコピペしたけどメリット無いね!」って後何回繰り返すんだ?
2. なんだこの察してちゃんなコードは。保育園にいるつもりか?
意図の明確なコードが1行も無いんだが?
3. お前がここにゴミを貼る妥当性が一つも無い
Rustの世界に持ってきた概念のどれも使わないで、何が検証できると思ってるんだ?
例えるなら「ひらがなしか知らない外国人が日本語の良し悪しを検証します!」っていうもんだぞ
誰がマトモに付き合うんだ? >>529
CやC++だと非安全コードはどこにでも現れる可能性があるので100%のコードを人力で確認する必要があったが
rustでは安全性に関してはunsafeな部分のみ(例えば全体の1%)を確認すれば良いという話では
静的チェックで100%なんとかしようという話はしていないと思うが そうだなーと思う反面unsafeだらけのコードを目の前にしてげんなりする未来も見えるという… ほとんどの用途でunsafeを直接使うことは無いんじゃない?
グローバル変数はOnceCellで解決してしまったし
もし生ポ操作するとしたら新たな型を作ってその中に閉じ込める そういうコードが書ける事が問題だとあれほど批判してたのに >>551
それは何も問題ではないよ
例えばVec型もpushやpopですら内部はunsafe利用だけど我々はそれを知らず気にせず安全に使うことができる そもそも競プロにメモリ安全性とかいらないしC++で書いといてくださいよ Rustの良いところはメモリ安全だけではなかろう? 機能性で言えば競プロに必要なものは大抵の言語が備えてるだろうし
使いやすさで言えばRustはきっちり書くことを求められてるから素早く書くのには向いてないし
それでも敢えてRustを選ぶ理由は趣味や慣れくらいなのでは releaseビルドするとTrojan:Script/Wacatac.B!mlを検出して
Windows Defenderに怒られる
--release付けないと大丈夫
誤検知かな? >>553
ごめん
例えばUnsafeCellの存在はRustの借用ルールに制約されることなく自由に新たな型を設計して作る道を開いているけど
あくまでも安全な型を作るための素材であって具体的にはRefCellやOnceCellなどの様々な安全な型を提供する素材となっているように
unsafeの存在も上位レベルで安全な関数やモジュールを提供するための素材としてのみ用いるべきではないか
ということを伝えたかったのです つまり競プロ君のunsafeの使い方はただ危ない逸脱のみであり、
安全かつ便利な何かを提供する目的のための使い方ではなく、
Rustの精神に反している、と。
したがって競プロの話は、
このRust本スレでやるべきことではなく、
ここでは禁じて別スレでやるべき、と。 >>559
競プロくんを競プロの代表扱いするのはさすがに競プロの人に失礼では Rustの精神とかそんな大層な話でもないでしょ
建設的に話せない奴に付き合う必要はないというだけ >>558
違う人が書いた事を、さも自分が書いたように返答するのはどうかと思う >>562
え??
>>558は自分の意見を書いただけでこのスレにしか書いていないし参考にしたサイトや書き込みもないよ
もし偶然にそっくりな内容なものがどこか他にあるなら見てみたいので教えて >>559
こういう自分の意見にあわないと何でも排除したいヤツはどこにでもいるんだよなあ Range関連での質問です
(Included(&x), Included(&y)) はx..=yと書けますが、
(Excluded(&x), Included(&y)) を似たように書く方法ってありますか? >>565
ないんじゃない?
(3..=5).skip(1)で、妥協するかなぁ Range はよく使うから構文糖を入れてちょっと簡単にするという判断がうまれたんだと思うんで、
それほど頻出しないパターンは明示的に書くしかしょうがないと思う。
自分のプログラムでよく使うのであればそういう関数を用意しておけというくらいの妥協になる。 >>565
range式も魔法があるわけではなく
それぞれ対応する構造体があって各traitなどを実装してるだけなのですが
stdにあるのは以下の6種類のみですね
assert_eq!(.., std::ops::RangeFull);
assert_eq!(3.., std::ops::RangeFrom { start: 3 });
assert_eq!(..7, std::ops::RangeTo { end: 7 });
assert_eq!(..=7, std::ops::RangeToInclusive { end: 7 });
assert_eq!(3..7, std::ops::Range { start: 3, end: 7 });
assert_eq!(3..=7, std::ops::RangeInclusive::new(3, 7));
例えば開始点のあるRangeFrom・Range・RangeInclusiveはIteratorも実装
一方でその(Excluded(&x), Included(&y))形式すなわち
(Bound<T>, Bound<T>)および(Bound<&'a T>, Bound<&'a T>)型だと
実装されているのはRangeBoundsトレイトのみでIteratorトレイトなどは無いという違いがあるようです
開始がUnboundedだと意味がないからでしょう
つまりイテレータで回したい時にはこの形式では使えないので
(Excluded(x), Included(y)) は (x+1)..=y と書くしかないと思います
もちろんSkip構造体のコストを払って(x..=y).skip(1)もアリです >>566 >>568
すみません、言葉足らずでした
BTreeMap/Setのrangeメソッドに渡す引数を意図していました
こちらに渡すのはイテレータではないのでskip(1)はできないようです
>>567 >>568
あまり頻出ではないですし仕方ないですかね
実際困るわけではないのですが、
アンバランスなので気になってしまいました ttps://lkml.org/lkml/2021/7/7/349
完全にストップしたな。最低だよ。 Rust for Linuxに関しては結局それ以降進展無しということ? そりゃ普段の作業はGitHub上でやって、まとまったところでパッチ投げるんだから
LKMLで日々の進捗報告なんかしたら迷惑でしかない いや実際のドライバーが動かないのにごねてるだけやん。。話になってないんだが。 as usize祭りの回避ができてきてる━━━━(゚∀゚)━━━━!!
let mut heap: BinaryHeap<Reverse<(usize, usize)>> = BinaryHeap::new();
heap.push(Reverse((0, 0)));
while let Some(Reverse((_, now))) = heap.pop() {
let mut que: VecDeque<(usize, usize)> = VecDeque::new();
que.push_back((now, 0));
while let Some((next, cnt)) = que.pop_front() {
if cnt == price[now].1 { break; };
for &i in &list[next] {
if total[i] > total[now] + price[now].0 {
total[i] = total[now] + price[now].0;
heap.push(Reverse((total[i], i)));
}
que.push_back((i, cnt + 1));
}
}
} VSCodeか何かで、編集中のファイルを(保存する度ではなく)リアルタイムで構文チェックしてもらうことってできないの?
目が悪いもので、C#みたいに間違えたら即指摘みたいなのがすごく助かるんだけど・・・・ rust-analyzer入れれば若干のラグはあるけどそんな感じでやってくれると思うが >>581
IntelliJRustにon the fly analysisあるぞ 普通にVscodeでRustの拡張入れたらやってくれん?
俺が思てる構文チェックとかの支援とは違うんかな vscode+rust-analyzerでオートセーブ無効でもリアルタイム構文チェックしてくれるよ いつrust-analyzerに移行するか悩み中。 >>586
Auto Saveオフだと、指摘してくれないやつ結構ない?
セーブして初めて指摘されるやつが結構あるような rust-analyzerってvimでも使える?
流石にvim捨てるべきかなあ rls から rust-analyzer の移行なんて躊躇するもんじゃないぞ。
試して合わなければすぐに戻せばいいだけだし、戻りたいと思う可能性は俺はゼロだと思う。 >>588
構文チェックとrust-analyzerの検知できる型エラーは保存しなくても指摘されるはず(前者は即時、後者は少しラグがある)
rustcじゃないと検出できないものは確かに保存時しか出ないかもね
特に害あるものじゃないしauto save有効にしても良いのでは? >>589
実際にビルドしてみてそのエラーメッセージをエディタに反映するという仕組み (いわゆる flycheck) は昔からあったんだが、
頻繁に実際にビルドするんじゃなくて処理系の構文解析プロセスとエディタを連携させればもっと効率的なんと違うか?という
のがマイクロソフトによって LSP (Language Server Protocol) として標準化されたという経緯がある。
エディタにとっては場当たり的なエラーメッセージの解析をせずによくなったので昔より楽になってるんだよ。
昔から flycheck をやってるようなエディタはだいたい LSP にも対応してる。 https://thenewstack.io/linus-torvalds-on-community-rust-and-linuxs-longevity/
> “Probably next year, we’ll start seeing some first intrepid modules being written in Rust, and maybe being integrated in the mainline kernel.” 統合早いな。多言語プロジェクトでcargo面倒くさい問題はなんかやってんだろうか?
統合されたらソース読んでみよ。 言語を組み合わせる場合を含めてビルドプロセスの記述はなんだかんだで make が万能なんだよな。
クソみたいに場当たり的だけど必要だから機能を追加してきたという現実の前には
どんな美しいパラダイムも砂上の楼閣という印象だわ。 cargoが勝手にクレートダウンロードしてくれるのは便利だけどね
セキュリティ的には……どうなんかなー ビルドはmakeからrustc呼ぶ形になってたはず
カーネルに関してはクレートのダウンロードなんかもしないならそれで問題ない >>596
既存のものがクソだから俺が全く新しいクールな奴を作ってやるぜ!っていって新しいクソが1つ増えるのはもはや伝統芸やね >>597
そのための --offline オプション >>600
makeの機能を持つprologは欲しいなぁ。
論理プログラミング言語を拡張したmakeとか堅牢そうな気がするけど、誰もやらないのかしらん。 宣言的なものの依存がゴタゴタしたもののデバッグのしずらさを知らんのだろう。呑気なもんだ。 rust-analyserだかに移行しようとうおもったけどemacs とは相性悪過ぎて結局rlsに戻した
analの方はcodeいれんとインストール出来んかったりとほぼvs用だなあれ(´・ω・`) >>605
lsp-modeとの組み合わせで普通に使えるが マジかeglot使ってたからかも
何かfunction defとかの問い合わせ方法間違ってんのか知らんが常にno docみたいのがmessage表示されて使いもんにならんかった
lspってマジで全然分からんちんで小鳥の餌待ち状態で微塵も弄れないのよね俺(´・ω・`) rlsもlspだよ
rlsのlsはlanguage serverのls >>607
標準ライブラリのソースコードがないとか?
rustup component add rust-src
で入ると思う あんま多くは試しでないがrust-analyzerインストールする時に入れさせられたvscodeではanal pluginで動いてたしanal自体はインストール出来てると思うんだがな
>>608
そのfuckin msの策定したlspを部分的にとか言語ごとに異なるoverrideてかimplで構成するプロジェクト群がrust-analyzerとかclangdだかとかgoplzとか
ただこれらだけじゃ意味不明のjson object返したり読み込んだりするだけのdaemonで役に立たないから
仲介者としてのeglotとかlsp-modeが必要になる
ここらまでも簡単に弄れるというか(弄れる必要があると言うのか...)がemacsの良いところ(´・ω・`) インストールもなにも実行ファイルのパス通すだけだからね
~/.vscode/ 配下にあるはずだからそれを使うか GitHub からダウンロードしてくれば良い べき剰余をオーバーフローさせずに作る関数を作ったヽ(´ー`)ノ
fn calc(num: usize, pow: usize, m: usize) -> usize {
let mut bit: usize = 1;
let mut res: usize = 1;
let mut tmp_pow: usize = num;
while pow >= bit {
if pow & bit > 0 {
res = (res * tmp_pow) % m;
}
bit = bit << 1;
tmp_pow = (tmp_pow * tmp_pow) % m;
}
res
} >>613
普通にオーバーフローするが
calc(usize::MAX, usize::MAX, usize::MAX-1); 多分競プロのやつだから各数値は32bitなんだろう
そらオーバーフローしねえよって話 ↓これと同じアルゴリズムなのに>>613のは読みにくいね
https://ja.wikipedia.org/wiki/冪剰余#途中で剰余をとる
u64で受け取って内部ではu128で計算して
u64で返すようにしとけばオーバーフローしない u16ならu32、u32ならu64、u64ならu128みたいな関係をジェネリクスで表現できたりする? trait作ってassociated typeで表現するのはできるかな Traitを各データ型に対して全部実装するのが面倒だから
対応する倍のサイズの型を表現する方法はないのかなって話だったんだけど
なさそうってことだね コンパイラを単純化(高速化)するためにプリミティブ型の型クラスはありません。例えば、Haskellに
あるような数値型全般を表す Num という型クラスは、数値型全般を表しますが実体は IntやDoubleなど。
またはtypescriptのtype Tree = Leaf | Nodeはサポートされません rustはどちらかと言えばほとんどをトレイトで表現しますが、技術的にはこれらは、Tagged unionと呼ばれ
昔はSum typeともバリアント型とも呼ばれていました。プリミティブ型ではありませんが、似た機能を実現
する技術はenum variantsでも表現できます。C20にあるstd:variantもTagged unionです
もちろんassociatedでも似たことは出来るでしょう
https://en.wikipedia.org/wiki/Tagged_union >>622-623 の言ってることが何一つわからんのだが >>622
おっしゃる通りですがRustでは別の解決方法を取っていますね
まず前者の全般的なNum型がない件ですが
Rustでは単純な例だと以下のように1を足す関数add1ををジェネリックに書こうとすると
(注釈: 足し算の「+」はstd::ops::Add traitを満たせば使えて任意の型でオーバーロード可)
fn add1<T: std::ops::Add<Output=T>>(n: T) -> T {
n + 1
}
これはコンパイラが通らなくて「1」を型Iにする必要があり「1::<T>」等とでも書ければいいのですが無理です
そこでnum craitのOne traitを使って以下のように書きます
fn add1<T: std::ops::Add<Output=T> + num::One>(n: T) -> T {
n + num::one::<T>()
}
これで以下のようにジェネリックに1を足すことができました
assert_eq!(add1(36), 37);
assert_eq!(add1(5.0), 6.0);
assert_eq!(add1(1000i128), 1001i128);
さらにこの方式ならば自分で定義する構造体など任意の型もAddとOneのtraitを満たせばadd1()を使える利点があります
つまり最初の話に戻ると全般的なNum型があるよりももっと高度なことができるわけです
後者の件は一般的に代数データ型の直和をどう扱うかという話になりますが
Rustではenumがタグ付き共用体でもあるのでenumでサポートできますね >>617
rustは可変参照を基本的に好まないスタイルだから、ああなるのは仕方ないな 他人のフリして自分のレスに返信してるやつなんなのwww >>628
可変参照は関係あるのかな?
どちらもbit処理を下から順にするアルゴリズムで変わりなく
>>613はbitマスクを大きく(左シフト)していく方法
>>617はbitマスクは常に1で本体を小さく(右シフト)していく方法の違いだけだよね
だから後者の方式でもRustでコーディングできて動くよね
両者の差分
fn calc(num: usize, pow: usize, m: usize) -> usize {
- let mut bit: usize = 1;
+ let mut bit: usize = pow;
let mut res: usize = 1;
let mut tmp_pow: usize = num;
- while pow >= bit {
- if pow & bit > 0 {
+ while bit > 0 {
+ if bit & 1 > 0 {
res = (res * tmp_pow) % m;
}
- bit = bit << 1;
+ bit = bit >> 1;
tmp_pow = (tmp_pow * tmp_pow) % m;
}
res
} >>630
アルゴリズムではなくて、ポインタを渡すのか、実数値を渡すのか
そこを明確にしているRustの仕様から引数を可変参照にするのは・・という意味では
そして>>617が何を読みにくいといっているのかも、よくわからんし >>624 >>627
がねがねその通りで、言った通りトレイトだが、「Num型があるよりももっと高度なことができる」これは弁明的。
近代的な言語はmixinもしくはアドホック多相で(高度なことが)出来る場合がほとんどであり、無いものを無いと
要求できず弁護をするのはちょっと違う。他にも角度のように、0-360まで制限したいプリミティブ型が欲しいのに
PascalのようなSubrange型も足りていない。範囲を表す表現、0..360はあるのに。些細な事だが、コンパイラを
速くする事を現在は主眼なので(仕様に矛盾が無ければ)いずれは拡張されるのかもしれないが mutをつけたベクター型について教えてください
これはまず、入っているのは参照なんですか?
また、参照が変わらない(?)のに、参照先を変更するにはmutがなぜ必要になってくるのですか?
(所有権概念のせいなのでしょうか?それともスマートポインタの仕組み上、参照するアドレスが変わるのでしょうか?) >>633
let mut x = vec![1,2,3];
xに入ってるのはVec<i32>、これはスマートポインタ(pointer, capacity, length)。
「参照」というのはRustでは&Vec<i32>のようにアンパサンドがついてる型のこと
なのでxに入ってるのは参照ではない
例えばx.push(10)するのにxがmutじゃなきゃいけないのは
直接的にはpushのシグニチャが&mut selfを要求してるからだけど
考え方としては「multiple readers or single writer」ルールをコンパイル時に強制するため
連続したバッファを確保できなければアドレスが変わる可能性も有るし
ゼロキャパシティなら具体的なアドレスを持ってない Cortex-M対応がClangよりRustの方が進んでいて草 core::ptr::unique::Uniqueもalloc::raw_vecもただのdoc(hidden)なのに
Vecがスマートポインタってデタラメ広めてる奴らどこが出処だよ。
以下の関係で、
Vec has-a RawVec
RawVec has-a Unique
- Vecがrustの作法を強制するためのnewtypeパターン←composition
- RawVecが動的配列の低レベルapi←composition
- Uniqueがユニークポインタ←smart pointer
これだけだろ。
rustのコレクションはデータ構造上直接実装することになる型以外
Box含めて基本newtypeパターン(composition)だぞ。
>>633
GCのある言語しか触ったことない限りその発想にはならんから
まずアロケータの仕組みからやりな。 また他人のフリして間違いを指摘するレスが来るから乞うご期待www compositionだからスマートポインタでないという理屈だと Rc も Arc も非公開な内部型の composition だからスマートポインタでなくなってしまう >>640
The concept of smart pointers isn’t unique to Rust: smart pointers originated in C++ and exist in other languages as well.
とあるけど? We’ve already encountered a few smart pointers in this book, such as String and Vec<T> in Chapter 8, although we didn’t call them smart pointers at the time. Both these types count as smart pointers because they own some memory and allow you to manipulate it. They also have metadata (such as their capacity) and extra capabilities or guarantees (such as with String ensuring its data will always be valid UTF-8).
というわけで Rust の定義では Vec<T> はスマートポインタ クイズ: この中にウソはいくつウソがある?
「またはtypescriptのtype Tree = Leaf | Nodeはサポートされません」
「rustはどちらかと言えばほとんどをトレイトで表現しますが、技術的にはこれらは、Tagged unionと呼ばれ 昔はSum typeともバリアント型とも呼ばれていました。」
「rustは可変参照を基本的に好まないスタイルだから、ああなるのは仕方ないな」
「Vecがスマートポインタってデタラメ広めてる奴らどこが出処だよ。 」 >>633
pub struct Vec<略> {
buf: RawVec<T, A>,
len: usize,
}
pub struct RawVec<略> {
ptr: Unique<T>,
cap: usize,
alloc: A,
}
pub struct Unique<T: ?Sized> {
pointer: *const T,
_marker: PhantomData<T>,
}
push|insertの際にlen|capとアロケート先が変化するという事、上のは難しい事をわざと言ってる
スマートポインタ議論は無視でOK。しかしPhantomDataなんて理解してる人に会ったことない >>631
その冪剰余関数の引数は全て数値すなわちCopy traitを持つので
関数呼び出しに参照を渡す必要はありません
また、可変参照の数値を渡す必要がある別の関数がもしあったとしても
普通に値を渡して変更値は返り値とする方がわかりやすいでしょう >スマートポインタ議論は無視でOK。
他人のフリして我がフリ直せww >>633
初級者ならばこのスレで言及されている内部実装の話は知らずとも使えるので無視してもよい
それよりもmutableとimmutableの意味となぜ区別が必要かを理解したほうがいい
あと参照の意味も理解していないようだからそこもまず基本だからおさえるべき
それら基本を理解すればVecの中身が書き換わるならばmut指定が必要とわかるはず
Rustは簡素に理解しやすく出来ているのに他言語のポインタ周辺の概念を無駄に持ち出してきて難しく考えて失敗する人たちが一部いる Rusterは他人を同一人物と思い込む素性の悪い病人しか居ないな >>647
>Rustは簡素に理解しやすく出来ているのに
それには賛同できない このスレにはアンチRustのC++爺さんと
間違った知識を上から目線でレスするRust初心者が各1名住み着いてるから
質問者は回答内容を自分で精査しないとダメだよ
特に後者はタチが悪いので注意して Rustに近々追加される機能で熱いものなにかありますか? 現時点でRustなんかどうでもいい
10年後に普及してたら一般プログラマーも使う程度 653見る前に654書いちゃったのでちょっと訂正
Rustに関するまじめな質問はteratailでするのがよい
>>653
もうすぐRust2021がくるぞい
熱いのがあるかっていうと微妙かも >>650
mutの必要有無は他言語では一般的じゃないRustのルールに関連してるんだけど
それが少し難しいので回答する側にもそのルールを理解してない人がそれなりにいるということ
基本的にコンパイラが教えてくれるので深く理解してなくても使う分にはそこまで問題にはならない Rustを知るということは、弱点も知ることにつながる vlangもmutがあるが散々否定される、曰く「理論に沿ったコンピューター工学を元にしてない」だとか
「トランスコンパイラでしょ」とか、NoGCが過大広告でLobsterというのは分かるがリークするでしょとか async/awaitの追加で一旦大きな機能追加目標は終わって、以降は処理系の効率化にリソースを割いていく、みたいな話を読んだ気がする 結局他の言語でのメモリモデルも理解してないとrustはまともに使えんよ。
そこを誤魔化すやつはクソだわ。 >>633
Rustは書き換え競合を避けるために、書き換え可能な可変参照(for writer)と、書き換えられない参照(for reader)の区別をして、
書き換えられない参照は同時に複数を持てる(multiple readers)けど、可変参照は同時に一つだけしか許さない(single writer)とすることで、競合を避けている。
Rustではmutかどうかもその観点からなので、変数が別のVecになるだけでなく、同じVecのまま配列内容や長さの変化しても、内容長さ同じだが領域拡大で場所移動でも、書き換わりとしてmutが必要。
だから、Vecのメソッドでmutを要求してるのはそれらの結果論にすぎないし、Vecの内部構造がこうなってるからという説明は不要で筋違い。
>>661
それは違うな。
むしろ頭を一旦ゼロにする柔軟な人ほど理解が早い。
他言語での様々なモデル(メモリモデルやクラスモデルや…)をベースに難しく考える人ほど混乱して理解が遅い。 >むしろ頭を一旦ゼロにする柔軟な人ほど理解が早い。
>他言語での様々なモデル(メモリモデルやクラスモデルや…)をベースに難しく考える人ほど混乱して理解が遅い。
これを本気で考えてるならバカとしか言いようがない。
C、もしくはアセンブラをバインディングした時に確実にぶっ壊れるコードになるわ。 >>663
それはABIやFFIの話であってRustの話ではない。
Rustで完結するシステムでは一切考慮する必要ない。
他言語ライブラリなど利用の際も、適切な仲介モジュールがあれば、利用側で考慮する必要はない。
各言語との連携部分では、それぞれその言語の知識が不可欠なのは当たり前。
だが、それはRustの話ではなく、Rustにおいてはその知識は必要ない。 メモリモデルって並行プログラミングやらないならあんまり関係なくない??? アトミック操作のOrderingの話なんかはC++の定義に丸投げしてるから他の言語の知識が必要というのは一応正しい >>666
それは理解するのにC++の知識を一切必要としない。
なぜならC++言語仕様とは独立して定められている。
つまり、その件についてもRustを理解習得するために他の言語の知識は必要ない。 >>662
「Vecの内部構造がこうなってるからという説明は不要で筋違い」うーん、それこそ趣旨が違うよ。
vec[0] = 2などとして内容長さ同じの場合の理解では、1つの可変参照と、複数の参照を持つ事を
知っているのは必要だが通常では長さや容量が拡張されるpushやinsertは内部構造により説明される。
mutatorであるpushを呼ばない限りはmutは必要なければ、「mutをつけたベクター型」では無くて
配列という質問になるのでは? >>668
公開(pub)されていないstruct Vecの内部構造や非公開のRawVecなどを持ち出してくる人たちがいるから、
「Vecの内部構造がこうなってるからという説明は不要で筋違い」と書いた。
そこは長さや容量を持っている等の概念の理解だけで十分であるし、実際に公表されている情報もそこまで。 >>667
C++の知識を「あまり」必要としないのは確かだがC20/C22などの仕様を「参考」にしているのは明らか。
というかLLVMから見てClangっぽく見えるように頑張っていると公式が言っている >>669
なるほど言いたい事は理解してるが、長さや容量を持っている等の概念の理解ならライブラリソースを
示した方が明らかでしょう。親切だと褒められる事はすれど不要と切って捨てるほどではないのでは? >>664
rustが単独で使われるなんてことは絶対にない。
低レイヤーのことがまるでわかってないってことがよくわかったよ。 >>662
「multiple readers or single writer」のセーフティルールは
参照だけに適用されるものではなくて参照の所有者を含めて適用されるもの >>672
Rustでプログラムを書くに当たってRustを構成する様々な低レベルのレイヤーのうちどこまで書き手は意識すべきと考えますか?
さすがにCPUを構成するシリコンひとつひとつの振る舞いを意識することは出来ないので、
これより先は気にしなくて良いという境界は存在すると思うのですが、それはどのあたりにあるとお考えでしょうか >>672
no_stdでさらにシステムコール(あるいは相当)はasmでレジスタ渡しで呼び出しに至るまでRust完全単独で既存OS(など)利用もあるしOS作成ならOS側もRust単独 >>664
>Rustで完結するシステムでは一切考慮する必要ない。
それって議論の価値ある? だって現実的じゃないじゃん
研究者のための言語だっていうなら、それもありだけど
ここにいる人間は実用を求めてるわけでしょ。多分…… すまんが何を言っているかさっぱり分からない
自分が書いてるのは9割方Rustで完結したプロジェクトだけど、みんなFFIばっかり書いてるのか? Win32APIとリンクしたり、そういうプログラムは書かないってことね Win32API使いたいんなら単にwindows-rsクレート使えば良いだけで
その先のC ABIがどうなってるかとか気にする必要はないと思うが ああでもwindows-rs自体は割とunsafe あるから気にしないとダメかな いや、そもそもwindows-rsクレート使おうが
C理解してないと使えないよ
だってwindows-rsの型定義は「今のところ」まともじゃないもん
ポインタは何でもかんでもDWORDだし 確かに例が悪かった。windows-rsに関してはunsafe がある以上呼び出し先のCの知識は必須だね
言いたいのは自分でunsafeを書かない限り、Rustだけで完結するってこと
そりゃ分野によってはまだライブラリ不足で完結しにくいのもあるだろうけど、多くの分野で完結すると思うがなぁ で、そういうメモリをほとんど気にしないソフトはrustで書く必要がないものなんだよね。
ファッションでやってることがバレちゃったね。 Rust以外のプログラミング言語を考えれば理解しやすい
C言語を全く知らなくても使えるようにその言語だけで書かれたAPIで何でも利用できる
Rustも同様でC言語を全く知らなくても使えるようにRustだけで書かれたAPIで何でも利用できるようにすることができるし実際にほとんどの分野ではそうなっている
その上でRustの場合は効率面から元のAPI向き出しで例えばCStr使ったりするなどC言語でのAPIのまま提供するモジュールも存在するというだけにすぎなくてそこはあくまでもFFI領域
したがって「他の言語と同様にRustもC言語を全く知らなくても使える」で正解 >>683
rustで書く必要性が薄いってのは結構当てはまるとは思うが、
だからといってメモリ回りの知識がrustで何か書くには絶対必須とはならんだろう >>683
例えばstd::fsやstd::netなどは本来ならCのABIでやりとりするものだが
そんなこといっさい気にする必要なくRustの型で渡してRustの型で返ってくるようにRustの標準ライブラリが作られている
そこにCの知識は全く必要としない たくさん書くのは自信がなさの表れ
そんな必死になるような話じゃないだろうに Cを理解してないとRustは使えない、と
ウソをつく人がいるからだろう そう思い込んでりゃいいんでない?
近くにいなけりゃ放置するよ。近くにいればボコボコにするけど。 >>674
cpuはシリコンウエハ一枚から切り取ったものからなっている
複数のシリコンの集合体ではない >>688
そういうやつの相手をムキになってやってるうちは自分も同じレベルだって気付けよな >>690
ちなRyzenとか、組み込みマイコンとかは、マルチチップを繋いで一つにパッケージしてるのもあるけどね。
シリコン一つ一つとかポエムっぽいのは秋になったからか? コンピュータアーキテクチャの基礎知識(メモリモデル、アクセスオーダ、スレッディング等)やOSのシステムコール、APIの知識の事を "C言語の知識" と呼ぶ人が居るのね。
まあどうでもいいけど。 システムコールにしても最終的にはレジスタに積んでsyscall命令もしくは割り込みするだけだからCでもRustでもasmと共存するだけか
C言語の知識は要らないな まあシステムコールやAPIは C や CPP のヘッダ形式で定義/提供されてるという事を言いたいなら判らんでもないが、
そこまでコアな言語仕様知識は要らないねえ。 rustは書けるけどCが書けない人いる?
そういう人がいないとCがいるかいらないかわからない
自分はCの知識が役に立ったと思う RustでWebバックエンド書いてる人になら普通にいるんじゃない?
Web系ならこれまでのキャリアで全くCに触れなくてもおかしくないし 昔からRust for Rubyistsとかあるしスクリプト系言語から流れて来る人もそれなりにいるかと スマートポインタやシェアードポインタ、所有権なんかは、C++0xあたりで導入された考えだから
どの程度の範囲をC言語と言っているのかによる。要らない派が多く「見える」が、知識があって
理解をを妨げるという考えは全否定する。「あって困るものではない」 >>695
OSプログラムしてるとレジスタ内容をメモリに載せるなんて普通にあることなんだが。
まあrustでOSなんて書かないから関係ないですけどね。 >>701
OSなんて書いたこともないくせに語るなド素人 >>702
ソースコード読むことすらしてないバカは黙ってて。 そんなことよりシステムコールの呼び出しにCの知識は必要ないっていうコメント対して>>701のレスが噛み合ってないんだが、何を言いたかったのか解説してくれないか なるほど、レジスタからメモリ書き込みの同期タイミングなどが必要とかそこまで具体的に言わないと理解できないレベルなのか。
すげー馬鹿しかいないのなら仕方ないな。 >>705
それな
> OSプログラムしてるとレジスタ内容をメモリに載せるなんて普通にあることなんだが。
何でいきなり一人だけ見当ハズレなこと言い出したのかだけでも説明してほしいわ >>701
Rustはインラインasmできるので好きなレジスタと好きな変数(メモリ)の行き来演算できるしRustだけでOSも書ける >>711
そりゃアセンブリですから
safeにするには不変条件を満たすように自分でやらなきゃいけない Rust? 人気らしいね、でもオイラやらないよ
Cは嫌いだし、その後釜狙いの言語はどうせ肌に合わないさ
大半の人には必要ない言語だよね、だからオイラGoをやるよ GoのほうがよっぽどCの後釜感あるがな
GCのあるCという感じ >>711
unsafeを誤解しているようだけど
CやC++と同じ状況すなわちその部分のメモリ安全性は自己管理となるだけ
だから論理的に安全な操作でそれがローカルに閉じ込められて他に影響を及ぼさないならば使われうる
例えば標準ライブラリのVecもその内部実装の一部でunsafeが使われているが我々はVecを安全に使うことができる
>>715
つまりGoはCやC++の代替になれない rustの強みである静的メモリ安全性っていうのが活かせてないやんって意味で言ったんやけど
cやc++と同じ状況ならむしろrustよりcやc++使うよね? 量の概念がないやつが定期的に現れるな
コード全域がunaafeなのと局所的なのは全然違うでしょ >>717
例えばVecは実装内部でunsafeを用いているが
Vecはメモリ安全性を保証する
そしてVecを用いたプログラムもRustコンパイラが通ればメモリ安全性が保証される >>719
unsafeなのにメモリ安全性どうやって保証してるの? C++の場合は、vector自身がメモリーの所有権を持ってるので安全性が保障されるんだけど。 >>721
え?何を言ってるの?
Vecに限らずRustの各型を含めた標準ライブラリの内部はもちろんunsafeだらけだけど
論理的に安全な操作のみ、かつ、内部に閉じ込められていて外部に影響を及ぼさないもののみ
だからそれら型を含めた標準ライブラリを我々は安全に使うことができる
そしてそららを用いた我々のプログラムはコンパイラが通ればメモリ安全性を保証される >>723
だからアスペか?
論理的に安全な操作のみ、かつ、内部に閉じ込められていて外部に影響を及ぼさないってことをどうやって保証してるのか聞いてんだけど?
国会の答弁みたいな返答やめろよ
というか外部にメモリ及ぼさないはメモリ安全性が保たれるの必要条件じゃないんだけど 外部にメモリ及ぼさないじゃなくて外部に影響及ぼさないだった >>724
C++はコンパイルが通ってもメモリ安全性は保証されません
Rustはコンパイラが通ればメモリ安全性が保証されます
全く異なります
>>725
論理的にそれらを満たす操作かどうかです
Rustコンパイラが通ればメモリ安全性を保証するかどうかも論理的に基づいて保証されます >>727
メモリ安全性を保証することを諦めればコンパイル通るのは当然だよね?
こんな基本的なこともわからないんですか? Cしか知らない人ってプログラミング言語の仕様とコンピュータのアーキテクチャが区別できないってマ?
型理論も知らないってマ? >>728
その通りでC++はコンパイルが通ってもメモリ安全性が保証されない言語
一方でRustはコンパイルが通ればメモリ安全性が保証される言語 >>730
>unsafeを誤解しているようだけど
>CやC++と同じ状況すなわちその部分の>メモリ安全性は自己管理となるだけ
って自分で言ってるよね?自分の過去の発言と言ってること矛盾してない?
rustのunsafeはメモリ安全性を保証することを諦めてるって言いたかったようだけど今は言ってること無茶苦茶じゃない? >>722
これが一般的なC++erの認識だとしたら恐ろしいな unsafeなコードが周りを滅茶滅茶にしない保証は無いよ unsafeを使った場合の安全性の保証を機械的にやりたければ↓みたいなので契約プログラミングする手はあるね
https://crates.io/crates/contracts >>731
もちろんRustの標準ライブラリの実装内部には多数の細かい小さなunsafeがあってその部分はコンパイラによるメモリ安全性保証の範囲外
それそれの内部ローカルのunsafe使用が論理的にメモリ安全であるか否かの保証はコンパイラではなく人間が行ないunsafeはそのためにある
その上でRustコンパイラはプログラム全体のメモリ安全性を保証する 話は簡単だ
C/C++はプログラム全てがRustのunsafe状態
つまりC/C++はプログラム全てを人間がメモリ安全であると保証しなければならないが人間なので複雑化するとミスも生じる
GAFAM各社はメモリ安全に関するバグが全く減らずセキュリティ脆弱性の多くがこの問題に起因することに気付いた
そこでコンパイラがメモリ安全であると保証するRustを採用して少しずつC/C++から移行させていってる段階 unsafe blockはマーが全力で頑張ります!ゾーンだからな
アルゴリズムにおいてあるアルゴリズムが正当であると判定するアルゴリズムは存在しないんだからラストコンパライでも完全なセーフティは保証は出来ないけどな
ただ完全ではないものの他の注意すべき所をランコンに任せてunsafe部にヒューマンリソース限定出来るのはc++を遥かに優れた点よね(´・ω・`) 布教しようとしなくたっていいんだよ
めんどくせえから >>737
GAFAがその体たらくとは信じがたいけど、resource管理は所有権ベースでほぼ解決するし、逆に所有権以外で解決することは出来ないと思う。 >>738
チューリングマシンの停止性問題のこと言ってるんだろうけど違うよ
あるアルゴリズムじゃなくて任意のね
「あるプログラムが正当であると判定するプログラムは存在しない」じゃなくて「任意のプログラムを正当であると判定するプログラムは存在しない」が正しい
これが5chクオリティか Rustコンパイラによるメモリ安全性の保証は信頼してても、unsafe使ってる標準ライブラリを信頼しない話おもしろいね。
実際に問題なく動いてるんだから仕様を信頼すればいいのに。 >>742
人間が局所的に注力すれば済むのがRust
人間がプログラム全般に注力しなければならず破綻したのがCとC++ >>741
うーんまぁ日本語で論理学考える事なんてあんましないから間違えてるのかもしれんが
あるアルゴリズム、ある整数等々で俺はある集合(=アルゴリズム全体で構成される集合)の元の任意性を表してんたんだけどな(´・ω・`) >>743
勝手に破綻したことにするのやめな?
そういうとこやぞお前マジ >>744
その言い訳は厳しいよ
まあワイもまともに勉強するまでもそこあたりあやふやだったしそんな気にすんなや >>740
C/C++に限界を感じたGAFAMたち大手IT企業がRustに結集
特定の言語がIT業界を挙げて支持されるのは初めて
プログラミング言語「Rust」のための「Rust Foundation」設立 -- AWS(Amazon)、Microsoft、Google、Mozilla、Huaweiが創設
https://japan.zdnet.com/article/35166267/
Facebookが「Rust Foundation」に参加
https://japan.zdnet.com/article/35170192/ C++はこれで鼻から悪魔出るから
vector<int> hoge {0};
int& fuga = hoge[0];
for (size_t i = 0; i < 5; ++i) {
hoge.push_back(i);
}
cout << fuga;
}
nsafeがどうたらぬ気にしてRustはこういうのが防げるってだけでもそれなりの価値はある
ちなみにunsafeブロックは本当に慎重に作らないと、unsafeの外部をちょっといじっただけで鼻から悪魔が出たりする
https://doc.rust-jp.rs/rust-nomicon-ja/working-with-unsafe.html
unsafeブロック外のidx < arr.len()をidx <= arr.len()にしただけで死ぬ unsafeなコードが1行でもあったらRustで書く意味ないと主張する人が定期的に現れるのはなぜなのか >>750
C++が劣ることを認めたくない人が「unsafeがあるならC++と同じだからRustの存在意義はない。」という間違った主張をしてるみたい C++との対決は別の専用スレがあるのでそっち使ってくださいね Vec型の質問に高卒が答える
↓
当然の如く高卒がバカにされる
↓
高卒発狂
↓
パソコンがどうの、C++がどうの、いつもの大先生問答に発展 >>749
ちなみになんでこれで悪魔がでるんですか?
無学ですみません >>755
fugaがhogeのメモリ参照を取った後にhoge.push_back()でデータを追加している。
データ追加ではhogeの内部で確保していたメモリ領域が足りなくなると
新しいアドレスに確保しなおす(元の領域は開放する)ので、
fugaが指しているアドレスはアクセスしてはいけない領域になってる。(ダングリングポインタ)
その状態でcoutでfugaを使ってるから。 >>756
なるほど
ダングリングポインタになっているんですね
教えてくださってありがとうございます unsafeなtraitとそうでない通常のtraitってどう違うんでしょうか
implにunsafeって書かないといけない点以外で バカは実際にバグが起きるかどうかを考えてなくて
バグを誰かのせいにできるかどうかしか考えてないんだろ。
だからこんなしょーもないものが持て囃されるってわけだ。 東アジア圏は原因の究明と再発防止より責任の追及と処罰を優先する文化だからな
気をつければ問題ないみたいな精神論が平気で唱えられるのも同様
システム工学先進国のアメリカあたりと比べたらかなり後れている それは東アジア人の性質ってか東朝鮮の性質だろ(´・ω・`) CargoでC/C++のコードをビルドするときにヘッダファイル等の依存関係って何処まで面倒を見てくれるんだろ?
自分で全部記述しないとダメなのか、自動的に追跡してくれるのか・・・
ググってもCのコードも一緒にビルドできます以上の情報が見つからん 面倒見るわけねーじゃん。
ヘッダーファイル依存をまともに解決しようと思うと、ビルド速度に影響がモロに出る。
解決するには暗黙のキャッシュ使うことになって問題が起きやすくなる。 >>762
一番基本的なやり方だとcc crate使うことになると思うけど
このやり方だとヘッダやライブラリは自分で指定する必要ある
使ったことないけどpkg_config crateとか使えば多少は楽になるのかもしれない
C/C++コードが別プロジェクトからの流用ならそのプロジェクトのビルドツールに乗っかるのが楽かも
例えば cmake や autocfg/autotools といった crate はあるみたい >>749
vectorじゃなくて、listを使うと大丈夫。
C言語は、もともと、linked list が代名詞の様な言語。
それを引き継いだC++もstd::listこそが主役。
ところが、stroustrupがvectorを推奨するから混乱してる。 >>765
それは初耳。誰が linked list が C の代名詞と言っているの?
経験上は配列使うことの方が多いように思うんだが >>765
std::listはn番目アクセス遅いよ
だからstd::vectorを利用するケースが圧倒的に多い listそんな使うことないやろ。挿入と削除が早いだけやんけ。何が言いたかったんだか。 確かにlistはあまり使った記憶がないなー
キャッシュのミスヒットを考えると、
vectorでリロケートした方が速い場合もあるし listは敵キャラの弾幕なんかの座標管理なんかに使える (Cで書かれてるLinuxカーネルのフォークなんだから当たり前やろ) そもそも全部書き直すならLinuxを冠する意味が・・・ 何で?
(全部書き直すなど誰も言ってないけど理由を聞いてみたい) うん、それ、RustでLinuxを作り直してるんじゃなくて、元々のLinuxをベースにして、新しい機能をRustで開発しようとしているプロジェクトでしょ 彡 ⌒ ミ
(´・ω・`) 頭が不自由という言葉が引っかかったので飛んできました 彡 ⌒ ミ
(´・ω・`) 飛ぶとかカッパの風上にも置けんな、泳げや C++erはほんとゴシップ談義が好きやな
Rustスレにまでそのカルチャー持ち込まんで欲しいわ どっちでもいいけど、インターフェースは統一して欲しいな。
今のところtokioか優勢みたいね。 std::sync::mpsc ってなんで send がノンブロッキングなんだろうなぁ。 ブロッキングなSenderがほしいならchannel_sync使うんだべさ ブロッキングとかノンブロッキングとか何度か解説読んだ気がするけど意味がわからないわ おまいら mut のことを何て呼んでる?
俺は心の中でムットと呼んでいる インテジャーはイント
キャラクターはチャー
なんだから、ムットでも何でも好きに呼べばよろし
ちなみに俺は心の中でムトゥと踊る^H^H呼んでる そんなくだらない疑問より誰か>>758に答えてくれませんでしょうか >>802
implにunsafeって書かないといけないのと同じことだけど
implを書くやつが要求されてるsafetyルールを担保しないといけない
そのためのマーカー >>791
sync_channelってのがあるのか。ありがと。
ちゃんとランデブーもできるって書いてあるな。 let x = f64::cos(3.14);
みたいなのをf64::を省略して書きたいのですがどうすればよいですか?
use f64::cos; みたいなことはダメなようです 1回はf64と言わないと伝わらないので
let p = 3.14_f64;
let x = p.cos(); すみません、p.cos()の記法がなんかイヤでcos(p)みたいな記法をしたいってことでした modなら確かにuseで省略できるけど
Box::newのBox::を省略したいみたいな話だしなあ fn cos(x: f64) -> f64 {
f64::cos(x)
}
cos(3.14)
素直にp.cos()のほうがいいとは思う let cos = f64::cos;
ならいける
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=3c7b96b61723e46d132c9e0f2d46911b fn main() {
println!("{}", cos(&32));
println!("{}", cos(&4.5))
}
trait GetDouble {
fn get_double(&self) -> f64;
}
fn cos(num: &dyn GetDouble) -> f64 {
f64::cos(num.get_double())
}
impl GetDouble for f64 {
fn get_double(&self) -> f64 {
*self
}
}
impl GetDouble for i32 {
fn get_double(&self) -> f64 {
f64::from(*self)
}
}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=cb0e5606622069ca33b0ef0971fa94b4
これでいこう ジェネリックにしたいならIntoでいいんじゃないかな
fn cos(x: impl Into<f64>) -> f64 {
f64::cos(x.into())
} 文法でrustとc++/cが似ているって言うやつは何をもって似ていると言っているだろう
ムーブセマンティクスがデフォだし、classはない、for文はイテレータだし、変数と関数の宣言の違いがはっきりしているし
何よりも型は前置じゃないし C++とスクリプト言語ぐらいしか知らないんじゃないの? >>817
誰がもなにもオフィシャルなドキュメントでC++に似せたと言っている
型引数が<>だったりブロックが{}だったりそういうレベルで似てると言っている C/C++というよりC familyに似せたと言っていたからちょっとニュアンスは違ってくるか >>819
ソースをくれ
公式で構文を似せたとか言っていないと思うが
C++: references, RAII, smart pointers, move semantics, monomorphization, memory model
https://doc.rust-lang.org/reference/influences.html 型名がintならc++ぽいというのはなんか違うんだよね
->とか<<<とか気持ち悪いことをし始めたらc++感が出てくる >>821
http://web.archive.org/web/20150401014855/http://doc.rust-lang.org/nightly/intro.html
> you may find the syntax easier if you've used a "curly brace" programming language before, like C or JavaScript
確かに似せたとまでは言ってなかった
generics の angle bracket についてはコアメンバーが言及してるしC++の影響受けてると言って良いと思う
https://old.reddit.com/r/rust/comments/6l9mpe/minor_rant_i_wish_rust_had_gone_with_square/ C++ iostream の << 演算子をパクらなかったのは、やっぱりあれが失敗作だからだよね >>823
thx、ソースまで探してくれてありがとう
個人的にはC++を感じるというエモーション(?)がどこなのかを聞きたかった よくある質問
RustはLLVMの上に構築されており、LLVMから見てClangっぽく見えるように頑張っているので、LLVMの
性能が向上したらRustの性能向上にもつながります。
https://prev.rust-lang.org/ja-JP/faq.html 見た目はC++に似ているかも知れないけどML系列の方が近いんじゃない?
コンパイラがうるさいところとか「コンパイルが通れば大体動く」という感触はHaskellに近い
Vecに限定したくないなあとか関数に分けると型表記が面倒だなあとかはHaskellには無かったけど move semanticsとかcall by ref(not call by val in terms of ptr)とかは他のスクリプトではないの多いしな(rakuぐらいじゃね?)
糞みたいに面倒なbig fiveとか書いて来てるc++ちゃんと理解してる連中はrustの基本部分の理解はかなり早そう
記法は全然似てないてかerror handlerの部分とか全くの別物になってるしな
比較的若いgoとかktとかの方が書いててなんとなく似てる様な気もする(´・ω・`) もう長いことC++書いてないけど、考えれば考えるほどC++つらいわ。昔の自分はよく書いてたな 本当はMLが好きな人がMozillaでC++書かされるのに疲れた結果生まれた言語なのでMLやC++の要素を併せ持つのは必然 >>828
GoやKotlinに似てたらc系列ぐらいの雑さでしょ ChromeよりMozillaの方が性能良いことが、Rustを使うべきである証明になってるのでは? Chrome も Rust 使おうみたいな話なかったっけ セルフホストされるまではOCamlで書かれてたので、Chromeより性能の良いMozillaを作ったRustを最初に実装したOCamlを使うべき証明になってるのでは? chromeユーザーだけどfirefoxの方が性能いいってマジなんか? https://amethyst.rs/posts/amethyst--starting-fresh
アメジストが死んだ... エンダァァァァァァァァァァァァァイヤァァァァァァ
rustのゲームエンジンはbevy一強になるのか ちゃんとリリースまでたどり着いたrustのゲームってあるの? >>838
icedじゃだめなん?
>>839
今のところない
試作を含むならネット上に転がっているよ
bevyね...レンダラーがwgpuだからね
現状はレイトレーシングとか無理
ゲームエンジンに挑戦するいい機会かも >>824
C++はシフト演算子をなぜ入出力に使いまわそうとしたのか未だに理解できない
見にくく&わかりにくくなってる >>841
shellのリダイレクトに似てると思ったからだろ >>841
当時の C++ には可変長引数を現代的な型システムの枠組みで扱う方法がなかった。
(C++11 からは variadic template がある。 これも今となっては現代的と言えるかどうか……。)
新しいオブジェクトを追加したときにオーバーロードが可能である必要など
の諸々の事情が積み重なって演算子オーバーロードの仕組みを使うのが妥当という結論になり、
オーバーロード可能な演算子の中で比較的それらしく見えるのが << だったという経緯。
記法だけなら printf で不満は出なかっただろうけど、
printf (というか C の可変長引数の仕組み) は型システム的な保護が全然できないぶっ壊れなので
それを是とすることも出来なかった。 (廃止もしなかったけど。)
良くはないが他にどうにも出来なかったんだよ。 歴史が長くなるとしょうもない事情の積み重ねでグダグダになるのもよくあること。
Rust もいずれはそうなる。 そしてそのときは新しい何かで置き換えられるんだよ。
でも Rust の場合は Edition という区切りで新しい Rust 自身で置き換えつつ
過去の Rust とも共存することを最初から意図したデザインにしているので
比較的長く維持されるんじゃないかな。 実際、型安全であるiostreamよりprintfのがよっぽどマシって議論はある。
しょーもない技術要素よりも視認性のがよっぽど大事だったりするわけで。 >>827
>「コンパイルが通れば大体動く」という感触はHaskellに近い
C/C++でも「コンパイルが通れば大体動く」けど
Haskellはコンパイル時にアルゴリズムミスまでチェックしてくれるのか? 単にHaskellはC/C++よりも型安全性の度合いが強いってこと言いたいんだろ Rustでゲームエンジン作ったら億万長者になれるのかな UnityやUnreal Engine並のを作れるならできるんじゃね
さもなきゃプロプライエタリなエンジンなんてきょうび流行らん Rustの方が圧倒的に高速なら儲かるんじゃね?
知らんけど もうインディー2Dゲームぐらいはリリースされてるのかと思ったけど
まだなのか >>851
億万の金とリソースをかけなきゃ使い物になるエンジンなんて作れないんじゃないの?
まあ、そこまでいかなくともユーザーのいる既存のツールで開発止まっているもの(MMDとか)のクローン作ればワンチャンあるかもね。 ゲームエンジンでボトルネックとなるような重い処理ってなんなの
描画関連が重いならGPU側処理がメインでCPUで動くプログラムは何で書いても良いのでは 行列計算とメモリー帯域、PS5とPCを比べれば一目瞭然。PC4-25600でさえメモリー帯域が25GB/sで
デュアルチャネルで50GB/s、PS5は帯域幅218GB/s、
つまり描画が重いのではなく、CPUやGPUで行列計算した結果をメモリーへ格納したり再び取り出したりが重い。
描画だけなら4K再生できるVRAMの速度だけで終わる話 >>851
儲かるかは知らんがbevy engineの作者はお賽銭で40万/月貰っているぞ ゲーム1本も出てないってそれなんかデカイ問題あるんじゃないの。
使ってみたら、あれこれ全然意味ないわ的な。 そらまあUnityとかみたいなガチゲームエンジンとかと比べたら意味ないんじゃね ゲームとか組み込みと並んで過去の資産が積み上がっているところだろう
現状グラフィックAPIなどのバックエンドは全部C/C++だぞ
一朝一夕の話ではないが、取り組み続ける必要がある
とりあえずコールオブデューティのTreyarchは触っているぽい インディ→ue4かunity
大手→ゲームの開発スパン3-4年+ゲームエンジン開発期間
今から積極的取り組んでも公表できる成果ができるは8-10年じゃない
そういえば任天堂もrust人材を募集してたよ カスタムアロケータ回りがしょぼいからガチのゲームエンジン用としては現状まだきついのでは たしかにコンシューマゲーム会社なんかがRust採用を進めていく、ってのはなんかありそうだね
プロダクトのプロトタイプ作成とかめっちゃあると思うんだけど、そういうのとかで、どんどん試してみて欲しい
彼らがRustコミュニティに貢献してくれるのか、っていうとなんか怪しい気はするけど 最近はマイコンもセキュリティ機能が重要視されているけど
処理系は相変わらずC/C++でRustを推進みたいな流れにはなっていない矛盾 そもそも組み込みで使えるrustコンパイラがないからな 限定的ながらCortex-M用のバックエンドがあるじゃん LLVMバックエンドがあるならなんとかできるのでは
ないなら知らん >>870
RL78に乗り換えてどうぞ。LLVMバックエンドもあるよ 僕はRX-78-2からRX-78NT-1に乗り換えたよ
みんなもそうしなよ 真面目な話Green Hillsが対応したら組み込みでも大分状況変わると思うんだが
なんか内部では研究してるみたいだし ルネサスは近年arm32bitとしてraファミリ出してる。h8とかsuperhな人は今すぐ乗り換えろ バックエンドがある組み込み向けISAはCortex-M系、RISC-V系、RL78、AVR8あたり?
>>876
RAで済むなら他社のCortex-M系マイコンでも良いんじゃね感が・・・ アロケータ自作は大げさじゃないか
heaplessクレートでどうにかなるんじゃないかな
オレは使ったことないけど Unityでいけるくらいならデフォルトのアロケータで十分では?
jemallocとかに切り替えてもいいけど、どちらにしても自作するほどかね Unity使うなら内部のGCはBoehm GCなんだからGC_MALLOC使ったほうが良いのでは?
オレはRc<T>使いながらBoehmが使えるのか知らんけど 別にゲームにカスタムアロケータが必須なんてことはないと思うが
UnityみたいにGCありの言語で書く場合にGCのスパイクが許容できないから
独自のメモリプールとかを書かざるを得ないのでは
それともC++でもアロケータ自作してるのか? UnityってBoehm GCなんだ?
それで十分動くんならRustにもGCあってもよかったんじゃない? goはboehmじゃなく2017年ごろまでtcmallocで今は派生(随分、中身が違う)してるはず 412 名前: 以下、名無しにかわりましてVIPがお送りします 投稿日: 2013/01/19(土) 21:03:25.42 ID:a2pD/tlo0
FランのFはフェニックスのFや!
例えこんなところで落ちぶれても不死鳥のごとく上流階級に返り咲くんや!!
414 名前: 以下、名無しにかわりましてVIPがお送りします 投稿日: 2013/01/19(土) 21:04:02.87 ID:dT9mn0sK0
>>412
フェニックスは「phoenix」 >>887
スレチだが、Boehmなので本来はSTWだけなのでUnityにGCラグが発生していたことは有名ですが、2018/12頃に
インクリメンタルGCが出来て改善された。
https://blog.unity.com/technology/feature-preview-incremental-garbage-collection
またUnityでゲームなどを作るときに良くやるのがGCを動かさないこと(=オブジェクトを破棄しない)で
オブジェクトプールを使用して1度作ったオブジェクトをプールして置き破棄させない方法など、Unityにある
文字列比較などを使用しないなど細かい事をやる。本末転倒といえばその通り 典型的なバッドノウハウだな
とはいえ日本でUnityが一番つかわれているであろう現場のモバイルゲーム開発は
昔はケータイJavaのゲーム開発やってた場合が多いのでその辺のGCバッドノウハウに慣れちゃってるという
Boehmはボエーンて読んでるわ oe はドイツ語の o の代替綴りとしてあてられることが多い。
つまり boehm の本来の綴りは bohm ってことね。
o はオの口の音でエという感じなので音としては中途半端で、カタカナに当てはめにくい。
ドイツ語の発音通りをあえてカタカナにするならボェーンに聞こえるんだけど、
bohm という人名は通例ではベームと表記してるね。 あれ? 2ch に投稿したらウムラウトが消えてる……。 appleをアップルと記載するような文化やからね。カタカナにしてしまったら本来の発音との差異なんて気にしたらキリがない 名女優のオードリー・ヘップバーンと
ローマ字表記のヘボン式で有名なヘボン氏が実は同じ綴り同じ発音の同じ姓みたいなもんか まじかあ、これが可能だったのかあ
let v = vec![1, 2, 3];
println!("{}", v[if true { 1 } else { 2 }]); >>901
ヘボンさんは自分でも気に入って「平文」なんてハンコ
持ってたくらいだから定着しちゃったんだよなw 音韻と音声は異なる。 ある言語で同じ音だと認められる音が音韻で、
たとえば日本語だとシンブンシという言葉に表れる二個のンは実際には違う音
なのに同じ音として処理している。
(だからヘボン式ローマ字では書き分けるルールになっている。)
音韻として同じでも音声として幅はあり、そして音韻は言語に依存するもんだから、
外国語の音を転写してくるとどう頑張ったって辻褄の合わない部分は出てくる。 いつの間にか[T; N]にIntoIteratorがimplされてるな
しかも興味深いことにVec等と異なり消費されないようだ
借用ルール的にはどういう扱い? >>907
Rust 1.53.0で配列にIntoIteratorが実装された
あと識別子に日本語も使えるようになった
配列は要素がCopyを実装しているかどうかで所有権の扱いが変わる
#[derive(Debug,Clone,Copy)]
struct 構造体 {
値: isize,
}
fn main() {
let 配列 = [構造体{値:1}, 構造体{値:2}, 構造体{値:3}];
for 変数 in 配列 {
println!("{:?}", 変数);
}
println!("{:?}", 配列[0]);
}
例えばこれはコンパイルが通って動くけど
構造体のderiveのCopyを外すと
配列の所有権はfor in内部のinto_iter()で移動してしまいコンパイルが通らなくなる >>911
ぶっちゃけ日本語の識別子わかりやすいって思ってしまった 日本語識別子わかりやすいんだけど入力に手間がかかるのがつらい let v0 = vec![1, 2, 3];
let mut v1 = v0;
v1.push(120);
let mut v0 = vec![1, 2, 3];
let v1 = &mut v0;
v1.push(120);
所有権関連で試してみてるんだけど、この二つの違いってなんなん?
いまいちよくわからん
上のはmutでないvecをlet mutの変数に入れるとpushできてまうし
下のはlet mutでない変数なのに&mutでいれるとpushできてまう >>914
それぞれpushした後にv0とv1がどうなってるか確認してみるとわかる すまんがVSCode + Rust-Analyzerで勉強中なんだけどさ
数ヶ月前は変数の型が表示されていたのに、今じゃ全然表示されなくなっちゃったんだけど・・・・どうすればいいんだぜ? int * constみたいなもん
参照先のアドレスは変更不可だけどそのアドレスが指してるvectorは&mutだから変更可能 >>914
他の言語での余計な知識を捨て去ってゼロから考えるとわかりやすかったよ
今回の件で関係するルールは単純でこれだけかな?
【所有権】
・所有権を持てるのは一人だけ
・使う(=代入や関数引数も含まれる)と所有権は移動する
・ただしCopyトレイト実装型は使う時にCopyされるので所有権は移動しない
【所有権を持つ可変と非可変】
・その変数の中身を書き換える予定があるなら変数を可変(mut)に宣言しておく
・他の変数に代入しなおせば可変か非可変か変更可能(つまりその変数を使う時の制限ヒント)
【参照(=貸出=借用)】
・所有権が移動されたくなければ参照で貸し出す
・可変参照(&mut)の貸し出しは1人のみに参照独占で元も可変変数であること
・非可変参照(&)の貸し出しは同時に何人でも可能
・まとめるとsingle writer or multi readers
所有権を明確にするのはメモリ自動解放のため
可変を明確にするのは並行(concurrent)/並列(parallel)での競合回避のため 所有権を伸ばして発音すると昇龍拳みたいに聞こえる
出掛かりが無敵なところも似てる 丁寧で優しい920を弄りたくないけど、これを読める人は914のような質問はしないね 以下の関数をジェネリックにする方法ありますか?
fn is_one_two_three<A: AsRef<[isize]>>(a: A) {
assert_eq!(&[1, 2, 3], a.as_ref());
}
fn main() {
let a = [1, 2, 3];
is_one_two_three(a);
let a = vec![1, 2, 3];
is_one_two_three(a);
}
配列もVecも受け取る関数でこれはコンパイルも通り動いているのですが
isizeと型が決め打ちのところをジェネリックにTとしたいです
どうするとよいでしょうか? >>925
数値型を一般化する trait を使うのが普通かな。
自分で定義しても良いが num_traits::FromPrimitive を使うならこんな感じ
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=1fbd536dd6c9ea76beb20a666b085190 >>914
気持ちの上では他の言語と対応付けるのではなく Rust のルールで理解すべきという点で >>920 に
同意ではあるんだが、そうは言っても知っていると引っ張られるのも仕方のない話で、
入門初期では多少はしょうがないとも思う。
あえて C++ で同等のものに置き換えるとするとこんな感じかな。
#include <vector>
int main(void) {
{
const std::vector<int> v0 = {1, 2, 3};
std::vector<int> v1 = v0;
v1.push_back(120);
}
{
std::vector<int> v0 = {1, 2, 3};
std::vector<int>* const v1 = &v0;
v1->push_back(120);
}
}
この場合は所有権の概念はあまり関係なくて
メソッド呼出しの演算子が参照を自動で調整してしまうのも混乱の原因になってる気がする。
mut が何にかかっているのか見えにくい。 >>927
少なくとも上は全く同等じゃない
C++では表現出来ない >>928
ムーブの仕組みが違うのはしょうがない。
この場合は const 性の話だと思ったから…… C++で考えるのは弊害しかないじゃん
何がしょうがないだよ 弊害しかないは言いすぎ
この場合mutをどこに付けると何が可変になるかの話だから
C++でconstをどこに付けると何が不変になるのかを例に出すのは自然なたとえだと思いますよ let mut vec0 = vec![vec![0, 2, 3]; 3];
for mut i in vec0.iter_mut() {
i.push(9);
}
for mut i in &mut vec0 {
i.push(9);
}
この二つのループの意味は同じ?
こういう二つの書き方があるのでちょっとわかりにくい気がする へー、これが通るんだ
ちょっと笑った
let vec0 = vec![0, 2, 3];
let mut vec0 = vec0;
vec0.push(99); シャドーイングOKな言語でもlintが禁止してきてイラっとする >>934
状態まで置き換え可能なのはおかしいような気がする
せっかく不変変数にしてるのに事実上代入可能にしてることに何の意味があるんだろう >>924
「関係するルールは単純でこれだけ」と言って関係ないものも含めて8個もルールを羅列するやつが丁寧で優しいわけがないよ >>937
変数名の再利用と状態変更はちがくね?
そもそも変更しないと宣言して変数をシャドーイングして変更可能にするのも疑問だけど、
まあそれは仕様だとして、それが変数名の再利用とは無関係じゃんね 再利用しない前提なんだから >>936
状態置き換えてない
新しい方の変数を参照するようにしているだけ >>932
> for mut i in vec0.iter_mut() {
> for mut i in &mut vec0 {
どちらもiは&mutになるので同じfor文になる
そしてlet mut i = &mut ... と書いている時と同じく左側のmutは不要(warning) >>925
配列もVecも受け取る関数ならば
as_ref()でスライスに揃える方法だけでなく
配列もVecもそのままの型で使う方法もあり
どちらもa[i]の形はIndexトレイトで使えるので例えば
fn get_second_item<A: std::ops::Index<usize, Output=T>, T: Copy>(a: A) -> T {
a[1]
}
fn main() {
let a = [1.1, 2.2, 3.3];
assert_eq!(2.2, get_second_item(a));
let a = vec!["a", "b", "c"];
assert_eq!("b", get_second_item(a));
}
と配列/Vec側も中身のf64/&str側もジェネリックに書ける 背後にある考え方を説明せずにルールだけ教えても理解できないよ。
まあ、ルールに一貫したコンセプトがないんだったら「こういうものだ」と押し付けるしかないけど。 可変の場合は面倒でもmutが必要ってしたほうがわかりやすいような気がするなあ let mut p = &mut q; の左辺mutを書くとwarningが出る理由は、pはmutではなく、あくまでも&mutであるためだろう。
つまり、そこに左辺mutを書いてしまう人はきちんと理解していないという意味ではなかろうか。 let mut ~~はそこで定義される変数が可変(再代入可能)になるもので、
&mut ~~はそこで作成される参照が可変になる、という理解なんだけど、
どうもしっくり来てない。引数の宣言で&mutとつけるとどうなるの、とかすぐ出てこない。 let mutのmutはコード生成には不要だけど&mutのmutは必要だと言う話を聞いた let mutのmutはbindingがmutableかどうか
&mutは型が&mut Tなのかどうか
Cのconst pointerとpointer to constと同じ
Rustはデフォルトimmutableなのでmutableにしたい場合にのみmutで修飾
普通使わないけどパターンマッチと組み合わせると
let &mut mut x = &mut y;
みたいな書き方もありうる mutが必要ってより、for mutにfor let mutにならないことが不思議 それは単にforの文法がlet不要なように設計されたってだけでは let パターン = ...
for パターン in iter
match パターン ...
fn hoge(パターン: TypeName, ...)
ってことやぞ Rustにはif let Some(3) = v {}とか、 while let Some(i) = a {}とかあり。letは不変のキーワードじゃなく
右辺に対するパターンマッチ展開で、for letがないのは、forはfor..inしかなく、Cのようなfor ;条件;の文が
存在しないためという考えらしいです。。。 forで変数の初期化が要るみたいな発想になる時点でC由来の処理系に洗脳されているんじゃぁ・・・ for p in v { … } は
v.into_iter().for_each(|p| …) と同じ機能たけど
長いメソッドチェーンな時など敢えてforでなくfor_each使ったりも ただしfor文は値を返せないのが弱点かな
イテレータならfor_eachの代わりにfoldしたりfindしたりあるいはmapやfilterなど色々処理して最後にcollectしたりと値を返せる >>958
forやwhileは、そもそもループが実行されないパターンがあるので、それは無理ってなったらしい
だからloopでは値を返すことができるので、loopを使うぺし >>959
for式やwhile式がOptionを返してループ0回ならNoneで済む話ではないのでしょうか? forで値を返したいとか言ってるやつまだいたのかw >>960
ループ内は実行されないからNoneも返せないってことよ
loopは明示的に自分でbreakするから許容
let test: = if true { 1 };
たとえば、これでtestにNoneが入るとかおかしいことになるってわかるっしょ?
それと同じこと。 ごめん誤爆した。
実際問題として必要な場面がないだろ。 rust現場で使ってる人は何系のシステム作ってるん? 求人検索をしてみても、Rust使ってるとこなんて指で数えられるぐらいしかなさそうかな 試験的にGoからRustに切り替え中だよ。両方ともバックエンドとフロントエンドまでやってるのでそのまま移植出来て簡単…じゃなかった
インフラはサクッと終わったけど、フロントは素のWasmで実装するもGoより遥かに複雑で難解なRustでやる意味は?的な事になって
vDOM系フレームワークで実装するも、Non-vDOM系のが殆どの場面で速い事が分かったのでやり直し中
で、本番環境で運用できるのか?となると最初の印象に反して「出来る」と思うね。
動かし始めて不具合が出た時に、何処がヤバいのか分からない怖さがない。
過去の資産と経験則は捨ててRustのお作法に従うようにするのが大切、下手にアレを使いたいので使い回すとかやると余計苦労する。 >>970
もしよろしければオススメのRustフレームワークを教えてください うちではバイトの女子大生も使ってるが
Rustを使うような企業はネット求人になんか頼らんだろうね、今のところ Dominatorってこれか
https://github.com/Pauan/rust-dominator
virtual DOM使わずゼロコストでリアクティブか
ベンチマーク見るとVue/React/Angularなどは非常に遅いんだな
https://rawgit.com/krausest/js-framework-benchmark/master/webdriver-ts-results/table.html
Vanilla JSで頑張るのでなければRustでDominatorを使った方が良さそうってことか
ウェブフロントエンドまでRustの時代が来るとは驚き おもしろそうだけど、メンテが辛くなりそう。仕事でそんなん大丈夫かしら? ダメに決まってんじゃん。。無理やり使おうとしてるのが丸わかりだわ。 >>975
少くともその表に載ってるsolidってのは非vDOM系のJSフレームワークだけど…
その表ではDominatorとどっちが速いですか?
そしてそれはなぜですか?
それを勘案しても、
Vanilla JSで頑張るのでなければRustでDominatorを使った方が良さそうってなりますか? フロントエンドのwasmでrustを使う意味が分からん、assemblyscriptなんかでts変換したほうがよっぽど
人材確保も容易で速度も出そうだけど、まあ全部1つの言語に統一したいという欲望は分かるが その種の願望はいつだって失敗してるのに何回でもこだわるバカが出てくる。
ビジュアルプログラミングとかノーコード並みに愚かだわ。 htmlマクロが微妙だよな。yewもしかり
マクロの仕様理解して書かないといけないからwebpackみたいなコンパイラー挟んでreact,vueみたいなhtmlベースでかけたら普及進むと思う フロントエンドはElmで書いた方がいいと思う
Elmの設計をパクったRust用フレームワークよりElmそのもので書いた方がいい >>979
WasmはもともとC/C++をブラウザのフロントエンドで使いたい願望から
始まったものだ。
意外に思うかもしれないが、C/C++を使いたい人はRustの1000倍くらい多い。 >>979
AssemblyScriptはメモリ管理GC問題があるし文法が単にTSの限定サブセットに過ぎないため色々と辛すぎる
そのためWebAssemblyでの使用言語調査結果もこんな状況でRustが圧勝
https://blog.scottlogic.com/ceberhardt/assets/state-of-wasm/desired-language.png
>>978
Wasm⇔JSのオーバーヘッドがあるので処理が少なくほとんどDOM操作になる時だけはJSのみで書いたほうが速い (当たり前)
そのためほぼDOM操作のそのベンチマークではRustフレームワークがわずか数%遅くなっているが現実には処理内容次第ですぐに逆転する
>>983
Elmは型クラス(Rustではtrait)がなく例えば抽象的なイテレータも持てず色々と辛い
このスレはRustにアンチな人がRustを貶めようと常駐して頑張ってるようだけど
Rustを用いるのがベストな方法な場合が非常に多いよ もはや人類の発展はRustにかかっていると言ってもいい similar word exists: `掃き溜め`
similar word exists: `吹き溜まり` rustがベストな時が多いとかよくそういうデマを平気で流せるよね。。 シャドーイングがよくわかりません。
変数名によって中身が一意に決まらなくなることによって、安全性も下がるし並列性?も確保できなくなる気がするのですが、変数が全mutableな言語より安全性マシだしRustは関数型言語じゃないから並列性そこまで重要視してないし書き味のが大事だぜってことですか? 安全性も下がるし並列性?も確保できなくなる気がするのは気のせいではないでしょうか >>991
プログラミング初心者には難しいかもしれないけど
一般的にプログラミング言語ではスコープという概念があってスコープが異なれば同じ変数名でも全く別のものとして認識され格納場所は異なるし型が異なってもよい
その中でもブロックスコープは多くのプログラミング言語で採用されていてブロックが始まると新たなスコープが出来て同じ変数名でも全く別のものとして扱われる
今回のシャドーイングスコープも同様でシャドーイングの時点から新たなスコープが始まるため同じ変数名でも全く別の変数として扱われる
だから安全性は全く下がらないし並行でも並列でもシャドーイングで問題が生じることはない
むしろシャドーイングの利用で利便性が高まっていることがプログラミング経験を重ねると理解できる ダイナミックスコープがデフォルトの言語なんて Emacs Lisp くらいしか見たことないわ。 意図したシャドーイングならともかく、間違って同じ変数名つけたコード片突っ込んでしまった系だと他言語にあるらしい2重宣言エラーないの怖くないですか?
新たなスコープが生まれるので並列性に問題ないことはなんとなく理解できました 次スレは?
>>980が1時間待っても立てなかったら俺がやる このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 74日 11時間 14分 14秒 5ちゃんねるの運営はプレミアム会員の皆さまに支えられています。
運営にご協力お願いいたします。
───────────────────
《プレミアム会員の主な特典》
★ 5ちゃんねる専用ブラウザからの広告除去
★ 5ちゃんねるの過去ログを取得
★ 書き込み規制の緩和
───────────────────
会員登録には個人情報は一切必要ありません。
月300円から匿名でご購入いただけます。
▼ プレミアム会員登録はこちら ▼
https://premium.5ch.net/
▼ 浪人ログインはこちら ▼
https://login.5ch.net/login.php レス数が1000を超えています。これ以上書き込みはできません。