Rust プログラミング言語が登場したのは何年ですか? どこから始めるべきか · Rust プログラミング言語。 プログラミング言語の構文

私は Rust を初めて使用しましたが、すぐに私のお気に入りのプログラミング言語になりました。 Rust で小さなプロジェクトを書くのは通常、人間工学的ではなく、時間がかかります (少なくとも私がハンドルを握っている場合) が、プログラム設計についての私の考え方に課題を与えます。 新しいことを学ぶと、コンパイラとの戦いは少なくなります。

Rust コミュニティは最近、Tokio ライブラリの形で実装された非同期 I/O に多くの努力を注いでいます。 それは素晴らしいことです。

コミュニティ メンバーの多くは、Web サーバーやそれに関連した作業をしたことがない人たちで、私たちが何を達成したいのかが明確ではありません。 1.0 の時代にこれらのことが議論されたとき、私もこれまでにそれを扱ったことがなく、それについて漠然と考えていました。

  • それは何ですか - 非同期I/O?
  • コルーチンとは何ですか? コルーチン )?
  • 軽量スレッドとは( 軽量スレッド )?
  • 先物とは何ですか?( 先物 )?

  • それらはどのように組み合わされるのでしょうか?

フィードをダウンロードする小さなプログラムの書き方を紹介します ( ) JSON 形式で、メモのリストを解析し、フォーマットされた形式でコンソールに表示します。

私たちの場合、すべてが非常に簡潔なコードになりました。 どうやって? カットの下を見てください。

unsafe キーワードは、Rust 言語の設計に不可欠な部分です。 馴染みのない人のために説明すると、unsafe は、簡単に言えば、型チェックをバイパスする方法であるキーワードです( 型チェック) さび。

多くの人は、安全でないキーワードの存在に最初は驚きます。 確かに、メモリエラーによってプログラムがクラッシュしないのはRustの機能ではないでしょうか? これが本当なら、なぜ型システムをバイパスする簡単な方法があるのでしょうか? これは言語設計上の欠陥のように思えるかもしれません。

それでも、私の意見では、安全でないことはデメリットではありません。 実際、それは言語の重要な部分です。 unsafe は一種のエスケープバルブとして機能します。つまり、単純なケースでは型システムを使用できますが、コード内で使用したいあらゆる種類の巧妙なトリックも許可されます。 これらの手法 (安全でないコード) を安全な外部抽象化の背後に隠すことのみを要求します。

このnoteでは、unsafeというキーワードと、限定された「unsafe」の考え方を紹介します。 実はこれは、少し後に書きたいと思っているメモの前兆です。 彼女は、安全でないコードで実行できることと実行できないことを指定する Rust のメモリ モデルについて説明します。

Rust の初心者として、私は文字列を表現するさまざまな方法について混乱しました。 Rust 言語に関する本には、「参照と借用」という章があり、例では 3 つの異なるタイプの文字列変数 (String、&String、および &str) が使用されています。

str と String の違いから始めましょう。String は拡張可能なヒープ割り当てデータ構造ですが、str は不変の固定長文字列です。 どこかで念頭に置いて。

多くのプログラマーは、オブジェクト指向言語でプログラミングする方法をすでに知っています。 Rust は古典的なオブジェクト指向言語ではありませんが、基本的な OOP ツールを使用できます。

この記事では、Rust で OOP スタイルでプログラミングする方法を見ていきます。 これを例を使用して実行します。トレーニング タスクでクラスの階層を構築します。

私たちの仕事は幾何学的形状を扱うことです。 それらをテキスト形式で画面に表示し、面積を計算します。 私たちの形状のセットは、長方形、正方形、楕円、円です。

Rust は、他の多くの一般的な言語とは多少異なるエレガントな言語です。 たとえば、クラスと継承を使用する代わりに、Rust は独自の特性ベースの型システムを提供します。 しかし、Rust を使い始めたプログラマの多くは (私と同じように)、一般的に受け入れられているデザイン パターンに慣れていないのではないかと思います。

今回はデザインパターンについてお話したいと思います 新しいタイプ(newtype)、および型変換に役立つ From および Into トレイトも含まれます。

私は最近、デザインパターンとプログラミングで使用するテクニックについてよく考えています。 プロジェクトの探索を開始し、これまでに何度も見た馴染みのあるパターンやスタイルを確認するのは本当に素晴らしいことです。 これによりプロジェクトの理解が容易になり、作業のスピードアップが可能になります。

新しいプロジェクトに取り組んでいるときに、前のプロジェクトで行ったのと同じ方法で何かを行う必要があることに気づくことがあります。 それは機能やライブラリの一部ではない可能性があり、きちんとしたマクロや小さなコンテナにまとめることができないものである可能性があります。 それは単に問題をうまく解決する設計パターンまたは構造コンセプトである可能性があります。

このような問題によく適用される興味深いパターンの 1 つは、「有限状態マシン」です。 少し時間をかけて、このフレーズが正確に何を意味するのか、そしてなぜこれがそれほど興味深いのかを理解することをお勧めします。

以下は、Rust プログラミング言語での移動、コピー、借用を図で説明したものです。 基本的に、これらの概念は Rust に固有のものであり、初心者にとっては障害となることがよくあります。

混乱を避けるために、テキストは最小限に抑えるようにしました。 このノートはさまざまなチュートリアルに代わるものではなく、視覚的な情報の方が認識しやすいと考える人のためにのみ作成されています。 Rust を学び始めたばかりで、これらのチャートが役立つと思われる場合は、概念を強化するためにコードに同様のチャートをマークすることをお勧めします。

