Rust part11

■ このスレッドは過去ログ倉庫に格納されています
2021/06/17(木) 00:24:12.56ID:NvYoNP9C
公式
https://www.rust-lang.org/
https://blog.rust-lang.org/
https://github.com/rust-lang/rust

Web上の実行環境
https://play.rust-lang.org

日本語の情報
https://rust-jp.rs/

※Rustを学びたい人はまず最初に公式のThe Bookを読むこと
https://doc.rust-lang.org/book/

※C++との比較は専用スレへ
C++ vs Rust
https://mevius.5ch.net/test/read.cgi/tech/1619219089/

前スレ
Rust part10
https://mevius.5ch.net/test/read.cgi/tech/1617367084/
2021/08/21(土) 09:43:26.29ID:KTz5aeQ/
>>795
アロケーションが発生するのは伸長するときだけでしょ
伸長するような用途だったら、そもそも配列使えないし

>一方で配列は必ず固定長でスタックに置かれます
だめじゃん。スタックオーバーフロー考慮するならvecの方がいいじゃん

まあ、自分も組み込み以外でスタックフレームのサイズなんて考慮したことないけど
2021/08/21(土) 09:50:40.59ID:KTz5aeQ/
>>795
ちなみにスタックにあることによってL2キャッシュに載りやすいだろ!
という意見ならそれは同意する。サイズが小さければね。
799デフォルトの名無しさん
垢版 |
2021/08/21(土) 10:08:08.47ID:/0ZvMIRv
>>797
> アロケーションが発生するのは伸長するときだけでしょ

いいえ。
Vecの実体は必ずヒープにアロケーションされます。
Vec自体は(指定しなければ)スタック上で、ヒープへのポインタや長さなどで構成されて固定長です。
Stringも内部はVec<u8>なので同様です。
2021/08/21(土) 10:12:53.88ID:KTz5aeQ/
>>799
ああ、アロケーションじゃなくてヒープにってところを問題視してる?
ガベージコレクションの発生を懸念してる?
801デフォルトの名無しさん
垢版 |
2021/08/21(土) 10:22:22.66ID:HwKH2mPW
>>800
Rustではガベージコレクションは起きない
しかしスタック上かヒープ上かの区別は重要
スタック上のデータはその関数を終える時に消滅する
2021/08/21(土) 10:31:43.28ID:KTz5aeQ/
>>801
>Rustではガベージコレクションは起きない
ヒープを使ってるんだから起きないわけないだろ

>スタック上のデータはその関数を終える時に消滅する
Vecの中身だって関数を終えるときに解放されるでしょ
されないんだっけ?

そもそもの話は配列を使ってるところをVecにしても問題なくね?ってことなんだけど
どこが問題になるかの例を示してもらえたら、わかりやすい
2021/08/21(土) 10:58:14.92ID:Hi//C77Q
rustにはガベージコレクションがないんだぜ・・・
2021/08/21(土) 11:04:35.75ID:eqU3IJp1
デストラクタ的な機構で後始末するのはガベージコレクションとは普通言わない
2021/08/21(土) 11:09:11.24ID:JLDZmydZ
Cでもひーぷをつかうとがべーじこれくしょんがおきるの?
806デフォルトの名無しさん
垢版 |
2021/08/21(土) 11:11:34.22ID:6mCMrQuL
ヒープへのメモリアロケーションはコストが高いから避けたいんでしょ
807デフォルトの名無しさん
垢版 |
2021/08/21(土) 11:25:28.41ID:ozkLLafu
>>802
RustにGCはない

Vecの中身(配列相当部分)はスタック上ではなくヒープ上なので関数を終えるときに解放されない
Vec自体が消える時に解放される

Vec自体(ポインタと長さなど)はスタック上にあれば関数を終える時に消える
もちろんVec自体を関数の返り値として返すことは出来る
受け取った上位の関数でVecの中身を使える

例えば
fn main() {
 let mut v: Vec<i32> = make_i32_vec_from_args();
 v.push(999);
 println!("{:?}", v);
}

fn make_i32_vec_from_args() -> Vec<i32> {
 let mut v = Vec::new();
 std::env::args().skip(1).map(|s| s.parse::<i32>().unwrap()).for_each(|n| v.push(n));
 v
}

$ cargo run 111 222 333
[111, 222, 333, 999]
2021/08/21(土) 11:42:53.96ID:3jqa2oM2
そういや何でalloca()無いの?
2021/08/21(土) 12:23:12.36ID:kcBD0DB/
>>795
Box<[T; N]> のように配列がヒープに置かれる場合もある
2021/08/21(土) 12:35:23.13ID:5zDPvhJy
>>809
それはBoxだからであって、そんなこと言い出したら整数だってヒープに置かれうる
しかし普通に「整数型はスタックに置かれる」と言われる時は、Boxを使わない場合を意味している
Boxを使えばヒープに置かれるのは自明だからだ

