18
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Rustミニクイズ集 ①

Last updated at Posted at 2025-11-30

こんにチュア!本記事は Rustアドベントカレンダー2025 1日目の記事です!

本記事では、ゆめみ社内開催のRust勉強会にて自分が出題したミニクイズをまとめました!面白いネタがあったら同僚に出すような、小ネタ集として見てくれたら幸いです :sparkles:

まだRust勉強会は続くためナンバリングが①になっています。今日から新会社所属になりましたが、今後とも変わらずRust勉強会を実施できたら②の記事が書けるかも...?書けることを願っています!

【宣伝】hooqアドベントカレンダー走行中!

筆者は本アドカレとは別に hooqアドベントカレンダー という筆者が作ったクレートhooqを紹介する個人アドベントカレンダーも執筆してます!もし良かったら覗いてみてください :eyes:

1日目の記事: 【Rust】お手軽エラーロギング用マクロ hooq を作りました!

Rust勉強会概要

社内Rust勉強会は、 Rustlings に沿って進めています。そのため、各クイズもなるべくその回に沿った内容です!よって、参考のためにRustlingsの該当回も付記しておきます。

Let's クイズ!

では本題のクイズに入りましょう!

第1問 チュートリアル回

初回は第0回として問題は解かず、Rustの紹介を行いました!というわけでRustという名前の由来に関する問題です。

問題

Rustの名前の由来の一つに、"tRUST" や "RobUST" など信頼や堅牢といった言葉に近いからというのがあります(要出典)。

もう一つ、明確な由来とされているものがあるのですが、それは以下の3つのうちどれでしょう?

  1. 「最後のプログラミング言語」を目指し、"last"と掛けた
  2. 開発メンバーがゲームオタクで、ゲームのRustから取った
  3. 開発メンバーが自転車好きで、チェーンの"錆"から取った
答え

答えは「3. 開発メンバーが自転車好きで、チェーンの"錆"から取った」。

設計者のグレイドン・ホアレさんが生物オタクでもあるために"さび菌"を由来ともしているらしい。(さび菌はしぶといとされる)

第2問 変数宣言

まずは変数宣言から、というわけで、ミュータブル・イミュータブルに関係するような問題を出してみました!

rustlings: 01_variables

問題

Rustの次のコードに一番近いTSコードはどれでしょうか...?

rust
let v: Vec<i32> = vec![1, 2, 3];
  1. let v: number[] = [1, 2, 3];
  2. const v: number[] = [1, 2, 3];
  3. const v: readonly number[] = [1, 2, 3];
答え

答えは 3

const v: readonly number[] = [1, 2, 3];

Rustのイミュータブルは、配列の中身に関しても守られます。
安心して let に身を任せてしまいましょう!

第3問 関数

関数の返り値省略時のシグネチャを問いました!この手の知識って後々効いてくる感があります...

rustlings: 02_functions

問題

Rustの関数は何も値を返さない時、返り値の型を省略できます。

rust
fn hoge() {/* 処理 */}

省略しなかった場合の上記 hoge 関数のシグネチャはどれでしょう?

  1. fn hoge() -> None
  2. fn hoge() -> ()
  3. fn hoge() -> !
答え

正解は 2. fn hoge() -> ()

() はユニット型といい、C言語の void 型のような、何もないことを示す型です。

  • None: Option 列挙体のバリアントの一つ。型名ではない
    • fn hoge() -> None というシグネチャは(基本的に)ない
  • !: Never型という型。そもそも返り値を 返さない ことを示します
    • fn hoeg() -> ! というシグネチャの関数は作れます

第4問 データ型

Rustの整数型の型名はビット数が入っているのが特徴的だったため、そこにフィーチャーしたコンサイ的な問題を出してみました!

rustlings: 04_primitive_types

問題

  • Q1. u64 型の最大値はいくつでしょう?

  • Q2. i32 型の最小値・最大値はいくつでしょう?

答え
  • Q1. u64 の最大値

2^64 - 1 = 18446744073709551615

  • Q2. i32

    • 最小値: - 2^31 = -2147483648
    • 最大値: 2 ^ 31 - 1 = 2147483647
  • 符号付き整数は2の補数表現です

  • 各型の MAX, MIN 定数で知ることができます

(補足) 2の補数表現

  • 負数を「正の数をビット反転し1を足したもの」で表現
    • 負数の最上位ビットは1に
  • 1の補数と比べると
    • 表現できる数の種類が1つ多い
      • (1の補数には+0, -0がある)
    • 正の数の減加算器がそのまま使える

第5問 データ型 (2)

前問に続きデータ型の問題...と見せかけた謎問です!