ペアノ数を使用した自然数演算の実装は、プログラミングを教える際によく行われるタスクです。 Rustで実装できないかなぁと考えていました。

したがって、私のタスクは、型チェックを使用して自然数を書き留めて加算することです。

Wikipediaによると、「ペアノの公理とは、19世紀にイタリアの数学者ジュゼッペ・ペアノによって導入された、自然数の公理系の一つである。」とあります。

そのうちの 2 つに興味があります。自然数を入力して使用できるものです。

  • 1は自然数です
  • 自然数の次の数も自然数です。

以下を使用して、Rust でそのまま書いてみましょう。

1 2 3 4 enum Nat(Zero, Succ(Nat))

Nat は 0 または次の自然数です。

コメント: futures-rs プロジェクトが再編成され、多くのものが名前変更されました。 可能な場合は、リンクが更新されています。

先物取引を始める

このドキュメントは、フューチャーとスレッドのゼロコスト実装を提供する、Rust のフューチャー プログラミング言語コンテナーを探索するのに役立ちます。 Future は、C++、Java、Scala など、他の多くのプログラミング言語で使用でき、Future コンテナはこれらの言語のライブラリからインスピレーションを得ています。 ただし、これは人間工学に基づいており、Rust に固有のゼロコスト抽象化の哲学にも準拠しています。つまり、フューチャーの作成と構成にメモリの割り当ては必要なく、フューチャーを管理するタスクに必要な割り当ては 1 つだけです。 Future は、Rust における非同期で構成可能な高性能 I/O の基盤となることを目的としており、初期のパフォーマンス測定では、Future 上に構築された単純な HTTP サーバーが実際に高速であることが示されています。

このドキュメントはいくつかのセクションに分かれています。

  • "こんにちは世界!";
  • 未来型。
  • ストリーム型。
  • 特定の先物とストリーム(Stream);
  • リターン先物。
  • 課題と将来。
  • ローカルタスクデータ。

コメント: futures-rs プロジェクトが再編成され、多くのものが名前変更されました。 可能な場合は、リンクが更新されています。

Rust エコシステムにおける大きなギャップの 1 つは、高速性と効率性でした 非同期I/O。 mio ライブラリの強固な基盤はありますが、それは非常に低レベルであり、ステート マシンを手動で作成し、コールバックを操作する必要があります。

私たちは、人間工学に優れた、よりハイエンドなものを望んでいますが、それは優れた機能を備えています。 構成可能性、連携して動作する非同期抽象化のエコシステムをサポートします。 非常に聞き覚えのある話です。実装でも同じ目標が追求されました。 先物(または約束) 形式で糖衣構文をサポートする多くの言語 非同期/待機頂上で。

プロセッサーによってサポートされるプリミティブ整数型は、私たちが実際に操作することに慣れている無限の整数セットの限定された近似です。 この限定された表現は、「実数」 (例: 255_u8 + 1 == 0 ) と常に一致するとは限りません。 多くの場合、プログラマーはこの違いを忘れるため、簡単にバグが発生する可能性があります。

Rust はバグを防ぐことを目的としたプログラミング言語で、最も危険なエラーであるメモリ エラーを防ぐことに重点を置いていますが、プログラマが他の問題、つまり無視されるバグや、後で説明するように整数のオーバーフローを回避できるようにすることにも努めています。

アイアンについて少し

Iron は、Rust プログラミング言語で書かれた高レベルの Web フレームワークで、別のよく知られたライブラリである hyper 上に構築されています。 Iron は、Rust が提供するすべての利点を活用するように設計されています。 Iron は、カーネル内での操作のブロックを回避しようとします。

哲学

Iron は、可能な限り拡張可能であるという原則に基づいて構築されています。 彼は、独自の機能を拡張するための概念を導入しました。

  • 「中間」特性 - リクエスト処理でエンドツーエンドの機能を実装するために使用されます。
  • 修飾子 - 最も人間工学に基づいた方法でリクエストとレスポンスを変更するために使用されます。

この記事を読み進めるうちに、修飾子と中間型の基本部分について理解できるようになります。

プロジェクトの作成

まず、次のコマンドを使用して Cargo を使用してプロジェクトを作成しましょう。

コンパイル後、対応する実行可能ファイルを取得します。

1 2 3 $rusc hello.rs $ du -h hello 632K hello

単純な印刷で 632 キロバイト?! RustはC/C++に代わる可能性を秘めたシステム言語として位置づけられていますね。 では、最も近い競合他社で同様のプログラムをテストしてみてはいかがでしょうか?

私たちの環境では、ガベージ コレクターの利点の 1 つは、高性能のロックフリーのデータ構造を開発しやすいことであると広く信じられています。 手動でメモリ管理を行うのは簡単ではありませんが、GC を使用するとこの問題を簡単に解決できます。

この投稿では、Rust を使用して、次のような同時データ構造用のメモリ管理 API を構築できることを示します。

  • GC と同様に、ロックフリーのデータ構造を実装できるようになります。
  • メモリ管理スキームの悪用に対する静的な保護を作成します。
  • GC と同等のオーバーヘッドが発生します (さらに予測可能です)。

以下に示すテストでは、Rust はロックフリー キューの Java 実装を簡単に上回り、Rust 実装自体は簡単に作成できます。

新しい Crossbeam ライブラリにエポックベースのメモリ再利用スキームを実装しました。これで、データ構造で使用できるようになりました。 この投稿では、ロックフリーのデータ構造、エポック アルゴリズム、および内部 Rust API について説明します。

