メインコンテンツへスキップ

Rustでまさかの生産性爆上げ!

·3 分
2025/08 Rust プログラミング 生産性 開発効率 ソフトウェア開発

Rustでまさかの生産性爆上げ!

引用元:https://news.ycombinator.com/item?id=45041286

nneonneo 2025/08/27 21:06:12

去年、Rustで書かれたvirtio-hostネットワークドライバをPythonプログラマーなのに1週間で移植したよ!
ほとんどRustもvirtioも経験ないし、ライブラリも初めてだったけど、コンパイル通ったらほぼ完璧に動いたんだ。Rustのライブラリが間違った使い方をさせないようにできてるおかげだね。

mmastrac 2025/08/27 22:35:24

Rustをしばらく書いてるけど、大抵コンパイルが通れば動くね。たまにデッドロックとか高レベルな順序の問題はあるけど、バグさえなければ、コンパイラが成功すればプロジェクトはちゃんと動くってことだ。

jabwd 2025/08/28 01:52:47

俺のコードはあなたのほど複雑じゃないけど、同じような経験をしてるよ。
いくつかの落とし穴と、chronoのバグがあって、2年に1回くらい問題を起こしてるんだけど、それを除けば幸せなRustプログラマーさ。

burntsushi 2025/08/28 10:01:10

jiff を試したかどうか気になるな。chronoでのバグや落とし穴を解決してくれるかな?

AlanYx 2025/08/28 14:30:11

その点ではHaskellに似てるね。一度コンパイルが通れば、大抵はちゃんと動くことが多いんだ。

shark1 2025/08/28 14:25:39

あなたのレビューを読んでRustへの興味がどんどん増してるよ。ツールやエコシステムが素晴らしくて、しっかりしたコンセプトと基盤の上に成り立ってるみたいだね。

baq 2025/08/28 14:47:57

Rustには3つの大きな問題があるね。
―コンパイル時間
―コンパイル時間
―長いコンパイル時間
小さいプロジェクトなら大したことないけど、依存関係をたくさん入れたりコード量が多い場合は、最初にコンパイル単位を考える必要があるよ。

winter_blue 2025/08/28 15:21:17

Rustの増分コンパイル時間はどうなの?大規模プロジェクトでファイルを増分再コンパイルするのは速いのかな?リンク時間がそんなに悪くないといいんだけど。
JVMで好きなのはホットコードリロードだね。メソッドや関数内の変更は、ホットコードリロードでほとんどの場合すぐに反映されるからね。

chiffaa 2025/08/28 15:51:14

リンク時間が最悪だけど、mold[1]やsoldで解決できるよ。増分コンパイルはクリーンコンパイルより1桁(ひょっとしたら2桁)速いけど、それでも遅く感じることもあるかな。
デバッグ時にはsccache[2]とかcranelift[3]を使うと助けになるよ。ホットリロードできる言語ほど速くはないけど、それでもかなり快適な速度にはなるね。
[1] https://github.com/rui314/mold
[2] https://github.com/mozilla/sccache
[3] https://github.com/rust-lang/rustc_codegen_cranelift

mmastrac 2025/08/28 19:59:02

sccache使ってもプロジェクトは速くならなかったな〜。
Denoみたいなクソデカプロジェクトのリリースビルドだけがマジで無理だったわ。
他は大丈夫だったんだけどね。

chiffaa 2025/08/29 11:59:26

sccacheでクリーンコンパイルが2倍速くなったプロジェクトもあるけど、大抵は人によるって感じかな。
効果は限定的だよね。

mmastrac 2025/08/28 19:24:56

Denoではコンパイル時間が長くて困ったよ。リリースビルドは地獄だったけど、デバッグビルドはインクリメンタルなら平気だった。
DenoはRust製アプリの中でも最大級だろうけど、それでも生産性は高かったね。
君のプロジェクトで問題になるのはずっと先だろうし、対策もあるよ。

johnfn 2025/08/28 06:21:55