rustlings: 04_primitive_types

問題

次の表現のうち、コンパイルエラーとなってしまうものはどれ?
( main 関数内にあるものとします)

  1. let s = '';
  2. let n = 1_2__3___4____;
  3. let () = {};
答え

答えは1. let s = ''; です!

「空文字」という概念は存在しないのでコンパイルエラーです。
空文字 "" なら問題ありません。

2: 整数リテラルはアンダーバーで区切ることができます
3: ブロック {} の返り値は () なので束縛可能です

ちなみにTypeScriptだと逆に2, 3がエラーで1だけ正常に実行されます。

第6問 ベクタ

Rustのドキュメントを読む習慣をつけてほしくて出した一題だったと思います。Vecのドキュメント をよく読めば解けます。( Deref<Target=[T]>Clone トレイトのメソッドが混ざっているので最初は難しいかもしれませんが...)

rustlings: 05_vecs

問題

Vec<T> のメソッドでないものはどれ?

ヒントもとい補足:

v: Vec<T> について v.xxx(...) と書けないものを選んでください

  1. map
  2. join
  3. clone
答え

答えは 1. map です!

mapIterator トレイトに定義されているメソッドで、Vec<T> からアクセスするには一旦 .iter() によって std::slice::Iter<'a, T> 型の値に変換する必要があります。

rust
fn main() {
    let v = vec![1, 2, 3];
    
    let v_strs: Vec<String> = v.iter().map(ToString::to_string).collect();
    
    println!("{}", v_strs.join(" "));
}

2の join はスライス &[T] から呼べるメソッドで、 impl Deref<Target = [T]> for Vec<T> {...} なので Vec<T> からも呼べます。

3の cloneClone トレイトが提供するメソッドで、 impl Clone for Vec<T> {...} なので Vec<T> のメソッドでもあります。

第7問 所有権

最初の鬼門、所有権を扱った回でした!「Rustにおけるプリミティブ型とは...?」というのを確認できるような問題にしてみました。

rustlings: 06_move_semantics

問題

rust
macro_rules! check_impl_copy {
    ($v:expr) => {
        let v1 = $v;
        let v2 = v1;
        println!("{v1:?}, {v2:?}");
    };
}

fn main() {
    /* 1. */ check_impl_copy!(10);
    /* 2. */ check_impl_copy!('\u{3042}');
    /* 3. */ check_impl_copy!(vec![1, 2, 3]);
    /* 4. */ check_impl_copy!([1, 2, 3]);
}
  1. ~ 4. のうちコンパイルエラーとなる行はどれでしょう?

補足: 例えば check_impl_copy!(true) は以下に展開されます

rust
let v1 = true;
let v2 = v1;
println!("{v1:?}, {v2:?}");
答え

答えは 3. vec![1, 2, 3] です!

    1. 整数型は Copy トレイトがついています
    1. これは char 型で、 Copy あり
    1. VecCopy を実装しません
    1. 配列は要素の型が Copy を実装する時 Copy です

Copy トレイトの有無は各型のドキュメントで確認できます。

第8問 構造体・列挙体

structenum が登場し、なんとなく予約語を調べたくなったので出した問題です!

rustlings: (直接関係するような問題はなし)

問題

次のうちRustの予約語※で ない ものはどれ?2つ選べ

struct, self, Self, union, enum, yield, match, switch, type, priv, try, use, super, abstract, typeof

※ 予約語には、将来的な機能追加のために予約されているものを含む

答え

答えは unionswitch です! (ただし The Rust Programming Language に準拠)

  • 対応機能が存在する予約語

    • struct, self, Self, enum, match, type, use, super
  • 将来のための予約語

    • yield, priv, try, abstract, typeof
  • switch: match式があるのでなし

  • union: 機能はあるが予約語でない

(参考) 共用体 union

列挙体があるRustにとっては不要だが、C言語の共用体と互換性を持たせる(FFI)ために用意されている機能

rust
#[repr(C)]
union MyUnion { // メモリ上では u8 も bool も1バイトを使う
    i: u8,
    b: bool,
}
fn main() {
    let u = MyUnion { i: 42 };
    println!("int: {}", unsafe { u.i });
    println!("bool: {}", unsafe { u.b }); // 未定義の動作
}