メモリ アクセス エラーとメモリ リークは、最も注目される 2 つのカテゴリのエラーであるため、その発生を防止または少なくとも軽減するために多大な努力が払われています。 これらの名前は類似性を示唆していますが、ある意味では正反対であり、1 つの問題を解決しても 2 つ目の問題が解決されるわけではありません。 マネージ言語の普及は、この考えを裏付けています。マネージ言語は、メモリを解放する作業を引き継ぐことで、一部のメモリ アクセス エラーを防ぎます。

簡単に言えば: メモリ アクセス違反は不正なデータによる何らかのアクションであり、メモリ リークは 不在正しいデータを使用した特定のアクション。 表形式の場合:

プログラミング言語の学習についていくつか思うことがあります。

まず第一に、私たちは間違った方法で取り組んでいます。 きっとあなたも同じように感じたことがあると思います。 あなたは新しい言語を学ぼうとしていますが、すべてがどのように機能するのかよくわかりません。 ある場所ではある構文が使用され、別の場所では別の構文が使用されるのはなぜですか? こうした奇妙なことはすべて煩わしく、最終的にはいつもの言語に戻ります。

私たちの言語に対する認識は、私たちに残酷な冗談を言っていると思います。 新しい言語について最後に話し合ったときのことを思い出してください。 誰かがそれについて言及し、他の誰かがその速度、構文、または利用可能な Web フレームワークについて質問しました。

これは車について議論するのとよく似ています。 新しいUAZ Rybakについて聞いたことがありますか? 彼はどのくらい速いですか? 車で湖を越えてもいいですか?

私たちが言語について同じように話すときは、それらが交換可能であることを意味します。 車のように。 私がラーダ・サランスクの運転方法を知っていれば、UAZ ルイバクも問題なく運転できます。 唯一の違いは速度とダッシュボードですよね?

しかし、PHP 自動車がどのようなものになるかを想像してみてください。 さて、Lisp 車がどれほど違うかを想像してみてください。 あるボタンから別のボタンに切り替えるには、どのボタンが暖房を制御するかを知るだけでは十分ではありません。

注: この記事は、読者が Rust FFI (翻訳)、エンディアン、および ioctl に精通していることを前提としています。

C コードのバインディングを作成する場合、必然的に共用体を含む構造に遭遇します。 Rust には結合のサポートが組み込まれていないため、独自に戦略を立てる必要があります。 C では、共用体は、異なる型のデータを同じメモリ領域に格納する型です。 連結を支持する理由は数多くあります。たとえば、整数のバイナリ表現と浮動小数点数の間の変換、擬似多相性の実装、ビットへの直接アクセスなどです。 擬似ポリモーフィズムに焦点を当てます。


「Rust 言語の批判と C/C++ が決して死なない理由」という記事がとても気に入りました。 私たちは記事を英語に翻訳し、ブログでも公開することを著者に提案しました。 彼も同意してくれたので、この記事をロシア語と英語で紹介できることをうれしく思います。 元の記事が見つかりました。

原文を掲載します(本文はロシア語)。 この記事は著者の同意を得てブログに掲載されました。

注: 以下では、Rust が高速で安全な言語を作成する試みであると仮定しています。 結局のところ、Mozilla の人たちはブラウザ エンジン開発ツールとしてそれを作成しました。 これが単なる安全な言語である場合、何か奇妙な結果が得られます。 すでに十数種類の安全な言語が存在しており、誰もが自分の好みのものを見つけるでしょう。 そして、目的が C++ を置き換えることではない場合、(1) なぜその言語で安全でないサブセットが作成されるのでしょうか? (2) なぜ言語から軽量ストリームを削除する必要があったのですか? 便利ではないでしょうか? 言い換えれば、この場合、何が起こっているのかはまったく意味がありません。

もしあなたが linux.org.ru フォーラムを読んでいるなら、これはこのスレッドで議論された、Rust を好まない純粋に技術的な 10 の理由のリストではないことに注意してください。 との Skype でのディスカッションからわかるように、 親愛なる同志 @sum3rman、これらの理由をどのように「技術的」に考慮すべきかについては、複数の意見があります。 全体として、私はくだらないリストを作成しましたが、おそらくその中から最も興味深い点のいくつかを引用する危険を冒すことになります。 実際、ここには単純で技術的ではない理由がたくさんあります。

C/C++ が近い将来にどこにも行かないという事実は、冷静な考えを持つ人には明らかです。 ほとんどすべてのデスクトップ アプリケーション、オペレーティング システム カーネル、コンパイラ、ゲームおよびブラウザ エンジン、仮想マシン、データベース、アーカイバ、オーディオおよびビデオ コーデック、その他の大量の C ベース ライブラリなどを書き直す人は誰もいません。 これは、非常に多くの高速で、デバッグされ、時間をかけてテストされたコードです。 それを書き直すのは非常に高価で、リスクが高く、正直に言うと、最も頑固な Rust ファンだけの歪んだ意識の中でのみ意味をなすものです。C/C++ プログラマーに対する需要は、非常に長い間大きくなっており、今後も大きくなるでしょう。

では、新しいコードを記述するときに Rust を使用するのはどうでしょうか?

