雑記帳

技術系メモとか

Rust入門①

Rustお勉強用メモ。 基本的には公式サイトの焼き直し。

まえがき - The Rust Programming Language

変数と不変性

fn main() {
    // letで変数を宣言した場合は、不変となる
    let x = 5;
    println!("The value of x is: {}", x);

    // mutを付けることで、再代入可能な変数として宣言できる
    let mut y = 3;
    println!("The value of y is: {}", y);
    y = 123;
    println!("The value of y is: {}", y);

    // letで再定義した場合は、別の変数として宣言できる
    let x = "Hello, world";
    println!("The value of x is: {}", x);
}
tattsun:~/dev/hello_world
$ cargo run
   Compiling hello_world v0.1.0 (/home/tattsun/dev/hello_world)
    Finished dev [unoptimized + debuginfo] target(s) in 0.24s
     Running `target/debug/hello_world`
The value of x is: 5
The value of y is: 3
The value of y is: 123
The value of x is: Hello, world

タプル

fn main() {
    // タプル
    let a: (i64, f64, char) = (123, 3.456, 'A');

    // パターンマッチによる値の取り出し
    let (x, y, z) = a;
    println!("The value of x is {}", x);
    println!("The value of y is {}", y);
    println!("The value of z is {}", z);

    // アクセス修飾子を利用して直接アクセスする
    println!("The value of a.0 is {}", a.0);
    println!("The value of a.1 is {}", a.1);
    println!("The value of a.2 is {}", a.2);
}
tattsun:~/dev/hello_world
$ cargo run
   Compiling hello_world v0.1.0 (/home/tattsun/dev/hello_world)
    Finished dev [unoptimized + debuginfo] target(s) in 0.24s
     Running `target/debug/hello_world`
The value of x is 123
The value of y is 3.456
The value of z is A
The value of a.0 is 123
The value of a.1 is 3.456
The value of a.2 is A

配列

配列はスタック領域に確保されるため、固定長となる。

fn main() {
    // 配列
    let arr = [1, 2, 3, 4, 5];

    println!("The value of arr[0] is {}", arr[0]);
    // 配列の範囲外へのアクセスはコンパイル時エラーとなる
    // println!("The value of arr[0] is {}", arr[6]);
}
tattsun:~/dev/hello_world
$ cargo run
   Compiling hello_world v0.1.0 (/home/tattsun/dev/hello_world)
    Finished dev [unoptimized + debuginfo] target(s) in 0.24s
     Running `target/debug/hello_world`
The value of arr[0] is 1

if式

fn main() {
    let x = 5;
    // 他の言語と同じく、if, else, else ifが利用できる
    // ifは式となるため、変数の宣言時に利用したりもできる
    let a = if x == 5 {
        "x is 5"
    } else {
        "x is not 5"
    };
    println!("The value of a is {}", a);
}
tattsun:~/dev/hello_world
$ cargo run
   Compiling hello_world v0.1.0 (/home/tattsun/dev/hello_world)
    Finished dev [unoptimized + debuginfo] target(s) in 0.24s
     Running `target/debug/hello_world`
The value of a is x is 5

WSL2 + Emacs + Rustの開発環境を構築する

流行りのWSL2がリリースされたようなので、まずは最低限のRust開発環境を整えてみた。

WSL2の導入

WSL2自体の導入は、MS公式サイトに詳しいあるため省略。 6/7時点では、Windows Updateによる配信はされていないため、別途インストーラーを利用する必要がある。

WSL2の基本操作は以下のページが詳しいため参照。GUIのツールも使えるんだ…、WSLすごい。

Rust + Emacsの導入は正直WSL関係ないのだが、備忘のために残しておく。

Rustの導入

公式のインストーラーを使えば良い。

tattsun:~
$ curl https://sh.rustup.rs -sSf | sh
info: downloading installer

(中略)

Rust is installed now. Great!

To get started you need Cargo's bin directory ($HOME/.cargo/bin) in your PATH
environment variable. Next time you log in this will be done
automatically.

To configure your current shell run source $HOME/.cargo/env

rustcなどを利用するために、パスを通す必要がある。

## 個人的にデフォルトの設定と後から追加した設定を分けておきたいので、
## ~/.bash_profile に追加設定用ファイルを作成し、それをインポートさせる。
$ echo 'source ~/.bash_profile' >> ~/.bashrc

$ echo 'PATH=$PATH:$HOME/.cargo/bin' >> ~/.bash_profile

$ source ~/.bash_profile

$ rustc --version
rustc 1.44.0 (49cae5576 2020-06-01)

Emacsの導入

まずはEmacsをインストールする。 GUI版も利用できるっぽいのだが、自分は一旦シェルからしか使わない予定なので、noxを入れておく。

$ sudo apt install -y emacs-nox

コード補完を利用するために、racerというツールが必要らしいので、先に入れておく。

$ rustup toolchain add nightly
$ rustup component add rust-src
$ cargo +nightly install racer

~/.emacs.d/init.el の設定は以下の通り。今後試しながら改善していく。

;; -------------------------------
;; 基本設定
;; -------------------------------

;; 言語設定
(set-language-environment 'Japanese)
(set-language-environment 'utf-8)
(prefer-coding-system 'utf-8)

;; 括弧の補完
(electric-pair-mode 1)

;; 列番号の表示
(column-number-mode 1)

;; 行番号の表示
(global-linum-mode t)

;; 対応する括弧を光らせる
(show-paren-mode 1)

;; メニューバーを非表示
(menu-bar-mode -1)


;; バックアップファイルは作成しない
(setq make-backup-files nil)
(setq auto-save-default nil)

;; -------------------------------
;; パッケージ管理
;; -------------------------------
(require 'package)
(add-to-list 'package-archives
         '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)

;; straight.elのインストール
(defvar bootstrap-version)
(let ((bootstrap-file
       (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
      (bootstrap-version 5))
  (unless (file-exists-p bootstrap-file)
    (with-current-buffer
    (url-retrieve-synchronously
     "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
     'silent 'inhibit-cookies)
      (goto-char (point-max))
      (eval-print-last-sexp)))
  (load bootstrap-file nil 'nomessage))


;; -------------------------------
;; Company
;; -------------------------------
(straight-use-package 'company)

;; -------------------------------
;; Rust
;; -------------------------------
(straight-use-package 'rust-mode)
(straight-use-package 'racer)
(add-hook 'rust-mode-hook #'racer-mode)
(add-hook 'racer-mode-hook #'eldoc-mode)
(add-hook 'racer-mode-hook #'company-mode)
(setq company-tooltip-align-annotations t)

Rustを書いてみる

適当なディレクトリにcargoプロジェクトを作成する。

$ cargo new hello_world --bin

Emacshello_world/src/main.rs を適当に編集して、補完が聞くかなど挙動を確かめる。

$ cargo run
   Compiling hello_world v0.1.0 (/home/tattsun/dev/hello_world)
    Finished dev [unoptimized + debuginfo] target(s) in 0.27s
     Running `target/debug/hello_world`
Hello, world

こんな感じで出力されればOK。