Rustはマジで最高ってところは同意するよ。でもhrefのバグがTypeScriptのせいってのは違うと思うな。
問題はhref設定がページの移動を後回しにすること自体が分かりにくいって点だろ?
Rustならそんな変なライブラリ設計しないだろうから、これはTypeScriptとRustの問題じゃなくて、WebプラットフォームAPIの問題だね。

flohofwoe 2025/08/28 06:32:55

異議あり!セッターでアクションを起こすなんてありえないし、ましてや即座に実行するなんて論外。
navigate_to(href)みたいに名前を変えるべきだね。
ブラウザ環境で即座に動かないのは当然だろ?
JSはイベントループに指示を出すだけだから、呼び出し元に戻らない関数は合わないんだよ。

johnfn 2025/08/28 07:10:17

良い指摘だね。セッターで作業しないのは当たり前だと思ってたから、コメントを修正したんだ。
「呼び出し元に戻らない関数は…」って話だけど、Node.jsではprocess.exit()でコールバックから抜けられるよね。
もしhrefの設定がそれと同じだったら、もっと分かりにくいだろうな。

mcherm 2025/08/28 10:07:28

もしhrefの設定がそう働くとしたら、try-finallyでリソースをクリーンアップしたり、ロックを解除したりするのとどう絡んでくると思う?
矛盾しないかな?

fleabitdev 2025/08/28 12:49:10

JavaScriptのtry-finallyなんて、どうせ穴だらけだよ。
tryブロックにawaitがあったらfinallyが動かないこともあるし、ブラウザはfinallyを無視してタブを止められるからね。
だからtry-finallyはコード内の局所的なルールを守るためのもの。
process.exit()みたいにJS環境を完全に終了させるなら、finallyブロックをスキップしたって問題ないよ。

bkolobara 2025/08/28 07:36:34

ありがとう、あの例は説明不足だったね。
Rustの所有権モデルを使えば、window.set_href(’/foo’)を呼んだらwindowの所有権が移って、二度と呼べないAPIを作れるって言いたかったんだ。
TypeScriptにはそういうライフタイムの概念がないから無理だね。
JavaScript APIは元々あるし、グローバル変数も多いから、TypeScriptに所有権モデルを導入するのは不可能だよ。
Rustの機能がうまく組み合わさってて、「単なる型」だけじゃ同じ保証は得られないってことを示したかったんだ。

johnfn 2025/08/28 08:00:15

Rustに詳しくないけど、まだ穴があるんじゃない?
window.set_hrefにムーブセマンティクスがあっても、let win = window.set_href(”/foo”)ってして、win.set_href(”/bar”)ってできちゃうんじゃない?これだとエラーにならないでしょ?
もし本当にムーブセマンティクスがないのが問題なら、型をちゃんとすれば問題は起こらないはず。
TypeScriptだってsetHrefがneverを返すようにすれば、それ以降の呼び出しはエラーにできるよ。
これってRustの「!」と同じようなもんじゃない?だからTypeScriptも捨てたもんじゃないかもね :)
https://www.typescriptlang.org/play/?ssl=9%26ssc=1%26pln=9%26pc=2#

bkolobara 2025/08/28 08:56:46

Rustの例は動かないよ。window.set_href(”/foo”)は何も返さない(ユニット型”()”、つまりvoidを返す)から、”()”に対してもう一度set_href()は呼べないんだ。これはRustでよくあるパターンで、特定の関数が特定のオブジェクトに対して一度しか呼ばれないようにしてるんだね。TypeScriptの解決策は本当に好きだよ!これは問題を完璧に解決してる。これが唯一の方法だったら、そもそもこの問題にぶつかることはなかっただろうな。

johnfn 2025/08/28 09:36:44

説明ありがとう!すごく良いパターンだね。
’これが唯一の方法だったら’
まったく同感だよ。

norman784 2025/08/28 11:09:31

他のコメントに追加だけど、これらの2つの例を見て実行してみて。どんなエラーが出るか分かるよ。
https://play.rust-lang.org/?version=stable&mode=debug&editio
https://play.rust-lang.org/?version=stable&mode=debug&editio

