# Rust演習
## プロジェクト作成
プロジェクト作成
```bash
cargo new myproj
cd myproj
```
ビルド
```bash
cargo build
```
実行
```bash
cargo run
# hello world
```
## 演習のやりかた
Rust Playground にソースコードを貼り付けて編集、実行してみましょう。
https://play.rust-lang.org
★がついてる演習は難しめなので分からなかったらスキップしても問題ないです。
## 参考資料
Rust のスタンダードライブラリのドキュメント
https://doc.rust-lang.org/std/
Rust 文法などの日本語資料
https://doc.rust-jp.rs/
## 変数と可変性
`let var`で定義した変数varは変更することができない。`let mut var`
```rust
//コンパイルエラー
fn main() {
let x = 5;
println!("The value of x is: {}", x);
x = 6; //xは変更できない
println!("The value of x is: {}", x);
}
```
コンパイルが通るようにエラーを直してください。
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=203848ff6cad71d22a09f842f2c9061f
### 配列(★)
以下のコードの添字アクセスは panic してしまいます。範囲外アクセスをしてもデフォルト値を出力するように変更してください。
```rust
fn main() {
let a = [1, 2, 3, 4, 5];
let index = 10;
let element = a[index];
println!("The value of element is: {}", element); // 要素の値は{}です
}
```
### 戻り値の書き方①
以下のコードはエラーが置きます。なおしましょう。
```rust
fn main() {
let x = plus_one(5);
println!("The value of x is: {}", x);
}
fn plus_one(x: i32) -> i32 {
x + 1;
}
```
### 戻り値の書き方②
引数の和が正しく表示される関数 `add3` を作ってみましょう。
```rust
fn main() {
println!("{}",add1(100,200));
println!("{}",add2(150,250));
//println!("{}",add3(2_000_000_000,2_000_000_000));
}
fn add1(x:i32, y:i32) -> i32{
let ans = x + y;
return ans;
}
fn add2(x:i32,y:i32) -> i32{
let ans = x + y;
ans
}
```
### 復習①★
1. 温度を華氏と摂氏で変換する。
2. フィボナッチ数列のn番目を生成する。
## 所有権
### 変数のスコープ
コンパイルエラーを直してください。
```rust
fn main() {
{
let x = 5;
let s = String::from("hello");
}
println!("{}",x);
println!("{}",s);
}
```
### 変数の束縛と所有権の移動
コンパイルエラーを直してください。
```rust
fn main(){
let s1 = String::from("hello");
let s2 = s1;//"hello"の所有権がs1からs2に移動
println!("{}",s1);
}
```
### 関数とスコープ
参照を使わずコンパイルエラーをなおしてください。
```rust
fn main() {
let s1 = String::from("hello");
let len1 = calculate_length(s1);
let len2 = calculate_length(s1);
}
fn calculate_length(s: String) -> usize {
let length = s.len(); // len()メソッドは、Stringの長さを返します
length
}
```
### 参照
参照を使ってコンパイルエラーをなおしてください。
```rust
fn main() {
let s1 = String::from("hello");
let len1 = calculate_length(s1);
let len2 = calculate_length(s1);
}
fn calculate_length(s: String) -> usize {
let length = s.len(); // len()メソッドは、Stringの長さを返します
length
}
```
### 宙に浮いた参照
コンパイルエラーを直してください。
```rust
fn main() {
let reference_to_nothing = dangle();
}
fn dangle() -> &String {
let s = String::from("hello");
&s
}
```
### 復習②★
1. 整数のリストが与えられ、ベクタを使ってmean(平均値)、median(ソートされた時に真ん中に来る値)、 mode(最も頻繁に出現する値; ハッシュマップがここでは有効活用できるでしょう)を返してください。
2. 文字列をピッグ・ラテン(訳注: 英語の言葉遊びの一つ)に変換してください。各単語の最初の子音は、 単語の終端に移り、"ay"が足されます。従って、"first"は"irst-fay"になります。ただし、 母音で始まる単語には、お尻に"hay"が付け足されます("apple"は"apple-hay"になります)。 UTF-8エンコードに関する詳細を心に留めておいてください!
3. ハッシュマップとベクタを使用して、ユーザに会社の部署に雇用者の名前を追加させられるテキストインターフェイスを作ってください。 例えば、"Add Sally to Engineering"(開発部門にサリーを追加)や"Add Amir to Sales"(販売部門にアミールを追加)などです。 それからユーザに、ある部署にいる人間の一覧や部署ごとにアルファベット順で並べ替えられた会社の全人間の一覧を扱わせてあげてください。
### 構造体
Circle型を作って、長方形が円に含まれているかをチェックするメソッドを作ってください。
```rust
struct Rectangle {
width: u32,
height: u32,
}
fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
println!(
"The area of the rectangle is {} square pixels.",
area(&rect1)
);
}
fn area(rectangle: &Rectangle) -> u32 {
rectangle.width * rectangle.height
}
```
### Trait
Circle型, Rect型に共通する area を取得することができる Shape Trait を作成し Cricle, Rect 型にそそれぞれ実装してください。
```rust
struct Rectangle {
width: u32,
height: u32,
}
fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
println!(
"The area of the rectangle is {} square pixels.",
area(&rect1)
);
}
fn area(rectangle: &Rectangle) -> u32 {
rectangle.width * rectangle.height
}
```
### Trait × Generics
加算・乗算処理が可能な任意の型について `norm` を計算する実装をしてください。
```rust
struct Point<T> {
x: T,
y: T,
}
impl<T> Point<T> {
fn x(&self) -> &T {
&self.x
}
}
fn main() {
let p = Point { x: 5, y: 10 };
println!("p.x = {}", p.x());
}
impl Point<f32> {
fn norm(&self) -> f32 {
(self.x.powi(2) + self.y.powi(2))
}
}
```
> Hint: https://doc.rust-lang.org/std/ops/trait.Add.html
### Trait × Generics②
Point<T>型をVec型で管理し、比較可能な任意の型Tについて sort できるようにしてください。
```rust
struct Point<T> {
x: T,
y: T,
}
fn main() {
let mut pv = vec![Point { x: 5, y: 10 }, Point { x: 1, y: 20 }];
pv.sort();
for v in pv.iter() {
println!("{}", v);
}
}
```
### Enum, Matching
コンパイルエラーをなおしてください
```rust
fn plus_one(x: Option<i32>) -> Option<i32> {
match x {
Some(i) => Some(i + 1),
}
}
```
### エラー処理
次のメソッド `new` を `Result<Guess, Error>` を返すメソッドにしてください。 Errorの型は自分で考えて定義してください。
```rust
pub struct Guess {
value: u32,
}
impl Guess {
pub fn new(value: u32) -> Guess {
if value < 1 || value > 100 {
// 予想の値は1から100の範囲でなければなりませんが、{}でした
panic!("Guess value must be between 1 and 100, got {}.", value);
}
Guess {
value
}
}
pub fn value(&self) -> u32 {
self.value
}
}
```
## 入出力プロジェクト: コマンドラインプログラムを構築する★
一通りやってみましょう。
https://doc.rust-jp.rs/book/second-edition/ch12-00-an-io-project.html