これが「より正確な」C/C++ を作成する最初の試みではないことを覚えておいてください。 たとえば、言語 D を考えてみましょう。これは 2001 年に登場した、非常に優れた言語です。 欠員はなく、通常の開発ツールもなく、特に際立った成功事例もありません。 OpenMW プロジェクトはもともと D で書かれていましたが、突然、完全に C++ で書き直すことにしました。 開発者が認めているように、「素晴らしいプロジェクトです。喜んで貢献させていただきますが、この愚かな D については知りませんし、知りたくありません」という形式の手紙をたくさん受け取りました。 Wikipedia によると、D に加えて、Vala、Cyclone、Limbo、BitC など、C++ をある程度廃止しようとする他の多くの試みがあったと報告されています。 そのような言語について聞いたことがある人はどれだけいるでしょうか?

私たちは歴史から学ぶ時期に来ていると思います。 少なくとも通常の開発ツールを見せ、いくつかの成功事例を語り、近くに住んでいるその言語を使う十数人のプログラマーを見せてやるまでは、まともな人間は一人もプロジェクトに新しい言語を持ち込もうとはしないだろう。 おそらく、最年少のプログラマーを除いて、プログラマーは、通常の開発ツール (Racer のような工芸品ではない) や数万の既成ライブラリ ( 「実験的」「不安定」などではありません)、いくつかの成功事例を語り、自分の都市で十数件の空き求人を示すのではありません。 鶏と卵の問題。 非常にまれに、この問題が首尾よく解決されることもあります (条件付きで Scala が例として挙げられます)。これは主に、何らかの理由で、言語。

すでに述べたように、技術的以外の理由だけでも十分です。 しかし、純粋に好奇心から、彼らがそこにいないことを少し想像してみましょう。 ではRustで書かない理由はないのでしょうか? これも少なくとも非常に大きな問題であることがわかりました。

C/C++ はさまざまな点で批判されています。 ちなみに、批判は、遠くからでも本番環境の C++ コードさえ見たことがない人によって行われることが非常に多いです。 この問題は次のように簡潔かつ明確に説明できます。C++ は非常に高速です (また、メモリやバッテリー充電などをあまり要求しません) が、配列の境界を越えたり、誤ってアクセスしたりする可能性があるという意味で安全ではありません。メモリの一部を解放するなど、さらに続きます。 かつて、この問題により、Java、C#、Python などの安全な言語が大量に出現しました。 しかし、これらの言語は C++ に比べてリソースを多く必要とし、ガベージ コレクション中に必然的に世界が停止するなど、他の欠点があることが判明しました。 したがって、人々は C++ と同じくらい高速でありながら安全な言語を作成するという課題に苦労しています。 そのような言語の 1 つが Rust です。

Rust は確かに安全ですが、残念ながら高速とは程遠いです。 この記事の執筆時点では、Rust の速度は Java、Go、Haskell と同等です。

私は、時間の経過とともに何らかの形でオーバークロックされることを心から願っていますが、それまでは、速度とセキュリティのトレードオフの点で、Scala や Go よりもそれほど興味深いものはありません。 そもそも言語を高速かつ安全にすることが可能なのか、それとも配列境界の超過の継続的なチェックや C ライブラリへのバインディングの安全なバインディングなどにより、言語が自動的に C/C よりも 2 倍遅くなるのかどうかという疑問はまだ未解決です。 C++。

Rust を安全にするものは何でしょうか? 簡単に言うと、静的コードアナライザーが組み込まれた言語です。 メモリ管理に関連するエラーだけでなく、マルチスレッドに関するエラーも含め、すべての典型的な C++ エラーを捕捉する、非常に優れた静的アナライザーです。 可変オブジェクトへのリンクをチャネル経由で別のスレッドに渡し、このリンクを自分で使用しようとしましたが、コンパイルできませんでした。 本当にかっこいいですね。

コードの 10% だけが 90% の確率で実行されるという議論がよく行われます (これは、私の理解する限り、純粋に経験則です。このテーマに関する厳密な調査はすぐには見つかりませんでした)。 したがって、プログラムの大部分は安全な Rust で書くことができますが、ホット コードの 10% は安全でないサブセットで書かれており、現在の Rust 実装の遅さは実際には問題ではありません。 わかりましたが、Rust はまったく必要ないことがわかりました。コードの 90% は Go で、10% は C で書くことができるからです。 プログラムの 100% が 1 つの言語で記述できるという理由だけで Rust を使用するのは、特効薬を求める人や常識外の理論家だけです。 実際には、これらは同じ言語の 2 つの方言であり、Java と C、または Go と C の組み合わせとそれほど違いはありません。

実際、10:90の法則はまだ嘘です。 このロジックにより、WebKit の 90%、VirtualBox の 90%、または GCC の 90% を Java で書き換えて、同じ結果を得ることができます。 明らかにそうではありません。 多くのプログラムでこの態度が大きく異なるということが重要ではないとしても、自分の手に注意してください。 プログラム全体が安全でない C/C++ で書かれており、その実行時間は相対的に 0.9*1 (ホット コードのごく一部) + 0.1*1 (大量のコールド コード) = 1 に等しいとします。これを、Si に挿入を含む安全な言語のプログラムと比較すると、0.9*1 + 0.1*2 = 1.1、およそ 10% の差です。 これは多いですか、それとも少ないですか? 規模によって異なります。 Google の場合、たとえ数パーセントでも数百万ドルを節約できます (論文のポイント 5「活用」を参照)。 あるいは、次の更新で JVM が突然 10% 多くのリソースを必要とし始めると想像してください。 利子をアメリカのお金に換算した後に得られる数字にゼロが何個あるのか、推測するのも怖いです。 C および C++ が使用されるタスクでは 10% は多くなります。