dominicrose 2025/08/28 08:13:44

Rustの例は面白かったけど、TypeScriptの例はTSが大きなプロジェクトに良いかどうかを示してないね。Rubyは実行時にバグをよく見つけるから怖いけど、結局コミット前には動くし、そこにたどり着くのは簡単でコードを読むのも編集するのも満足感があるんだ。プロジェクトが大きくなってもこうやって続けられるかどうか、それが問題だね。location.hrefの問題は本当にJavaScriptの問題で、TSがそれを引き継いだものだよ。JSが属性の変更を許すから、ブラウザもその変更を考慮しなきゃならない。でもRubyのexitキーワードとは違う。次のページが読み込まれるまでページはまだそこにいて、それが分かれば完全に納得できる話だよ。

masklinn 2025/08/28 06:46:21

技術的には、set_href()を返すか!を返すかに基づいて、Rustはセマンティクスをヒントできるかもしれないね。でも、条件付きリダイレクトの場合、’誤った’使い方でも表面化しないだろうね(非条件の場合は、その後のコードがデッドコードではないことに気づくかもしれないけど)。

socalgal2 2025/08/28 14:55:32

それは記事のコードのリポジトリじゃないよ。記事のコードは実質これだね。
set_href(’/foo’);
let future = doSomethingElse()
block_on(future)
if (some_condition) {
set_href(’/bar’);
}
このコードの方がバグがより明確になる。doSomethingElseが実質的にページを終了させてるんだ。これは多くのアプリで同じで、Rustでも変わらないよ。ブラウザはwindow.location.hrefを設定したときにプロセスを開始するわけじゃない。コードが終了してイベントループが他のタスクを実行するのを許可した後にプロセスを開始するんだ。例のコードのawaitが、新しいページの読み込み(またはアプリの終了など)という他のタスクの実行を許可してるんだよ。window.location.hrefを設定したときに追加されたそのタスクのことね。
もし分かりにくいなら
// task 1
window.location.href = ’/foo’ // task2 (ページを読み込むtask2をキューに入れる)
let content = await response.json(); // jsonを読み込むtask3を追加
// 完了したらtask4を追加する
// task4
if (content.onboardingDone) {
window.location.href = ”/dashboard”;
} else {
window.location.href = ”/onboarding”;
}
task2はtask1の後に実行される。task1はawaitで終了する。task2はすべてのタスクをクリアする。task3とtask4は決して実行されない。

depressedpanda 2025/08/29 09:57:36

いや、君はそれがどう機能するか誤解してると思うよ。問題は、君が呼ぶところのタスク4が、リダイレクト値によってトリガーされたナビゲーションの後に実行されることだよ。筆者はwindow.location.hrefセッターの副作用、つまり新しいページへのナビゲーションが、その下で実行されているコードを中止することを期待している。最初のif文にreturnがないから、これは明らかに起こらないんだ。

socalgal2 2025/08/30 19:28:11

returnはあるよ、それは“await”という形で偽装されてるんだ。
簡略化すると、”await”のセマンティクスは単なるシンタックスシュガーだよ。
const value = await someFunction()
console.log(value);
はこれのシンタックスシュガーだね。
return someFunction().then(function(value) {
// これはreturnの後に実行される、もし
// 新しいページの読み込みなど、他の何かが全てのイベントを削除しなかった場合だけど
console.log(value);
});

qalmakka 2025/08/28 13:39:10

うん、問題は一部の古いWeb APIが90年代に、おそらく急いで適当にハックされてきたことで、今僕らはその結果と付き合っていかなきゃならないってことだね。これはWebに限った話じゃなくて、僕の経験だとWinAPI全体とかほとんどのlibc関数でも基本的には同じだよ。

buzzin__ 2025/08/28 07:58:34

だから君の主張は、より良いプログラマーがRustを使うからRustは優れてるってことだよね。特にこの部分を言ってるんだ。「Rustはそんなバカなライブラリ設計はしない」って。それなら、Rustプログラマーはそんな循環論法はしないだろう、とも言えるんじゃないかな。