union は変数として普通に( r# を付けずに)利用可能です。なぜ union の機能はあるのに予約語ではないのでしょうね...互換性の問題とか?謎です。

rust
fn main() {
    let union = 10;
    println!("{union}");
}

Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=51091808ece8b31a030808800c8a0a0f

第9問 列挙体

列挙体にかこつけて複合的に問う謎問になってしまいました...

rustlings: 08_enums

問題

次のプログラムは1~5のうち2行をコメントアウトするとコンパイルが通ります。どの2行でしょうか?

rust
enum MyResult { Ok, Err }
use MyResult::{Ok, Err}; // 1

fn func() -> MyResult {
    let res = Ok;
    let _ = res; // 2
    let _a = res; // 3
    let _b = res;
    let _ = Ok as usize; // 4
    let _ = Err?; // 5
    Ok
}
答え

正解は 3番5番 です!

rust
enum MyResult { Ok, Err }
use MyResult::{Ok, Err}; // 1

fn func() -> MyResult {
    let res = Ok;
    let _ = res; // 2
    // let _a = res; // 3
    let _b = res;
    let _ = Ok as usize; // 4
    // let _ = Err?; // 5
    Ok
}
  • 1: use 列挙体型::{対象のバリアント, ...};列挙体型 は省略可能
  • 2と3: _変数名 は束縛をするが、 _ は束縛を行わない
  • 4: 全てのバリアントがユニット様である列挙体は整数型にキャスト可能
    • (正直使い所はほとんどない)
  • 5: ? 演算子(tryマクロ)が使える列挙体は OptionResult のみ
    • 正確には Tryトレイト実装型だが、実質 Option, Result に限られる
    • type MyResult<T> = Result<T, XXX>; のような型エイリアスの場合この限りではない
      • anyhow::Result などが該当

Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=4f4e94dde80758b6c76d2700f8e3d782

第10問 文字列

ちょうど案件か何かで文字列数をどう判定するかみたいなことで迷っていたので出した問題でした。 String::len はバイト数を返すのですよね...

rustlings: 09_strings

問題

次の文字列は何文字でしょうか...?

㍿👨‍💻ゆめみ👩‍💻

ヒント: ㍿ は1文字です

  • 6文字
  • 7文字
  • 34文字
  • 10文字
答え
  • 6文字: ⚪︎ とりあえず正解!
  • 7文字: C言語と違い \0 は含まれないので不正解
  • 34文字: △ 34文字ではなく 34バイト
  • 10文字: △ ユニコードのポイント数は10ポイント

"\u{337F}\u{1F468}\u{200D}\u{1F4BB}ゆめみ\u{1F469}\u{200D}\u{1F4BB}"

(ユニコード的な意味で)文字数を確認するコードです!

rust
use unicode_segmentation::UnicodeSegmentation;

fn main() {
    let s = "\u{337F}\u{1F468}\u{200D}\u{1F4BB}ゆめみ\u{1F469}\u{200D}\u{1F4BB}";

    println!("{s}"); // 6文字のはず
    println!("len: {}", s.len()); // 34
    println!("chars len: {}", s.chars().collect::<Vec<_>>().len()); // 10

    let g = s.graphemes(true).collect::<Vec<&str>>();
    println!("graphemes len: {}", g.len());
}

...ごめんなさい厳密な答えはありません!というかこの問は「〇文字!」と定めてしまうとうるさい人から色々言われるので気を付けましょう...

第11問 モジュール

モジュール分け、その言語になれてないとストレスの元ですよね...なんていうことに思いを馳せながら作った問題だった気がします。

rustlings: 10_modules

問題

a::b モジュールがしっかりと存在するのはどのツリーでしょうか?

ヒント?: 答えは一つとは限らないです!

  • 1
├── Cargo.toml
└── src
    ├── a
    │   ├── b
    │   │   └── mod.rs
    │   └── mod.rs
    └── main.rs
  • 2
├── Cargo.toml
└── src
    ├── a::b
    │   └── mod.rs
    ├── a.rs
    └── main.rs
  • 3
├── Cargo.toml
└── src
    ├── a
    │   └── b.rs
    ├── a.rs
    └── main.rs
答え

答えは 13 です!

  1. mod.rs を使ったモジュール分けです。
  2. このような書き方はありません。
  3. mod.rs を使わない場合の書き方です。
  • b.rs : b/mod.rs とわざわざする必要はないです
  • a.rsa/b.rs:
    • 2018 edition より利用可能に

第12問 ハッシュマップ・Option

程よいタイミングでHashMapとOptionの取り扱いが被ったので、両方を問えるような問いにしました!

rustlings: 11_hashmaps12_options

問題

HashMap::<K, V>::get(&self, k: &K) メソッドの返り値型はなんでしょう?

  1. V?
  2. Option<V>
  3. Maybe<&V>
  4. どれでもない
答え

答えは 4. どれでもない です!

get メソッドはキーに対応する値の 参照 を得るメソッドなので( &self がレシーバなのがヒント)、 &V にまつわる型が答えになります。

存在する・しないを表すのにはOption型を使います。

以上より、 Option<&V> が正解です。記法として1と3は(組み込みでは)存在せず、2は &V ではなく V なので不正解でした!

第13問 Option型

Option型を取り扱う折角の機会だったので、自分が(今でもまれに)よくやるミスを出題してみました!

rustlings: 12_options

問題

コンパイルエラーを探せ!

rust
fn print_name(id: usize, members: &HashMap<usize, Member>) {
    if let Member { name } = members.get(&id) {
        println!("Member {id}'s name: {name}");
    } else {
        println!("Member {id} is not found.");
    }
}

上記はコンパイルエラーになります。どこを間違えているでしょうか?

答え

let Member { name } = ... の部分が誤り!

Some がなく、正しくは let Some(Member {name}) = ...

Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=5821cddd432493f49b7cb8ffef1278c9

第14問 Result型

今回の問題はResult型というよりはトレイトの問題でした。とはいえ、特に最初に Result 型に触れた時に結構混乱しそうな内容なので、 Result 型を学ぶうちに触れておいて損はないと思い出題しました。初心者には少し難易度高めです。

rustlings: 13_error_handlings

問題

rust
fn process() -> Result<(), ???> {
    Ok(())
}

??? 部分に入れると必ずコンパイルエラーになるのはどれ?

  1. std::ops::Range<()>
  2. std::error::Error
  3. ()
  4. std::io::Error
答え

答えは 2. std::error::Error です!

他は型ですが、 std::error::Error は型ではなく トレイト なので、impl std::error::Error のように書く(静的ディスパッチの場合)か、Box<dyn std::error::Error> のようにトレイトオブジェクト(動的ディスパッチ)を使う必要があります!(大体後者が吉)

Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=f012be3ea0c570824c1c9895e655fcbe

第15問 Result型 (2)

難易度や内容的に、14問と15問は逆順で聞くべきだったかもしれませんが、当時の通りの順番で紹介しています。解き方は第6問の Vec 同様ドキュメントを確認することです。

rustlings: 13_error_handlings

問題

次のうち Result 型に存在しないメソッドはどれでしょう?

ヒント & 補足: "メソッド"はトレイト実装により提供されるメソッドを含みます

  1. map
  2. to_string
  3. unwrap
  4. flatten
答え

答えは 2. to_string

Result<T, E> where T: Debug, E: Debug の時は Result には Debug が実装されますが、 Display トレイトはどの場合でも実装されません!

よって ToString トレイトも同様に実装されず、 to_string は使えないです!

Result<T, E> where T: Display, E: Display などは普通にあり得ます。

すなわち、「正常値やエラーは中身を取り出してから表示する必要がある」ということです!

第16問 ジェネリクス

今回最後の問題は第13問と同様にコンパイルエラーを探せ!問題で、自分がやりがちだったミス由来の問題になっています。結局コンパイラの気持ちになるのがRust習得の早道ですね(多分)!

rustlings: 14_generics

問題

コンパイルエラーを探せ!

rust
struct Wrapper<T>(T);

impl Wrapper<String> {
    fn show(&self) {
        println!("{}", self.0);
    }
}

impl Wrapper<T> {
    fn func() {}
}

コンパイルエラーとなる原因箇所を指摘してみてください!

答え

impl<T> が足りません!

rust
impl Wrapper<T> {
    fn func() {}
}

ジェネリクスは impl にくっつけて書く必要があります。

rust
impl<T> Wrapper<T> {
    fn func() {}
}

(補足) なぜ impl<T> と書くのか?

  • impl ブロックは複雑な場合もある
    • 例: impl<T, U> Trait<T> for Type<U> {...}
  • 「ジェネリクスが埋まった 特定の型の時のみ実装を持つ
    みたいな書き方をする時もある
    • 例: impl std::fmt::Display for Wrapper<String> {...}
    • 全ての Wrapper<T>Display が実装されるわけではない
    • impl横の表記抜きでは String が型引数か型なのか判別できず

以上の事情で利用するジェネリクスはimpl横で示すのがルール

まとめ

いかがでしたでしょうか...?ミニクイズは元々勉強会参加者を増やすために始めたものでしたが、案外様になっていて自分でも驚いてます。

  • 新しいパラダイムが多い言語だから意外性を出しやすい
  • 一方で変な構文が少なく、理解・解説がしやすい機能が多い

こんなRustの性質がミニクイズと合っていたかもしれません。

最後に、本記事執筆にきっかけをくださった勉強会関係の皆様、自由に勉強会を開催させてくれたゆめみさん、そして読者の方に感謝いたします。

ここまで読んでいただきありがとうございました!

18
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?