やわらかテック

興味のあること。業務を通して得られた発見。個人的に試してみたことをアウトプットしています🍵

Rustの標準でプライベートとする考え方に感銘を受けた

Rustを学び中のこと...

最近、ぼちぼちをRustを書き始めました。とはいったものの、まだFizzbuzzを見ずに書ける程度で理解はまだまだの状態です。

doc.rust-jp.rs

上記の公式コミュニティが運営しているドキュメントを見ながら学習を進めているのですが、非常に驚いたことがありました。それはRustは関数、モジュール、構造体の定義など、あらゆるものを標準でプライベートにしている点です。

Rustにおけるプライバシーは、「あらゆる要素(関数、メソッド、構造体、enum、モジュールおよび定数)は標準では非公開」というやり方で動いています。

モジュールツリーの要素を示すためのパス - The Rust Programming Language 日本語版

以下のコードをビルドしようとすると「関数afternoonが非公開だ」と怒られて失敗してしまいます。

fn morning() {
    println!("おはようございます");
}

mod greeding {
    fn afternoon() {
        println!("こんにちは")
    }

    pub fn evening() {
        println!("こんばんは")
    }
}

fn main() {
    // 朝の挨拶
    morning();
    // 昼の挨拶
    self::greeding::afternoon();
    // 夜の挨拶
    self::greeding::evening();
}
$ cargo build
   Compiling scope v0.1.0 (/Users/takamizawa46/workspace/rust/projects/scope)
error[E0603]: function `afternoon` is private
  --> src/main.rs:19:21
   |
19 |     self::greeding::afternoon();
   |                     ^^^^^^^^^ private function
   |
note: the function `afternoon` is defined here
  --> src/main.rs:6:5
   |
6  |     fn afternoon() {

同一ファイル内に定義した関数に対して、特に公開・非公開の情報を付与せずとも呼び出しが可能ですが、モジュール内に定義された関数に対してはそうはいきません。先ほどエラーになったように、明示的にpubが関数名の前に記述されていないければ、その関数はプライベートと判断されて、呼び出すことは出来ないのです。
pub fn afternoonとすれば、ビルドに成功します。

mod greeding {
    pub fn afternoon() {
        println!("こんにちは")
    }
}
$ cargo build
   Compiling scope v0.1.0 (/Users/takamizawa46/workspace/rust/projects/scope)
    Finished dev [unoptimized + debuginfo] target(s) in 0.12s

標準でプライベートなのって面倒じゃないの

ハッキリ言うと面倒です。しかし、自分の開発の経験上、公開しなくても良いものを公開してしまう(標準で公開されているために)ことで、本来は隠蔽したい処理が意図せず呼び出せてしまったりすることの方が面倒です。コードレビューで「privateにしてね」と何度、指摘されたことか...。
ところがRustでは標準でプライベートになっているので、公開必要な箇所には必ず「pub」と記述をしないといけません。必要な分だけ、公開するというRustの考え方は非常に素晴らしいなと感じました。

eg: Rubyの場合には標準で公開されている

class Greeding
  class << self
    def afternoon
      puts "こんにちは"
    end
    
    def evening
      puts "こんばんは"
    end
  end
end


Greeding.afternoon() # こんにちは
Greeding.evening() # こんばんは

明示的にprivateを記述したものだけがプライベートになる。

private

def evening
  puts "こんばんは"
end

:
Greeding.evening()
# private method `evening' called for Greeding:Class (NoMethodError)

Rustが新しい考えをもった言語という意見をよく目にしますが、確かに今まで自分が触ってきた言語とは異なります。前回はトレイトについて非常に驚かされました。Rustをもっと書いてみたいと思います。

www.okb-shelf.work

参考文献