johnfn 2025/08/28 08:01:29

もしもっと寛大に言うなら、Rustのライブラリ設計はWeb APIのライブラリ設計より優れてるって言えるかもね。特に何十年も前に設計された.hrefみたいな古臭いものについては、その通りだと思うよ。

もっとコメントを表示(1)
merdaverse 2025/08/27 18:15:27

君のコードの下に書かれたコードは、早めにreturnしないと実行されちゃうんだよ。あと8時に速報。
真面目な話、値の代入でスクリプトの実行が止まるって、なんでそう思ったの?TypeScriptの例は文脈が足りないのかもしれないけど、それを“データ競合”として提示するのは、なんか変だよ。

lights0123 2025/08/27 18:38:49

exit()とかexecve()とかの関数はすぐに実行を停止するから、リダイレクトもそうだと思う気持ちはわかるよ。

dvt 2025/08/27 18:44:43

リダイレクトってのは代入なんだよ。どの言語でも、変数への代入で実行が止まったことなんて一度もないはずだろ。

JoshTriplett 2025/08/27 18:56:02

ほら、Pythonの例を見てみろよ。
MagicRedirectクラスで、hrefに値がセットされたら“Redirecting to URL”って表示してexit()するようになってるだろ?
location.href = “https://example.org/”ってやったら、ちゃんとリダイレクトして実行が止まってるじゃんか。
これは代入で実行が止まる例だよ。

dvt 2025/08/27 21:18:56

君、セッターをオーバーロードしてるだけだろ。可愛いことするね、俺もJavaScriptでやったことあるけど、これは反例にはならないと思うな。
これを普通のことだと考えるのは、元のブログ記事の考え方からしても変だよ。

rowanG077 2025/08/27 21:31:56

これって、別に変なことじゃないんだよ。Pythonだとプロパティのセッターで何でもできる、ごく普通の例だよ。そういう設計なんだ。
例えば、Fooクラスのbarプロパティに値をセットしたら“bye”って表示してsys.exit()する例とか、
動的言語を認めないならC#でも同じようにできるじゃん。
これ、多くのプログラミング言語では、別に変わったことじゃないんだよ。

dvt 2025/08/27 23:47:57

君もセッターをオーバーライドしてるだけだろ。俺は少数派かもしれないけど、これは完全に特殊なケースだよ。
代入演算子は副作用を持つべきじゃないし、論理学者としての俺の意見だけど、x = 5ってやったときに変なことが起こるかもしれないって意識しなきゃいけないなんて、根本的におかしいだろ。

JoshTriplett 2025/08/27 23:53:27

君は“変数代入で実行が止まらない”から“代入演算子は副作用を持つべきじゃない”に主張を変えたね。
location.hrefは反例だし、他のツールや言語、ライブラリにもそういう例はたくさんあるんだよ。
理想と現実、実際にどう動くかを理解することが重要だね。
(悪い慣習だけど、現実に起こるし、作業環境をコントロールできない人もいる。)
location.hrefに副作用があるなら、それが即座に起こると考えるのは不合理じゃないよ。
そういうのが嫌なら、記事が言うように、そんなことが起こらない言語を選べばいいって話だね。

dvt 2025/08/28 00:09:56

“どの言語でも変数代入で実行が止まったことなんてない”って君は言ってたけど、皮肉なことに、俺はまだ技術的には正しいんだよ。
C++、C#、Python、JavaScriptのどの例も、ゲッターとセッターを悪用したオブジェクトのプロパティへの代入であって、変数への代入じゃないからね(未定義動作の例は別だけど)。

Arch-TK 2025/08/27 18:43:36

window.location.hrefへの代入でブラウザが遷移するなんて、JavaScriptの実行が止まると思っちゃうよね。プログラミングでは仕様確認が基本だけど、この挙動は確かに変だから、勘違いするのも無理ないって話。

ordu 2025/08/27 19:16:15

C言語で*(int*)0 = 0;ってやってみてよ。最近のCコンパイラはUBに対して変な挙動をするけど、昔はSIGSEGVでプログラムがちゃんと止まってたんだ。