私たちは「時期尚早の最適化は諸悪の根源」を呪文のように繰り返します。 しかし、文字通りに受け取るなら、どこでもクイックソートの代わりにバブルソートを使用しましょう。 この特定の場所でプログラムの速度が低下するかどうかはわかりません。 より効率的なアトミックをすぐに使用できる場合、一部のアクションの通常のカウンターをアクターまたはトランザクション メモリでラップすることに何の意味があるのでしょうか? そして一般に、些細なケースでは、すべて、すべて、すべての変数を強制的に初期化したり、大量の追加チェックを実行したりすることには意味がありません。 最終的には 10% の加速ではなく、2 ~ 5% の加速にしましょう。 これも、数分間余分に考えるだけであれば、まったく悪いことではありません。 そして、すでにわかったように、C/C++ で解決される問題では、これが大きな違いとなる可能性があります。 では、ホットスポットを見つけてコード (おそらく大量のコード) を書き直し、それが本当に高速であることを証明する方が、事前にパフォーマンスについて考えるよりも簡単だと誰が言ったのでしょうか?

速度とセキュリティのトレードオフの問題を無視すると、言語自体の設計にも疑問が生じます。 特に 5 種類のポインタについて。 一方で、プログラマが変数がスタック上またはヒープ上のどこに配置されているか、および複数のスレッドが変数を同時に処理できるかどうかを考慮する場合、これは悪いことではありません。 しかし一方で、プログラムを書いていて、変数がスタック上ではなくヒープ上に存在する必要があることが判明したと想像してください。 Box を使用するためにすべてを書き換えます。 本当に必要なのは Rc または Arc であることがわかりました。 また書き直すんですね。 そして、それをスタック上の通常の変数に再度書き換えます。 これらすべてを、通常の IDE が手元になくても可能です。 そして、通常のゲームは役に立ちません。 まあ、あるいは単に「Vec」のスタイルで >>>" こんにちは、Java! しかし、最も悲しいことは、コンパイラはすべての変数の有効期間をすでに知っており、これらすべての Box や Arc などを自動的に出力できることです。しかし、何らかの理由で、作業のこの部分は転送されます。 val (3000 年代に!) を記述し、必要に応じて Box または Rc を明示的に指定できれば、はるかに便利です。この意味で、Rust 開発者はアイデア全体を台無しにしました。

このため、特にRustの適用範囲は大幅に狭まってしまいます。 正気の人間であれば、そのような言語で Web やサーバーサイドを作成する人はいないでしょう。 特に、JVM では同じ言語に比べて大きな利点が得られないことを考慮すると、 そして、これらのタスクでは、通常の軽量スレッド (Future ではなく) を使用した Go の方がはるかに魅力的に見えます。 未来の場合、足を撃たれないようにするには、やはり仕事の仕方を学ぶ必要があり、「安全な言葉遣い」と言います。 はい、これらの言語には独自の特徴があり、同じように世界を動かしますが、この問題はマイクロサービスに切り込むことと他の技術の両方で解決できます。 そしてそうです、Rust を JavaScript に翻訳したり、AWS でレイアウトするためにスクリプトを記述したり、MongoDB のクエリ言語として使用したりする人は誰もいません。 彼らが Android 用に書く可能性も低いですが、別の理由で、アーキテクチャは複数あり、JVM を使用するとはるかに簡単になります。 もしあなたが突然、Rust が「あらゆるタスクに適している」と思ったのなら、私はあなたを失望させなければなりません。

さて、ヒープへ:

  • マクロは、通常の例外の欠如によって引き起こされる過剰な冗長性を補うものです。 メタプログラミングの問題についてはすでに書きましたが、特にメタプログラミングの問題が原因で、Rust 用の通常の IDE が登場する可能性は低いです。 よくわかりませんが、Rust のマクロには名前空間さえないようです。
  • 人々は愚かであり、Cargo は Crates.io をバイパスして git リポジトリから直接パッケージをプルすることを本当に奨励しています。 その結果、Rabar を使用した Erlang の世界と同じようにパッケージが混乱する可能性が高く、ちなみに Go の世界でも同様の状況になるようです。
  • 多くの新しい言語と同様に、Rust も簡素化の道を歩みます。 一般的に、そこに通常の継承や例外がない理由は理解できますが、誰かが私にそのようなことを決定するという事実自体が不快な後味を残します。 C++ は、何を使用し、何を使用しないのかという点でプログラマを制限しません。
  • もし私たちが単純化の道をたどるつもりなら、言語のこれらの拡張機能をすべて放棄することになるでしょう。 そして、Haskell の世界と同様に、各プログラマーが自分の方言で書いていることが判明しました。
  • スマート ポインターは、どちらかといえば無料とは程遠く、ガベージ コレクション時間は予測できません。 一部のスレッドは、非常に深いデータ構造を突然解放する栄誉を手に入れました。 彼がデッドリンクの迷宮を歩いている間に、彼に依存しているスレッドは辛抱強く愚かになっていきます。 同じ問題が小さなヒープを持つ Erlang にも存在し、私自身も何度か観察しました。 スマート ポインターには、同様のメモリの断片化とリークという独自の問題があります。 サイクル構造のウィキポインターを忘れてしまいましたが、それだけです。 そしてこれは安全であると主張する言語で書かれています。 予測可能な GC 時間を必要とする場合は、負荷時のアプリケーションの動作を調査し、GC 時間が適切でない場合はアクションを実行する (同じオブジェクト プールを記憶する) か、メモリを手動で管理します。
  • Rustのセマンティクスの厳密な説明を見た人はいますか? 少なくともメモリモデルはありますか? また、私にとっては、プログラムの「正しさを証明する」「安全な」言語であり、実際にソースコードを 10 通りの方法で解釈できます。
  • もう一度思い出さずにはいられないのですが、 ほとんどの場合、問題はテクノロジーではなく人にあります。。 C++ コードが悪くなったり、Java が突然遅くなったりする場合、それはテクノロジーが悪いからではなく、その使用方法を正しく学習していないからです。 Rust にも不満があるでしょうが、その理由は異なります。 もっと人気のあるツールの使い方や使い方を学ぶのは簡単ではないでしょうか?