したがって、整数や配列やVecの管理データ部分はそのままだとスタックに置かれるがVecのデータ実体は常にヒープに置かれる、で良い
2021/08/21(土) 13:25:00.39ID:KTz5aeQ/
うーん、なんだかなー
みんなヒープのことを無限にバイトを吐き出す魔法の箱かなんかだと思ってない?

>>805
>Cでもひーぷをつかうとがべーじこれくしょんがおきるの?

当然
Cのmalloc/freeやC++のnew/deleteでもガベージコレクションは発生する
wikipediaの「ヒープ領域」がよくまとってるよ

いくつかの理由からfree/deleteのガベージコレクションはJavaやC#のガベージコレクションよりも超高速だ
それでも、組み込みの世界ではガベージコレクションのせいでリアルタイム性が失われることを嫌がって、
ヒープを使わなかったりする

じゃあ、組み込みでは動的なメモリをどうするかっていうと、リンクドリストのノードをメモリブロックに
見立てて、メモリ管理システムにしたりする
これだと取得も解放も定数時間のコストだからね

>>807
すまん、例をみてますます配列なくても困らない気がしてきた
配列でできて、Vecにできないことはないの?
2021/08/21(土) 13:35:03.05ID:+9L1DmAB
>>811
Rustにはガベージコレクションはありません
おっしゃる通りヒープからの取得も解放も定数時間のコストで行なわれ更にガベージが溜まることはありません
Rustでは生存期間や所有権に貸し借りが明白になっているため、使用中のものが解放されたり、解放済みが使われたり、使用済みが解放されなかったりは起きません
2021/08/21(土) 13:50:09.86ID:KTz5aeQ/
>>812
>ヒープからの取得も解放も定数時間のコストで行なわれ
これってどういう原理? 本当に定数ならそれもうヒープじゃないんじゃ

ヒープツリーを辿る処理も未使用ノードを結合する処理も定数時間って
ありえないと思うんだけど
814デフォルトの名無しさん
垢版 |
2021/08/21(土) 14:16:15.10ID:G8x/1s0B
もしかしてmalloc/freeのヒープメモリ管理のことをこの人はガベージコレクションと呼んでいるのかも
そのためRustにガベージコレクションがないことを理解できていないような感じ?
2021/08/21(土) 14:22:08.01ID:KTz5aeQ/
調べた
・rustのヒープはフリーリストアロケータじゃない
(サイズごとのメモリスラブをさらに分割して使う)
・取得・解放は定数時間じゃない
(メモリスラブ全体が未使用になったときに、デフラグして別サイズのスラブとして利用可能になる)
→これ実質ガベージコレクション処理じゃん
・当然デフラグは発生するが、大して問題にならない
→そうだろうね。C++でさえアロケータ書いたことない
・問題になるならアロケータを自作することも可能(デフォルトはjemalloc)
だそうだ。
ヒープはヒープ構造じゃないのか……
2021/08/21(土) 14:36:21.13ID:KTz5aeQ/
>>814
>もしかしてmalloc/freeのヒープメモリ管理のことをこの人はガベージコレクションと呼んでいるのかも
freeの中にもガベージコレクション処理があるんだよという話
javaと違ってマーク&スイープ処理いらないから早いけどね

>そのためRustにガベージコレクションがないことを理解できていないような感じ?
そんなことはわかってる
今は処理コストの話をしてる

サイズが変わらないVecと配列(配列なのでもちろん固定長)でそこまで優位の差があるのかと訊いた
そこでVecはヒープを使う(からダメだ)という答えが返ってきたので、
ヒープを使うとなぜダメなんだ? ガベージコレクションのオーバーヘッドを気にしてるのか?と

そうするとrustはガベージコレクションありませんと言われた
じゃあ、結局のところヒープを使うとなぜダメなんだ?
2021/08/21(土) 14:43:58.08ID:3jqa2oM2
勝手に定義した「ガベージコレクション」なんか議論するだけ時間の無駄
2021/08/21(土) 14:48:02.99ID:HlQuVij0
>>816
あなたが完全に間違っている
それを世間ではガベージコレクションとは呼ばない
2021/08/21(土) 14:50:34.09ID:KTz5aeQ/
>>818
辞書が絶対とは言いたくないがwikipediaの「ヒープ領域」見て
2021/08/21(土) 14:52:48.65ID:Hi//C77Q
自分でfreeしたものをGCと呼ぶとは強者が現れたな
2021/08/21(土) 14:53:06.41ID:O7+p4qIy
それこそwikipediaの「ガベージコレクション」見てもらった方がいいのでは。
822デフォルトの名無しさん
垢版 |
2021/08/21(土) 14:53:37.02ID:6mCMrQuL
もうジェマロクはデフォルトじゃないよ
2021/08/21(土) 14:58:27.12ID:Hi//C77Q
そういやこんな記事があったよ

実装言語を「Go」から「Rust」に変更、ゲーマー向けチャットアプリ「Discord」の課題とは
ttps://atmarkit.itmedia.co.jp/ait/articles/2002/10/news038.html