kketch 2025/08/28 01:54:44

セッターからの副作用は意外じゃないけど、ゲッターからの副作用は絶対ダメだよ。Rustってミュータビリティを強制するから、そういう期待をちゃんと扱える点でマジで便利だよね。

rowanG077 2025/08/28 00:22:31

議論はプロパティ代入についてだよ。誰も指摘しなかったんだから、それが当たり前でしょ。今さら話をすり替えようとするなんて、正直言ってバカバカしいよ。

DannyBee 2025/08/27 19:28:11

IBMのシステムではね、アドレス0が書き込み可能で常にゼロにマップされてたんだ。だからロードとストアの投機的実行も心配なしにできてたんだって。

lock1 2025/08/27 19:04:54

C++ならoperator=exit()呼ぶようにオーバーロードすれば、「プログラムが止まる変数代入」ってやつを実現できるぜ。

dvt 2025/08/28 00:51:12

議論は=が変なことをするって話だよね。俺が言いたいのは、オーバーロードとか変なことしない限り、=って普通は変なことしないってこと。反論は全部非標準的な例ばっかりじゃん。だから=にデフォで変な副作用があるなんて思うのは絶対ありえないよ。

stouset 2025/08/27 19:06:37

ソフトウェア開発って、知らないうちにたくさんの仮定をしてるんだよね。正しいのもあるけど、危険なのもあって、見極めるのがマジで難しい。hrefの件もAPIが誤解を生む余地があるから、たくさんの人がやっちゃうミスだろ。良いソフトウェア設計は、間違った使い方をしにくくすること。強い型とか、副作用がない純粋関数とか、デフォルト不変性とかがその基礎になるんだよ。

mabster 2025/08/27 22:07:21

昔の組み込みシステムでは、0番地って普通にアクセスするアドレスだったんだよ。だから、一部のコードではNULLポインタアクセスが必要だったし、NULLにジャンプしてシステムをリセットするのも結構普通だったんだ。

eru 2025/08/28 04:51:45

Rustはミュータビリティだけを気にするんだよ。核ミサイルを発射したり、ハードディスクをフォーマットしたりするかまでは追跡しないからね。

drdrey 2025/08/27 19:22:27

OPはリダイレクトが同期処理だと思ってたみたいだけど、スクリプトの実行が止まるとは思ってなかったんだろうね。

kketch 2025/08/28 12:37:41

うん、そうだね。どの言語でも普通そうは期待しないよ。Rustはミュータビリティと所有権の安全策を提供してくれるけど、それをどう使うかは君次第。非ミュータブルな関数呼んだ後でも、Rustで無理やり変更することもできるしね。紙ストローで人を殺すみたいなもんさ。

ngruhn 2025/08/27 19:24:09

JavaScriptを15年使ってる俺でも、そういう挙動だと思ってたよ。

jibal 2025/08/27 19:38:37

違うよ、君は間違ってる。親コメントの他のやつ読んでみてよ。もし同期だったら、POSIX exec()みたいにスクリプトは止まってたはず。OPがスクリプトが止まらないと思ってなかったなら、なんで彼は実行すべきじゃないコードに処理を続行させたんだ?彼はそれを止めるように直したのにさ。

dminik 2025/08/27 18:46:01

それってそんなに明確じゃない気がするな。プログラム全体を終了させるだけのexitを呼ぶセッターも作れるわけだし。

scheme271 2025/08/28 04:17:05

だからね、intやboolみたいなプリミティブ型以外だと、代入でメモリ割り当てとかが必要になる場合があるんだ。そうなると、メモリ不足エラーでプログラムが落ちるとか、ヤバいことが起こる可能性もある。c++のunique_ptrとか見ると、代入が裏でいろんなことやってプロパティを保ってるよね。Rustとか他の言語も、保証のために特定の型で似たことするはずだよ。

BobbyJo 2025/08/27 21:15:08

代入演算子をオーバーロードして関数呼ぶようにして、それを使うのを「本当の代入」とは考えないかな。