一般的に、今後 5 年間、私は Rust よりも C/C++ の学習に時間を投資したいと考えています。 C++ - これは業界標準です。 30 年以上にわたって、さまざまな問題がこの言語で解決さ​​れてきました。 そして、Rust やそれに類するものは、未来が曖昧な理解できないおもちゃです。 少なくとも 2000 年代から C++ の死が差し迫っているという話題がありましたが、C/C++ での記述はこの時期から始まっています。 まったく逆です。 そして、言語が発展しており (C++11、C++14)、その言語用の新しいツールが登場しており (CLion と Clang を思い出してください)、それに対応する人材の欠員が単にたくさんあることがわかります。

C++ プログラマーはいつでも、まともな給与以上の仕事を簡単に見つけることができ、必要に応じてすぐに Rust で再トレーニングすることができます。 その逆は非常に疑わしいです。 ところで、新しい職場を選ぶとき、言語は決して唯一の要素ではなく、決定的な要素ではありません。 さらに、経験豊富な C/C++ プログラマーは、PostgreSQL ソース コードや Linux カーネルを簡単に掘り下げ、強力な最新の開発ツールを使用でき、また、自由に使える書籍や記事 (たとえば、OpenGL に関するもの) をたくさん持っています。

時間と健康に気をつけてください。思っているほど時間と健康はありません。



現在、Rust 構文は、コンパイラーに付属の構文ファイルを使用して vim および emacs でサポートされています。
人気の専用エディタ Sublime Text 2 や無料エディタ Kate の構文パッケージもあります。 IDE ではまだ Rust がサポートされていません。 デバッガのサポートもないようです。

次のユーティリティは、rustc コンパイラに付属しています。
> ラストドック- Doxygen のようなソース コードからドキュメントを自動的に生成するユーティリティ。
> 錆びた- 追加のパッケージやライブラリを簡単にインストールできるパッケージ マネージャー。
> 錆びた- いわゆる REPL ユーティリティ (read-eval-print-loop)。 これは本質的には、コマンド ラインから Rust 式を取得し、それを内部 LLVM 表現にコンパイルし、実行して、結果を出力するテスト インタプリタです。
> さび- パラメータに応じて他のユーティリティまたはコンパイラを起動するユニバーサル ユーティリティ。 私にとっては決してうまくいきませんでした。