> 平均すれば高速に動作していたものの、数分ごとに平均応答時間が急に大きくなり、
> ユーザーエクスペリエンスを損なっていた。調査したところ、
> これはGoの中核機能であるメモリモデルとガベージコレクタ(GC)に起因することが分かった。

> Rustではガベージコレクションが不要だ。
> 同社がRead StatesサービスをRustで実装しようと考えたのはこれが理由だ。
> Rustを使えば、Goで実装した場合に生じた平均応答時間の急増は見られないだろう。
2021/08/21(土) 15:02:21.85ID:KTz5aeQ/
>>820
だから、ここではコストの話をしてるんだって言ってんのに

>>821
見た。もちろん知ってる。
本題からずれてる。自動解放とかデフラグの定義の話がしたいんじゃない
配列とVecのことが知りたいんだって

なんだってこう話を逸らすんだ?
2021/08/21(土) 15:02:56.01ID:watXYiN6
>>819
https://ja.wikipedia.org/wiki/%E3%83%8E%E3%83%BC%E3%83%88:%E3%83%92%E3%83%BC%E3%83%97%E9%A0%98%E5%9F%9F
> 7月15日(土)12:22の版で記述いただいた内容のうち、「ガベージコレクション」という部分だけ誤りと思われるので、7月19日(水)02:32の版で消させていただきました
せやな。
2021/08/21(土) 15:10:24.32ID:hSZ/tOwO
>>824
まずはプログラミング言語におけるガベージコレクションとは何かを理解して
次にRustではそのガベージコレクションがないことを理解して
その上で何を質問したいのかを整理してはいかがでしょうか?
それを終えてからでないとあなただけ用語の定義が異なったままでは話が進みません
827デフォルトの名無しさん
垢版 |
2021/08/21(土) 15:10:57.04ID:IZ1Oj5x4
ガベコレは普通javaとかpyのコンパイラやらインタプリタがreference counterをオブジェクトに勝手に付随させる事を想定するけどな


Vec arr処理コストの違いに関してはbuffer使わないんだからarrayの方が基本的には糞みたいに早いと思うがな
そこらosとかによって最適化図られるからオブジェクト生成のとき以外は決定的な違いあんまなさそうだが
要素数をコンパイルタイムに決定(これのアルゴにもよるが)出来るなら普通はシンプル配列の方が速いよね