buu700 2025/08/28 08:16:49

正直、hrefの件は妥当な仮定だと思うな。APIデザインは残念だけど、あのAPIならスクリプトもそこで止まるって考えるのが自然だよね。俺はこういうのは常に防御的に書くタイプなんだ。location.hrefの正確な挙動は今日まで自信なかったけど、昔書いたコードがちゃんと処理されてたのは、return文を最初から入れてたからだよ。こういう防御的コーディングはヘイゼンバグを防ぐし、技術的に不要でも可読性を上げる良いスタイルだと思う。

galangalalgol 2025/08/28 02:13:49

不変性を保つための代入演算子のオーバーロードは分かるけど、このケースは組み込みc++出身の俺には実行が変に感じるな。演算子オーバーロードは好きじゃないし避けるべきだと考えてるよ。もうc++は使ってなくて、数年前からRust一筋さ。

svieira 2025/08/27 19:33:24

昔は逆の挙動だったって確信してるよ。そうでなくても、最近何か変わって、”後で発生する”挙動がブラウザで増えたんじゃないかな。

JoshTriplett 2025/08/27 18:44:34

JavaScriptのページ遷移って”noreturn”関数みたいに動作するべきだけど、そうじゃないんだよな。これ、すごく間違いやすいミスだよね。

もっとコメントを表示(2)
jacquesm 2025/08/28 07:22:43

ほら、上の方で前提について話してたでしょ?これのことだよ: https://man7.org/linux/man-pages/man3/atexit.3.html

BinaryIgor 2025/08/27 17:30:15

多くのメリットって、静的型付けでコンパイルされる言語だからだよね?Java、Go、C++とかさ。TypeScriptはJavaScriptにコンパイルされるからちょっとややこしいけど、それでも問題ない。Rustはもっと厳密な型システムで追加のコンパイル時チェックがあるけど、タダじゃないし、学ぶのも読むのも大変だよね。

pornel 2025/08/27 18:19:28

大体はそうだけど、Rustは型システムに所有権、排他的アクセス、スレッドセーフティ、sum typesとか、もっと多くの要素を追加してるんだ。所有権と借用のおかげで、データがどこでどう使われるか明確になるから、大規模なプログラムや外部ライブラリを使う時にめちゃくちゃ役立つよ。Go言語と比較すると、Rustのスレッドセーフティはデータ競合をコンパイル時に捉えられるから、デバッグがめちゃくちゃ楽になるんだ。

zelphirkalt 2025/08/27 18:44:59

借用でイラつくのは、俺のデフォルトのやり方だと、できるだけ変数を変更しないようにしてるのに、Rustだと他の手続きに渡した後も使いたい場合、コピーやクローンを強制されることなんだ。これって、精神的にも構文的にもオーバーヘッドが大きいんだよな。FP言語だと、値を渡すだけで変更しない前提だから、そういう追加の手間は要らないし。要するに、変数を変更しないなら所有権なんて必要ないんだよ。変更する時だけ所有権の概念があればいいのに、変更しない時もずっと気にしてコードに持ち歩くのは嫌だね。

arwhatever 2025/08/27 18:23:41

もし君が全ての静的型付け言語を一緒くたにしてるなら、union型(Rustのenumやsum type)と網羅的なパターンマッチングの真の価値をまだ理解してないのかもしれないな。「union-pilled」って呼んでるんだけど、これに慣れると他の静的型付け言語を受け入れられなくなるくらいすごいんだ。

vlovich123 2025/08/27 19:48:46

君、Rustを実際に知らないんじゃない?Rustは非所有の借用も所有権も型システムで直接表現できるよ。
変更しない非所有の借用でクローン/コピー不要なのは fn foo(v: &SomeValue)
所有権の移動でクローン/コピー不要、変更なしは fn foo(v: SomeValue)
所有権の移動でfooが変更可能は fn foo(mut v: SomeValue)
Rustは君が求めてる表現力を全部サポートしてるはずだよ。もし同じ値の所有権を2つ持ちたいなら、定義上クローンするしかないけどね。システムエンジニアリング言語としてのトレードオフだよ。