この言語に関する利用可能なドキュメントはすべて、公式 Web サイト www.rust-lang.org に収集されています。 詳細なマニュアル (http://static.rust-lang.org/doc/tutorial.html) があります。これは、構文、メモリ モデル、ランタイム システムなどのすべてのニュアンスに関する包括的な正式なドキュメントと、組み込みコア ライブラリと標準ライブラリ std。 すべてのドキュメントは英語です。 ロシア語の最新資料はなく、既存のレビュー記事のいくつかはすでに非常に時代遅れです。

イデオロギーと構文


Rust は C に似た言語で、中括弧を使用してコードのブロックを区切ります。 この言語は「マルチパラダイム」です。 命令型手続き型、オブジェクト指向型、同時実行型、または関数型の方法でコードを作成できます。 Rust は、サポートされているプラ​​ットフォーム (バックエンドとして LLVM を使用) 上でネイティブ バイナリ コードにコンパイルします。 理論的には、Rust コードは C/C++ コードと同じくらい高速である必要があります。 Rust はシステム言語として位置付けられていますが、「真の」システム言語 C、C++、D のようなアセンブリ コード ブロックのサポートは組み込まれていません。

Rust のメモリ モデルは本質的に、null ポインタやダングリング ポインタ、バッファ オーバーフローを許可しません。 1 つのコード スレッド内でのみ機能するオプションのガベージ コレクターがあります。 この言語には、軽量のマルチタスクと、メッセージングを使用したスレッド間の通信のサポートが組み込まれています。 Rustには共有メモリはまったく存在しません。 すべての変数はスタック変数、特定のスレッドのヒープ変数、およびいわゆる「交換」ヒープ変数に分割されます。これらはすべてのスレッドで読み取ることができますが、変更することはできません。 これにより、マルチスレッド プログラミングの悩みの種と考えられているデッドロックが自動的に排除されます。 この言語の ABI は C と互換性があるため、追加のラッパーなしで Rust プログラムを C で書かれたライブラリにリンクできます。 低レベルのシステム プログラミングのニーズに対応し、C との互換性を確保するために、この言語にはポインターの正確性をチェックしない特別な「安全でない」モードがあります。 そのイデオロギーでは、Rust は Go 言語に最も近いです。 Go と同様に、マルチスレッド プログラミングの単純さと大規模なアプリケーションの開発速度が主に重視されており、構文も珍しく、いくつかの場所でやや驚くべきものになります。 同時に、Rust は Go ほどミニマルではなく、システム言語であると主張しています。

Rust の構文は主に C と C++ から借用されており、Go、C#、Haskell、Python、Ruby からのアイデアがいくつか組み込まれています。 この言語の構文を徹底的に説明するつもりはありませんが、最も興味深い概念のみに焦点を当てます。

Rust は人気を集めていますが、多くの人はまだその価値と機能を理解していません。 Rust プログラミング言語の主な利点について説明します。

Rustと他の言語の共通点は何ですか?

以前はすべての言語が信頼性かパフォーマンスのどちらかを選択していたため、上記の定義は信じがたいものであり、非現実的な記述のように思えます。

高速性の顕著な代表例は高速ですが、割り当てられたメモリやリモート サーバーへの誤ったアクセスが原因でエラーが頻繁に発生することは誰もが知っており、作業結果の予測不可能な出力については言うまでもありません。 複数の書き込みスレッドがあるため、結果を予測することが困難なことがよくあります。

信頼性に対する偏見は言語によって最もよく示されます ハスケル、本質的にコンパイルされており、高いセキュリティ パフォーマンスを提供します。 コンパイルできるものはすべて正しく動作します。 主な欠点- これはパフォーマンスが低いため、高速な書き込みが必要なプロジェクトを想像するのは困難です。 ハスケル.

中立の位置、一定のバランスが残りの部分によって占められます。 それらでは、バイアスが実用化されます。

さび最高の機能を組み込んだ C++そして ハスケル、他の競合他社よりも十分な実用性と機能性を維持することができました。

Rust言語の美しさは何ですか?

Rust の魔法の機能は、コンパイルの基本と所有者エンティティ情報 ( 所有者)、一時的にデバッグしているだけか、プロジェクトを引き継いだプログラマーについて ( 可変借用)、および通常のビューアについて( 不変借用).

プログラミングするとき ジャワまたは C++、データの種類は多少異なりますが、この情報をメモリに保持する必要があります。 で さびこれは言語構造を使用して実装されます。この情報により、コンパイラーが ID を確立し、動作モデルを正しく選択することが容易になります。 コンパイラーを使用すると、コードの実行中に発生する可能性のある一般的な問題を確実に排除できます。

この言語には少し異なるアプローチが必要です。 異例にもかかわらず、このアルゴリズムは非常に明白で効果的です。 ここで、言語の基本を定義します。これは、学習を開始すると行き詰まりにつながる可能性があります。

  1. 継承システムは完全に排除され、特別な構造と能力がそれを置き換えるために使用されます。
  2. ポインタは、追加の保護の対象ではないコード内、つまり unsafe() 関数内にのみ存在します。 これらを置き換えるために、安全なコードは、既存のオブジェクトへの正しいポインターを提供する参照を使用します。
  3. リンクが静的で、特定の要素 (たとえば、 immutableborrow = &Object ) を指している場合、リンクが終了するまで、ユーザーはそのリンクを変更できません。
  4. 変更される可変のborrow = &mut Objectリンクがある場合、リンクの存続期間中、他のユーザーはコンテンツを読み取ることができません。
  5. 開発者は Mac および *nix プラットフォームに焦点を当てており、そのためシステム上で動作します。 ウィンドウズ GNU 環境を使用した場合のみ可能です。

対象読者は非常に重要であり、Rust 言語にはかなり活発なコミュニティがあり、コミュニケーションとトレーニングの発達したシステムがあります。 IRC チャンネルまたは Reddit にアクセスすることをお勧めします。 今日に至るまで、それはすでに書かれており、それらのほとんどはまだ継続的に開発されており、そのプロジェクトは GitHub で見つけることができます。

この言語は、グラフィックスやゲームを作成する道をたどった開発者の間で最も人気があります。 本格的なオペレーティングシステムを作成する開発も行われていますが、まだ開発中です。 近い将来、クライアント プログラムや Web サーバーを作成できる可能性があります。 上記のタスクはすべて完全に Rust の機能内にあります。

主な、そしておそらく唯一の欠点は、その過度に活発な開発です。 新しいバージョンがリリースされると、構文が多少変更されるため、新しい機能に適応するために動作と開発のロジックを定期的に変更する必要があります。 Rust-1.0のリリースまではしばらくこの状況が続くだろう。

恒例のコラム『 今週のRust"、これはリンクの Rust "n Stuffs にあります。以前と過去の変更、および言語の開発の見通しに関する情報が常にあります。

ここまでで、問題のプログラミング言語の構文が C/C++ などの言語の構文に非常に似ていることに気づいたかもしれません。どちらの場合もコメントを強調表示するために 2 つのスラッシュが使用され、コード ブロックが中括弧で囲まれているためです。 、関数の引数は括弧で囲まれます。 また、 fn キーワードは関数の宣言に使用され、すべてのプログラムには main() 関数が必要であることにも注意してください。 この場合、println 関数名の後の感嘆符は、マクロが使用されていることを示します (本質的には、Rust ランタイム ライブラリの print 関数の便利なラッパー)。

プログラムをコンパイルするには、次のコマンドを実行するだけです。

Rustc hello.rs

その結果、hello という名前のバイナリ ファイルがプログラム ソース コード ファイルのあるディレクトリに表示されます。これを実行するには、コマンド./hello を実行するだけです。 しかし、このファイルのサイズに注意してみると、800 KB を超えていることに多少ショックを受けるでしょう。 このような単純なプログラムが動作するには、これだけが必要なのでしょうか? デフォルトでは、Rust コンパイラはほとんどのランタイム ライブラリをプログラムに静的にリンクするため、Rust ランタイム ライブラリがインストールされていないシステムにバイナリをコピーして問題なく実行できます。 ただし、最適化と動的リンクを実行するようにコンパイラーに指示することもできます。

Rustc -O Cprefer-dynamic hello.rs

これで、より許容可能なサイズ (8 KB に等しい) のバイナリ ファイルが得られますが、ldd ユーティリティを使用する場合、プログラムが正しく動作するには、libstd-dynamic ライブラリがシステム上に存在する必要があることがわかります。<версия>。それで 。

プログラミング言語の構文

Rust でプログラムをコンパイルして実行できるようになったので、このプログラミング言語の構文を理解し、C、C++、その他の同様のプログラミング言語の構文との違いを強調することを提案します。

Fn doubler (x: i32) -> i32 ( x * 2 ) fn main () ( let a: i32 = 5; let b; b = doubler(a); println!("a minutes 2 ()", b) ; match b ( 1 ... 10 => println!("1 から 10 まで"), _ => println!("別の数値"), ) )

C/C++ 言語の操作に慣れている場合、このコードはなんだか奇妙に感じるかもしれませんが、これは非常に論理的です。 main() 関数から始めましょう。関数の最初の行で、32 ビット整数変数 a を宣言し、初期値 5 を割り当てます。変数の型の指定はスキップできます (i32 は標準の変数型です)。また、初期値も割り当てません。この場合、ゼロ値が含まれます。 例の変数 a と同じ方法で変数を宣言して特定の値を割り当てると、後でその値を変更できなくなるため、次のコード スニペットをコンパイルするときにエラー メッセージが生成されることに注意してください。

i32 = 5; とします。 a = 10;

デフォルトでは、Rust の変数は不変です。つまり、初期化後に値を変更することはできません。 可変変数も同様の方法で明示的に宣言する必要があります。

mut a: i32 = 5 とします。

なぜこれが必要なのでしょうか? これは余計な仕事ですよね。 これは本質的には真実ですが、一方で、プログラミング言語のこの機能は安全なプログラムの開発に役立ちます。 実際に値を変更する必要がある変数のみを可変にする必要があります。 Rust では、プログラムがどのように動作するかをできるだけ正確に説明するために、必要なだけ冗長になることが求められます。上の行では、サイズがちょうど 32 ビットの符号付き整数変数 a を宣言していますが、将来その値が変更される可能性があります。

次に、変数 a を引数として doubler 関数を呼び出し、戻り値を変数 b に格納します。 プログラム コードの先頭にある doubler 関数の宣言に注意してください。これは、-> 記号の後の関数パラメータ (i32) の型と戻り値 (i32) の型を示しています。 また、関数が単一の操作 x * 2 を実行することも簡単にわかります。これには、Rust コードの通常のブロックのように、セミコロンが続きません。 そこで何が起こっているのですか?

C と同じ方法で関数の値を返すことも、この場合のように関数コードの最後の行に式を置くだけで関数の値を返すこともできることがわかりました。 また、これは単なる式であるため、後ろにセミコロンを置く必要はありません。

main() 関数に戻りましょう。ここでは、println!() マクロを使用して結果を出力しました。 文字シーケンス () を使用して変数の値を置換する手法に注目してください。 最後に、この例では、Rust プログラミング言語の非常に便利な「match」キーワードを示します。これにより、多数の if/else ステートメントを実行する必要がある場合にコードの量を大幅に削減できます。 この場合、1...10 は値の範囲 (1 から 10 まで) の宣言であり、アンダースコア (_) 文字は他のすべての値と一致します。

Rust では、文字列型により 4 バイト文字、つまり任意の Unicode 文字の使用が許可されます。これは、プログラミング言語が設計段階でさまざまな言語や特殊文字を処理できるように調整されていることを意味します。 もう 1 つの便利なデータ型は、さまざまな型の変数のコレクションであるタプルです。

x = (1, 2.0, "こんにちは") とします。

この場合、整数値、浮動小数点値、および文字列値が同じタプルに配置されます。 これらの値は不変であり、同じ方法でアクセスできます。

Println!("()", x.2);

その結果、タプル x の 3 番目の要素の値、つまり文字列 "Hello" が出力されます。 Rustでもサポートされている通常の配列の場合と同様、タプルの要素の番号付けは0から始まります。 タプルを使用して関数から複数の値を返すことができます。

fn switch(input: (i32, i32)) -> (i32, i32) ( (input.1, input.0) ) fn main() ( let x = (10, 50); let y = switch(x) ; println!("(), ()", y.0, y.1); )

この場合、switch() という関数は 2 つの 32 ビット整数値のタプルを受け取り、入力変数に格納します。 ただし、2 つの整数値を含むタプルも返します。 この関数は、タプルの要素を交換し、結果のタプルを返すことを可能にする単純な式を使用します。

main() 関数は、値 10 と 50 を含む x という名前のタプルと、switch() の呼び出しから返された値を含む y という名前のタプルを作成します。 次に、タプルの値が単純に画面に表示されます(50、10)。

アドバイス: Rust の機能を自分で調べてみたいと思っている場合は、https://doc.rust-lang.org/book にある公式ドキュメントを読むことから始めることをお勧めします。

これは、Rust プログラミング言語の構文と機能の簡単な説明です。 特別シリーズの記事でこのプログラミング言語についてさらに詳しく知りたい場合は、お知らせください。

トピックの続き:
りんご

通信事業者 / 2017 年 10 月 24 日 MTS 電話ファームウェア (Smart Race、Sprint、Surf、Run 4G) MTS は、他の通信事業者と同様に、顧客にさまざまなモデルのスマートフォンを提供しています。