goはparallel threadingみたいな部分で変なgc実装してて大量に独立の計算量ハード問題導入するからねそこらへんがドイヒーなんだろうな
俺は好きだけど(´・ω・`)
828デフォルトの名無しさん
垢版 |
2021/08/21(土) 16:18:04.16ID:iwjgeVKb
>>824
何度も説明されている通り
配列は固定長なのでデータ管理部分はなく配列は通常スタック上
Vecは可変長なのでデータ管理部分がありそれは通常スタック上そして配列相当部分は常にヒープ上
2021/08/21(土) 16:29:59.01ID:0b1Dm8dh
コンパクションとガベージコレクションの区別がついてない

世の中のガベージコレクターがコンパクションもやってるからといって
コンパクションのみを指してガベージコレクションとは呼ばない
2021/08/21(土) 16:33:27.85ID:Ay6lvOn8
ふりだしに戻る >>787
2021/08/21(土) 16:37:39.49ID:KTz5aeQ/
>>828
それの何が問題?
stringの実装はヒープだけど問題ないよね?
こういう使い方をすると配列より100倍くらい遅いとか、メモリリークするからVec止めて配列使えとか
そういう注意点ある?

もちろんループの中でVec::newするとオーバーヘッドでかいとか、
そういうわざとらしいのはなしにして

あえていうなら初期化の記述量がちょっと増える、とか?
2021/08/21(土) 16:59:15.86ID:dJkGQ7Qm
>>831
誰も何も問題にしていませんよ
あなたが勘違いをして勝手な何かを問題にしているだけ
StringはVecにstructの皮を被せただけなので状況は同じ
2021/08/21(土) 17:06:03.36ID:Hi//C77Q
>>829
HDDの頃はよく使ってたHDD最適化と容量を増やすみたいなソフトを思い出した

HDDのデフラグ → メモリコンパクション
HDDにある不要なキャッシュの削除 → ガベージコレクション

こんな感じに似てるな
2021/08/21(土) 17:16:16.64ID:eqU3IJp1
ヒープがヒープ構造じゃないのかとか言ってるから本当に何も知らなかったのだろう
オレオレ用語使われると混乱するからとりあえずmalloc動画くらいみて勉強してきてほしい
2021/08/21(土) 17:26:30.08ID:KTz5aeQ/
>>834
そこ話の本筋じゃないんだよなー
Vecはヒープ使ってるからダメって言われて、何がダメか説明してくれって言ってるだけなんだけどなー
2021/08/21(土) 17:30:07.73ID:pF+sRbnf
>>835
ヒープ使ってるからダメ、なんて誰も言っていない
全ては君の勘違い
2021/08/21(土) 17:31:33.62ID:KTz5aeQ/
>>836
そうなの? じゃあ結論として配列はVecに置き換えても問題ないってこと?
2021/08/21(土) 17:52:04.92ID:eqU3IJp1
Vecは固定長配列(型[u8; 32]とかで表されるやつ)を置き換える用途としては使えないが, 逆に言えばそれだけ
2021/08/21(土) 18:26:53.45ID:Hi//C77Q
むしろ配列なんてクレート使わないとコンパイル時点で数値が決まってないと使えないから
ほとんど出番がないんだから、どこに悩む必要があるというのか
2021/08/21(土) 18:30:22.30ID:AgJApIsV
>>835
>Vecはヒープ使ってるからダメって言われて、何がダメか説明してくれって言ってるだけなんだけどなー

あなたの妄想ではないですか?
スレを読みましたが、
Vecはヒープ使ってるからダメと言われた書き込みが見当たりません。
2021/08/21(土) 18:31:04.95ID:3jqa2oM2
ヒープは悪であるということをハッキリと言う
2021/08/21(土) 18:41:19.82ID:tswurJ+7
Linux のデフォルトではスタックの大きさは 8 メガが上限じゃなかったっけ?
(Windows だともっと小さかったはず)
大きさが固定 (コンパイル時に確定する) でかつ十分に小さく寿命が短いなら配列をスタックにおく
のは性能的に有利 (確保と解放のコストが小さい) だが、大きさを見積もれないときにスタックに置くと
スタックが足りないときにどうにもできないで即死するしかない。

大きさのわからない配列はスタックに置くべきではないというのが世の常識というもの。
少なくとも高レイヤのアプリケーションでは。
2021/08/21(土) 20:16:15.20ID:3jqa2oM2
仮想メモリなんだからスタック8GBに設定すればいいんじゃないの?
844デフォルトの名無しさん
垢版 |
2021/08/21(土) 20:43:23.20ID:7GAoG1Iq
Rustのメモリ安全性はボローチェッカーによって担保されているが、
Nimと比較してRustはタイプ量が多い事により限りなく低い生産性と
C++のような高い難読性、超巨大なバイナリ生成性能を兼ね備えています

Nimはバージョン1.5.1でRustのボローチェッカーに似た「View types」が実装されれば、
GC無しでView types参照の有効性を検証することによってメモリ安全性を保証しつつ
限りなく抑え込まれたタイプ量で高速化したCのソースコードを吐き出せます

Nimソースコード ==nimコンパイラ==> Cソースコード ==Cコンパイラ==> バイナリ

なので、nimコンパイラが通った時点でメモリ安全性が担保されませんか?

Nimの実験的特徴
著者: アンドレアス・ルンプ
バージョン: 1.5.1
http://nim-lang.github.io/Nim/manual_experimental.html


Nimは限りなく抑え込まれたタイプ量で高い生産性とPythonのような高い可読性を実現し
ているにもかかわらず、Cのソースコードを吐き出せるのでC言語でリモートワークされ
ている方は割り振られた仕事が早く終わっても終わってないふりをして怠けることができる

「怠け者とはこうあるべきだ!」と言うとても大事な事を Nim は我々に教えてくれます
845デフォルトの名無しさん
垢版 |
2021/08/21(土) 20:47:51.35ID:6mCMrQuL
Nimは知らんがパイソンが読みやすいなんて
2021/08/21(土) 20:53:42.26ID:Z4f8T8IW
pythonが特別読みやすいとは思わんが、pythonで読みづらいコード書くやつが
何で実装しても読みやすいものを書くことはないだろう。
2021/08/21(土) 20:55:25.62ID:6DBrqemS
>>844
Pythonはたまたま外部ライブラリ充実などで普及していますが、あまりよろしくない言語です。
そのためPythonで開発したいという人はいないです。
なので「Pythonのような高い可読性を実現している」と宣伝されても逆効果。
2021/08/21(土) 20:58:33.68ID:O7+p4qIy
>>844の人は関係ないスレに迷惑かけて、nimユーザーのイメージダウンが目的なんだろうか。
2021/08/21(土) 21:35:33.43ID:PyG7lKVy
積極的にPython使おうとは思わんなぁ。インタプリタ系はRuby使っているわ
Luaも結構良い感じだと思う
2021/08/21(土) 21:54:02.20ID:tswurJ+7
うん。 プログラマは Python をそんなに気に入ってない場合は多いと思う。

ただ現代ではプログラミングするのはプログラマとは限らない。
Python は元々はコンポーネントを組み合わせる、いわゆるグルー言語として設計されていて、
エンドユーザ向けの性質を持っている。 BASIC 系と似た立場かな。
このくらいに制限されていたほうがかえって使いやすいという場合は確かにある。

必要なコンポーネントが出そろっている状況で上位のロジックを組み立てる分には
Python も便利なこともあるにせよ、言語としての出来はそんなに良くない。
851デフォルトの名無しさん
垢版 |
2021/08/21(土) 21:59:07.63ID:7GAoG1Iq
>>845
>Nimは知らんがパイソンが読みやすいなんて

Pythonは構文にインデントを組み込むことによってざっと眺めた時に人間が読みやすい
一般的には上記の事をPythonは高い可読性があると表現されています
この事は「Pythonは可読性の高い言語」ググれば約 265,000 件出てきます

他の言語と可読性は同じだろって意見の人もいますが少数派ですね
2021/08/21(土) 22:21:31.89
>>851
https://mevius.5ch.net/test/read.cgi/tech/1587276362/963
「javascriptは可読性の高い言語」で検索すると約 334,000 件
2021/08/21(土) 22:31:37.65ID:7PPLxZL+
元の文脈的に
nimも構文にインデントを組み込んでるからpythonが出てきただけでそういう議論がしたいんじゃないと思う
854デフォルトの名無しさん
垢版 |
2021/08/21(土) 22:36:10.82ID:7GAoG1Iq
>>852
>「javascriptは可読性の高い言語」で検索すると約 334,000 件

単に検索件数が多いだけで、上位10件の表示内容を読んでも
「javascriptは可読性の高い言語」と言う内容のページは1つも見つかりません

対して「Pythonは可読性の高い言語」は上位10件の内5件見つかりました
855デフォルトの名無しさん
垢版 |
2021/08/21(土) 22:41:14.03ID:7GAoG1Iq
>>853
おっしゃる通りです(/ω\)
2021/08/21(土) 22:56:47.50ID:lXSuJ2vU
ただのコピペ荒らし
まったくRustもNimも関係ないスレでも見るし
857デフォルトの名無しさん
垢版 |
2021/08/21(土) 23:00:47.35ID:YSvCkW+D
Rust Tourだけやっていても作業の流れが身につかなさそうなので、写経を始めました
そこでまず出くわしたのがTokioのバージョンの壁で、バージョンによって動いたり動かなかったり差がありました
クレートの無難なバージョンがどれか、クレート同士の無難な食い合わせはどれか、など、どうやって知れば良いのですか?
858デフォルトの名無しさん
垢版 |
2021/08/21(土) 23:07:06.11ID:7GAoG1Iq
>>857
Nimの写経を始めましょう
2021/08/21(土) 23:07:52.34ID:kcBD0DB/
写経なら写し元と同じバージョンにそろえるのがよいのでは
860デフォルトの名無しさん
垢版 |
2021/08/21(土) 23:24:51.23ID:7GAoG1Iq
>>859
>写経なら写し元と同じバージョンにそろえるのがよいのでは

Nimのバージョン 1.5.1を写経しましょう

Nimの実験的特徴
著者: アンドレアス・ルンプ
バージョン: 1.5.1
http://nim-lang.github.io/Nim/manual_experimental.html
2021/08/21(土) 23:48:46.37ID:PyG7lKVy
組み込み系ではMicroPythonが流行っているらしいが全く魅力を感じないw
2021/08/21(土) 23:53:13.51ID:+zMEbJ+6
Nimを調べてみたのだが
Rustよりも高機能な点を見つけられなかった
もし有るならば書いてください
無ければ去ってください
863デフォルトの名無しさん
垢版 |
2021/08/22(日) 02:15:33.57ID:0Cz6ueFz
>>862
>Nimを調べてみたのだがRustよりも高機能な点を見つけられなかった
>もし有るならば書いてください
>無ければ去ってください

そんな寂しい事言わないでかまってよ〜(´;︵;`)