ModernMech 2025/08/27 19:05:47

enumsmatch expressions、それにtagged unionsがRustの秘密のソースなんだよ。

pjmlp 2025/08/28 09:36:01

このコードスニペットみたいに?(型定義とtokenizerのコードスニペット省略)ヒント、これRustじゃないからね。

lmm 2025/08/28 12:55:57

Rustの秘密は、a) 70年代後半の重要な言語機能(Algol ’52になくて人気の言語系譜に欠けてたもの)と、b) C言語より速いベンチマークみたいな「パーティートリック」の両方を提供してることだよ。人々はb)で採用し始めて、a)のおかげでプログラミングが苦じゃないって感じ。ML系の言語がRust以前に普及しなかったのはプログラミング文化の残念な点だけど、Rustも採用されないよりはマシだよね。

zelphirkalt 2025/08/27 20:09:14

値渡し(参照じゃない)だと値を借用しなきゃいけないから、呼び出し元で後から使えなくなる経験があるんだけど。参照渡しはまた別で、そっちだと使うのに構文的な手間がかかるんだよね。具体的な例を教えてくれない?

Tuna-Fish 2025/08/27 20:44:31

「値渡しで借用が必要」って、用語がごっちゃになってるね。借用は参照のときだけだよ。Copyできない値を渡すときはムーブなんだ。一般的に、Copyできないものは非mut参照で渡すのがベスト。そうすれば呼び出し元も後で使えるし、Rustの型システムとも相性いいんだ。全部cloneするんじゃなくて、Copyをderiveするか、参照を使おう。

zelphirkalt 2025/08/27 21:09:30

ってことは、CopyやCloneがないと値渡しできないって認識で合ってる?他の言語みたいに、値渡ししても呼び出し元で使えるようにしたいんだけど。参照渡しだと構文が面倒だしね。Rustはミュータブルな値の場合だけ、呼び出し元で使えるか心配してくれればいいのに。SerdeのStructでStringが入ってるとCopyをderiveできないこと、よくあるよね。

hollerith 2025/08/28 13:05:59

70年代後半の言語機能って話だけど、線形型は89年まで研究されてないよ。Rustがメモリ安全を保証できるのは、GCなしで線形型に頼ってるからだしね。ML系言語がRustほど流行らなかったのは、「CPUやメモリの使用量、メモリ局所性が推論しにくい」って正当な理由があるんだ。GCが必要なのも一因だよ。

lmm 2025/08/28 13:30:26

ModernMechも言ってたけど、RustのメリットはSum Typesとパターンマッチングがほとんどだよ。「ML系言語はCPUやメモリの使い方を推論しにくい」って言うけど、それってRustが使われるほとんどのケースでは、そこまで重要じゃないんだよね。

gf000 2025/08/28 15:19:29

「RustのメリットはSum Typesとパターンマッチングのおかげ」って意見には疑問だな。Scala、OCaml、Haskellとか、同じ機能を持つ言語はたくさんあったけど、Rustみたいに人気にならなかったでしょ。Rustがこれだけ人気なのは、他の言語にはない独自の能力があるからだと思うよ。

timeon 2025/08/27 18:56:36

「FP言語では値を渡す」って言ってたけど、それってRustでいうムーブのこと?参照渡しじゃないんだよね?

w10-1 2025/08/27 18:47:16

みんな、エフェクトシステムと型システムを区別するといいよ。エラーハンドリングとか所有権とかは、値の使い方に関わるからエフェクトとして捉えた方がわかりやすい。Javaは参照型メインだけど、それも別のエラーを生む。Swiftは排他性とか安全面でRustと良い勝負だし、所有権も追いついてるよ。あと、Rustのtraitとマクロはプログラマが制約を定義できるからすごいんだ。これで標準ライブラリも小さくなるしね。

zelphirkalt 2025/08/27 20:04:05

そうそう、Rustだとそれはムーブって呼ばれるよ。ムーブすると、呼び出し元ではもうその値を使えなくなるんだ。でも、呼び出し先で値を変更しないなら、呼び出し後もその値を使いたいんだよね。Rustが、変更がない場合は値を自由に使えるようにしてくれたらいいんだけどな。変更があるならエラーでOKだよ。

ModernMech 2025/08/28 16:35:38

Scala、OCaml、Haskellは関数型ファーストだけど、Rustがすごかったのは、それらの機能を命令型コアとうまく融合させたことだよ。これだけじゃ成功は無理で、企業のサポートや素晴らしいコミュニティ、そして運も必要だったんだ。Haskellは学術向けだし、OCamlは企業支援がなかった。ScalaはJavaのついでって感じだったから、Rustみたいに人気が出なかったのも納得だね。

gf000 2025/08/28 17:47:06

ScalaはFPとOOPが混じった言語だね。モナドとかをガチでやるFP派もいれば、Li Haoyiのライブラリみたいにバランス重視の人も同じくらいいるんだ。Scalaは確かにニッチだけど、そういう立ち位置なんだろうね。

ModernMech 2025/08/27 18:59:47

Swiftの型システムはRustと比べると使いやすさで劣るね。型チェッカーがタイムアウトして「リファクタリングしろ」って言ってくるのは、ジョークとしか思えないよ。よく平気な顔してリリースできたもんだよね。

throwawayffffas 2025/08/28 08:40:33

俺も同じ不満だね。できないわけじゃないけど、代入するときはデフォルトでコピーかムーブになってほしいんだ。C++のSTLを使うときみたいな感じがいいな。

NIckGeek 2025/08/27 20:49:21

値への参照(つまり&T)を渡せばいいんじゃない?所有権が絶対必要なら、関数が所有値を返すか、Rc<T>みたいな共有所有権を使えばいいよ。GC付きの関数型言語だと、だいたい後者と同じことしてるね。

zelphirkalt 2025/08/27 21:11:46

できるとは思うけど、そうするとすべてのプロシージャの引数に&を付けなきゃいけないし、プロシージャ内で参照を扱う構文にも対応しないといけないんだよね。

vlovich123 2025/08/28 10:48:06

コピーできない型は、パフォーマンスの問題があるからコピーできないんだ(C++で巨大なベクターをコピーするみたいにね)。でもRustは代入で常にムーブがデフォルトだから、君の不満が分からないな。型がCopyを実装してれば、所有権が競合するときはRustが自動でコピーするよ。

ModernMech 2025/08/28 18:41:59

Scalaの主な問題は、null値で実行時エラーが出る可能性があることだね。だからRustやHaskell、OCamlがパターンマッチングでくれるような実行時の安全性保証はないんだ。例えば、このScalaコードは実行時パニックになるよ: https://scastie.scala-lang.org/fnquHxAcThGn7Z8zistthw 。これはRustではコンパイルされない。ScalaはJVMでJavaを書かずにコードを書けるのが利点かな。

Tuna-Fish 2025/08/27 21:46:31

CopyCloneもできない値を渡すことはできるけど、呼び出し先にムーブされて呼び出し元では使えなくなるよ。大きな型での値渡しはコストが高いんだ。他の言語は常に参照渡しで、君はそれを値渡しと混同してるみたいだね。Rustは君の望むようにはできないよ。関数の型チェックには、その関数のコードと他の型定義だけが必要で、内容は関係ないんだ。これはコードを読みやすくする良いルールだよ。

rendaw 2025/08/28 05:16:10

すべての静的型システムが同じくらい表現力豊かで安全とは限らないよ。JavaはObjectと実行時キャストに頼りがちだし、Goにはenumがない。C++のバリアントは後から追加されたから、使うときに落とし穴や使いにくさがあるんだ(安全アクセスにはtry/exceptが必要で、他の制御構造とは一緒に使えないんだ)。

記事一覧へ

海外テックの反応まとめ
著者
海外テックの反応まとめ
暇つぶしがてらに読むだけで海外のテックニュースに詳しくなれるまとめサイトです。