行末のセミコロンが必要ない
タイプ数がもりもり減ります。

Rust にはもちろん必要です。

main が要らない
スクリプト言語感覚でいきなりコードを書けます。

Rust は main が必要です。

>Nimキチガイ

いつもみんなによく言われます
いや〜照れますね〜v(=^0^=)v
864デフォルトの名無しさん
垢版 |
2021/08/22(日) 02:16:39.23ID:KEfgBimj
>>863
nimのスレ立ててそっちでやってよ
2021/08/22(日) 02:32:40.46ID:w5XnK8W7
>>863
あなたは知恵遅れか何か?
Rustより高機能な点を問われているのに、セミコロンが必要ないとかどうでもいい話しかできないの?
答えられないならここから出ていきなさい。
2021/08/22(日) 02:33:23.15ID:j+Q/a+4n
構うな
さっさとNG
867デフォルトの名無しさん
垢版 |
2021/08/22(日) 02:35:27.65ID:0Cz6ueFz
>>863
>nimのスレ立ててそっちでやってよ

そんな寂しい事言わないでかまってよ〜(´;︵;`)

Nim は標準出力への文字列出力が楽
Nim では echo で改行付きの出力ができます。shell と同じですね。通常は改行付きで出力することの方が多いでしょ。
Nim はしょっちゅうやることは簡単にできるようになっています。
そんな Nim の echo は可変引数で値を受け取り型が何なんだろうとお構いなしに出力できます。

let n = 10
let str = "HOGE"
echo "Number: ", n, " String: ", str
一方 Rust は

let n = 10;
let str = "HOGE";
println!("Number: {} String: {}", n, str);
なんかよく判らんマクロでいちいちびっくりさせなきゃいけないです。よく使うものが冗長だとゲンナリします。
変数を直接ぶち込むことも出来ませんしね。

let n = 10
echo n
普通出来るでしょこんなもん・・・。ところが Rust は出来ない。

let n = 10;
println!(n); <- エラー
println!("{}", n); <- 毎度これを書かされる
うざいっす。
868デフォルトの名無しさん
垢版 |
2021/08/22(日) 02:38:26.87ID:0Cz6ueFz
>>865
そんな寂しい事言わないでかまってよ〜(´;︵;`)

NimはC の関数を気軽に持ってくる
たった一行足すだけで C の関数を使うことが出来るようになります。

proc printf*(format: cstring) {.header: "<stdio.h>", importc: "printf", varargs.}
let n = 10
let str = "HOGE"
printf "Number: %d String: %s\n", n, str
どうですこれ?C の資産を気軽に使うことができるんです。SWIG 等の鬱陶しいラッパーを使うこと無くです。
Rust の場合はご多分にもれずラッパー行きで超絶面倒くさいです。比較用に書きたいんですが結構な文章量になるのでやめます。
869デフォルトの名無しさん
垢版 |
2021/08/22(日) 02:44:19.98ID:0Cz6ueFz
>>866
そんな寂しい事言わないでかまってよ〜(´;︵;`)

Nimはmut mut しなくて良い
Rust はまともな変数を使おうとすると mut mut しないといけません。デフォルトだと再代入できませんから。
普通再代入しまくりますよね?定数ライクに使いたい機会なんて殆どないですよね?なのに mut を毎度書かされます。

let n:int = 10
let mut m: int = 10
Nim ならこうですよ。

let n = 10 # immutable
var m = 10 # mutable
素敵。
870デフォルトの名無しさん
垢版 |
2021/08/22(日) 02:55:06.51ID:0Cz6ueFz
>>862

Nim所有者・借用なんてもんでイライラしない
 Rust には C のポインタが可愛く見えるレベルで高くそびえ立つ鉄壁の初心者ガード、悪夢の"所有者・借用"の概念が存在します。
プログラムに慣れた人間ですら混乱に陥れ、書いている最中に精神力と人生の貴重な時間をガンガン削ってくれる究極の嫌がらせです。

Rust は変数のコピーしちゃうと元のやつが使えなくなるクソ仕様なのです。書き手にメリットなんて一切無い。C++の悪しきメモリ管理の呪いを持ち込んで来てその中でもさらに悪い部分をデフォルトにした感じです。

struct Point {
x: i32,
y: i32,
}

fn Print(p: Point) {
println!("x = {}, y = {}", p.x, p.y);
}

fn main() {
let mut a: Point = Point{ x: 10, y: 15 };
Print(a);
// エラー!
println!("x = {}, y = {}", a.x, a.y);
}
Print(a) で1回コピーされているのでその後使うと死にます。ウソでしょ?と思うでしょ?ホントです。
そしてプリミティブ型ならOKと言う Java に似たダブスタの呪いもオマケで付いてます。

おかげさまで関数はほぼ全て明示的に参照渡しをするハメになります。
「だったらデフォルトそうしとけよ! & をイチイチ書かせんなやワレ!」と思わないのってある種の才能だと思います
871デフォルトの名無しさん
垢版 |
2021/08/22(日) 02:59:07.86ID:0Cz6ueFz
>>862

struct Point {
x: i32,
y: i32,
}

fn Print(p: &Point) {
println!("x = {}, y = {}", p.x, p.y);
}

fn main() {
let mut a: Point = Point{ x: 10, y: 15 };
Print(&a);
println!("x = {}, y = {}", a.x, a.y);
}
これだとまぁエラーにはなりません。が、参照だからといってこんなことやったら死にます。

fn Print(p: &Point) {
println!("x = {}, y = {}", p.x, p.y);
p.x = 10; <- die
}
イミュータブルだからですって。はぁ・・・。
872デフォルトの名無しさん
垢版 |
2021/08/22(日) 03:01:25.00ID:0Cz6ueFz
>>862

だからこう書けですって。

fn Print(p: &mut Point) {
println!("x = {}, y = {}", p.x, p.y);
p.x = 100;
}

fn main() {
let mut a: Point = Point{ x: 10, y: 15 };
Print(&mut a);
println!("x = {}, y = {}", a.x, a.y);
}
はい来た。mut mut mut mut mut mut mut mut mut ああぁぁああぁ〜〜〜!!!

なんでよく使う方を面倒臭くしたがるんですか、この言語を作っている方々は。

その他又貸しの呪いやらなにやら超盛り沢山ですし。もうね私とはセンスが全く合わないです。

ぬぅぅうぅうぉぉおぉおぁぁあぁあああ!!!!!Rustよ!もうお前には頼まん!malloc と free を俺によこせうぉるぅぁあ!!こんな訳のわからんものに付き合わされるんだったら自分でメモリ管理した方がマシだわ!!!

とよくみんな発狂しませんよね。我慢強いですね。馬鹿じゃないの。

とっても良い子である Nim にはこんな呪いある"ワケ"がないです。
873デフォルトの名無しさん
垢版 |
2021/08/22(日) 03:06:14.74ID:0Cz6ueFz
>>862

type Point = object
x: int
y: int

proc print(this: Point) =
echo "x = ", this.x, ", y = ", this.y

var p = Point(x: 10, y: 15)
p.print()
echo "x = ", p.x, ", y = ", p.y
まぁ普通はこうですよね・・・。Rust がぶっ飛んで異常なだけです。ありえないです。

ちなみに Nim の場合 print(p) と p.print() は書き方が違うだけで意味は同じです。
874デフォルトの名無しさん
垢版 |
2021/08/22(日) 03:09:40.85ID:0Cz6ueFz
>>862

参照で渡す場合はこうなります。

type Point = object
x: int
y: int

proc print(this: ref Point) =
echo "x = ", this.x, ", y = ", this.y
this.x = 100

var p = Point.new
p.x = 10
p.y = 15
p.print()
echo "x = ", p.x, ", y = ", p.y
new で Point object を作成すると参照のオブジェクトが出来ます。これを渡すために print 側の引数には ref をつけてあげます。new 関数でメンバに値を割り当てることは出来ないので後から渡してやります。

つっても上のやつはあくまで Rust と似せて書いたらこうなるよって話でこんな書き方しません。
875デフォルトの名無しさん
垢版 |
2021/08/22(日) 03:11:53.65ID:0Cz6ueFz
>>862

普通オブジェクトなんて参照だろ、って事で Nim では以下のように書くのが慣例化しています。

type
Point = ref PointObj
PointObj = object
x: int
y: int

proc print(this: Point) =
echo "x = ", this.x, ", y = ", this.y
this.x = 100

var p = Point(x: 10, y: 15)
p.print()
echo "x = ", p.x, ", y = ", p.y
オブジェクトとそのリファレンスを同時に定義して、通常使わない方のオブジェクト側にサフィックスをつけておくと、まぁ素のオブジェクトも作りたきゃ作れるし、って話です。

自分は正直リファレンスだけで良いので更に手を抜いてこう書きますけどね。

type
Point = ref object
x: int
y: int
876デフォルトの名無しさん
垢版 |
2021/08/22(日) 03:16:29.28ID:0Cz6ueFz
>>862

パターンマッチ?case でしょ?
Nim も case でそれっぽく書けます。

複式パターン
fn main() {
let x = 1;
match x {
1 | 2 => println!("1 | 2"),
3 => println!("3"),
_ => println!("other"),
}
}
let x = 1
case x
of 1, 2: echo "1 | 2"
of 3: echo "3"
else: echo "other"
877デフォルトの名無しさん
垢版 |
2021/08/22(日) 03:20:10.82ID:0Cz6ueFz
>>862

範囲
fn main() {
let x = 1;
match x {
1...5 => println!("1...5"),
_ => println!("other"),
};
}


let x = 1
case x
of 1..5: echo "1..5"
else: echo "other"
878デフォルトの名無しさん
垢版 |
2021/08/22(日) 03:23:05.87ID:0Cz6ueFz
>>862

case の返りを受け取る
fn main() {
let x = 1;
let s = match x {
1 => "one",
2 => "two",
_ => "other",
};
println!("{}", s)
}


let x = 1
let s = case x
of 1: "one"
of 2: "two"
else: "other"
echo s
879デフォルトの名無しさん
垢版 |
2021/08/22(日) 03:24:44.35ID:0Cz6ueFz
>>862

分配束縛
Nim は標準ではできませんが

https://github.com/andreaferretti/patty

を突っ込むことで可能です。
880デフォルトの名無しさん
垢版 |
2021/08/22(日) 03:26:55.98ID:0Cz6ueFz
>>862

仕様バグがない
Rust の以下の挙動は全く理解ができません。

fn main() {
let x = 'x';
let c = 'c';
match c {
// x: c c: c
x => println!("x: {} c: {}", x, c),
}
// x: x
println!("x: {}", x)
}
普通 x にマッチすると思わないでしょこれ。
さらにその直後 x が 'c' に変わってるとか予想だにしませんよ。
まぁ普通はこんな書き方しないと思いますがこんな調子ではどこでどうハマるか予測不可能です恐ろしすぎます。

Nim はこんな書き方そもそも出来ません。
881デフォルトの名無しさん
垢版 |
2021/08/22(日) 03:31:02.98ID:0Cz6ueFz
>>862

コンパイラがケチくさくない
nim c -r hoge
これで hoge.nim をコンパイルします。
拡張子なんて指定する必要ありません。
-r で実行もします。

Rust の場合

rustc hoge <- ダメ
コンパイルと同時に実行しようと思ったら

rustc hoge.rs && ./hoge
うーん・・・
882デフォルトの名無しさん
垢版 |
2021/08/22(日) 03:36:37.77ID:0Cz6ueFz
>>862

実行速度・メモリ使用量・ファイルサイズが小さい
Rust と比べて Nim の実効速度はどっこいかむしろ速いです。
Rust はこんだけイライラする書き方を強制されるにも関わらずたいして速くないとかもう哀れすぎます。

コンパイル後のファイルサイズは話にならないレベルで比べ物になりません。

fizzbuzz の例(FizzBuzz を無駄にベンチマークしてみた By Nim、golang、Rust、Crystal、その他 - 強まっていこう)で言うと

項目      Nim     Rust
実行速度  0.37s     0.44s
ファイルサイズ  82K     3.4M
メモリ      356K     900K
こんな感じです。
2021/08/22(日) 03:40:59.41ID:EcXIWh+x
>>882
無知がやるとそうなるわな
884デフォルトの名無しさん
垢版 |
2021/08/22(日) 08:37:49.63ID:0Cz6ueFz
>>883

>無知がやるとそうなるわな

バカ丸出し
Nimは標準実装されたnimコンパイラが強力なマクロで
最適化されたCのソースコードを吐き出して、Cコンパイラ
で極小バイナリまで生成するから、コンパイルするだけで
後はプログラマがする仕事が無いので怠けててもいい

Rustは標準実装されたコンパイラでコンパイルするだけでは
超巨大なバイナリを生成するので、最適化せれたチューニング
を施して小さなバイナリを生成しなければならないから
プログラマの仕事が増えて怠けられない
2021/08/22(日) 08:40:06.97ID:BRNN665g
>>884
仕組みすら理解してないのか
2021/08/22(日) 08:43:57.27ID:c6eQFYhO
>>880
それはブロックスコープといって多くの言語が備えておりプログラミングの基礎です
まさかNimには存在しないのですか?
2021/08/22(日) 08:57:00.52ID:QorwbXcj
rustスレでnim nim言ってる奴荒らしだろ
888デフォルトの名無しさん
垢版 |
2021/08/22(日) 09:00:12.62ID:0Cz6ueFz
>>862

マクロのシンタックスを別で覚える必要がない
Rust のマクロは構文が全く変わってしまいます。
そしてそれは脳が全力で受付を拒否する素敵な仕上がりとなっております。
公式で自ら「マクロベースのコードの欠点は、組み込みルールの少なさに
由来するそのコードの理解のしづらさです。」と言いのけちゃう代物で
「なんじゃそりゃ」と言う言葉しか出ません。

Nim は構文がそのまま使えます。なので強力なマクロを使いこなすための
障壁の低さは比べ物になりません。
2021/08/22(日) 09:19:59.80ID:k4RSCji3
次世代言語22 Go Nim Rust Swift Kotlin TypeScript
https://mevius.5ch.net/test/read.cgi/tech/1629590343/
2021/08/22(日) 09:21:24.81ID:k4RSCji3
nim
https://mevius.5ch.net/test/read.cgi/tech/1519896738/
2021/08/22(日) 09:49:19.77ID:sxhQ+hXZ
実際rustって色々リンクするから、最小バイナリでかいよな
でも、それで困ったことってあるか?
俺はない
2021/08/22(日) 09:53:06.17ID:DrnSGK6Q
>>891
それはリンクする状況にするからであってRustのせいではない
例えばRustを使って組み込みやWASM等でもバイナリでかいと思ってないよね
893デフォルトの名無しさん
垢版 |
2021/08/22(日) 10:05:41.39ID:qkR4Cuiq
Rustは他に比べれば最小のバイナリでしょ、コンパイラ/リンカーが長い年数を掛けて最適化されたCより大きいが。
一番不満なのが公式はビルドが速いというがそんなに早くない事だけ。それ以外は従来のC/C++(C++17/20/23
なんかを除く)より圧倒的に安全だし、明示的であるからこそタイプ量が多い。
Nimに比べて大きいというのはRustのコンパイラがまだCを吐き出してた頃から最適化されていないから、Nimと
いうかGCCやClangに比べ、ほんの少し大きくなる。リンクするものが大きければバイナリが大きくなるのは
当然でGoなんかはまさにそれでしょ、goroutineを共有ライブラリに押し込めることは出来ないから
2021/08/22(日) 10:06:16.71ID:sxhQ+hXZ
>>892
まあ、ユーザコード自体のサイズがでかいわけじゃないのは同意
895デフォルトの名無しさん
垢版 |
2021/08/22(日) 10:17:01.78ID:qkR4Cuiq
もう1つ不満がある事は、Rustならメモリーリークしないと言う奴がいる事、公式も明言してる通り
グローバルの循環参照を作成してしまえば簡単にリークするのに、意識高い系のコード書かないやつが
メモリーリークしないんだと他の言語も触ったことの無い初心者に力説する事。盛大にリークしてて
正常に動いてるプログラムを直すのは大変・・・
ま、これは言語のせいじゃないけどね、他は凄い良く出来てる、Linuxカーネルに採用されるような
他の言語(第3の言語)は当分出てこないだろうと思うほど
2021/08/22(日) 10:35:44.30ID:FTtcJrTl
Rustのメモリ安全性は、メモリリークしない、ではないからな。
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

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