💭

Booleanとは何なのかをRuby, Rust, Pythonで掘り下げる

に公開

はじめに

私のソフトウェアのエンジニアとしての入りはC言語でした。次にPythonを触り、Booleanを見たときに衝撃を覚えたのを思い出します。
今回は、普段使用しているBooleanをRuby, Rust, Pythonで掘り下げてみます。

マシンスペック

MacBook Air M2 arm64
Docker上で実施

準備

Dockerの起動

mkdir bool_deepdive && cd $_
mkdir -p ruby python rust
vim Dockerfile
# ================================================================
# Boolean Deep‑Dive Lab  (Ubuntu 24.04, arm64/amd64 共通)
#   - ruby-dev  (debug build, libffi/fiddle 有り)
#   - python-dev (CPython 3.12.11, --with-pydebug)
#   - Rust stable (cargo/rustc)   ← dev ユーザ HOME にインストール
#   - gdb / lldb / clang
# ================================================================

#############################
# Stage 0 : Base OS + build tools
#############################
FROM ubuntu:24.04 AS base
ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y --no-install-recommends \
        build-essential git autoconf automake libtool pkg-config \
        zlib1g-dev libssl-dev libreadline-dev libffi-dev \
        wget curl ca-certificates \
        gdb lldb clang \
        python3.12 python3.12-venv python3.12-dev python3-pip \
    && apt-get clean && rm -rf /var/lib/apt/lists/*

#############################
# Stage 1 : Rust install (non‑root dev user)
#############################
FROM base AS rust-layer
RUN useradd -ms /bin/bash dev
USER dev
WORKDIR /home/dev

# rustup-init をユーザー権限で実行
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
    | sh -s -- -y --profile minimal --default-toolchain stable --no-modify-path

# dev ユーザーの cargo/bin を PATH に
ENV PATH="/home/dev/.cargo/bin:${PATH}"

#############################
# Stage 2 : Build CPython (debug)
#############################
FROM rust-layer AS build-python
USER root
WORKDIR /opt
RUN git clone --depth 1 --branch v3.12.11 https://github.com/python/cpython.git
WORKDIR /opt/cpython
RUN ./configure --with-pydebug && make -j$(nproc)

#############################
# Stage 3 : Build Ruby (debug + fiddle)
#############################
FROM rust-layer AS build-ruby
USER root
WORKDIR /opt

RUN git clone --depth 1 https://github.com/ruby/ruby.git \
 && chown -R root:root ruby

WORKDIR /opt/ruby

RUN wget -O tool/config.guess 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess' \
 && wget -O tool/config.sub 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub'

RUN apt-get update && apt-get install -y ruby-full

RUN autoconf \
 && ./configure --enable-shared --disable-install-doc --enable-debug-env --with-libffi BASERUBY=$(which ruby) \
 && make -j$(nproc)

#############################
# Stage 4 : Final dev image
#############################
FROM rust-layer
LABEL purpose="boolean-deep-dive"

# --- interpreters & sources ---
COPY --from=build-python /opt/cpython/python /usr/local/bin/python-dev
COPY --from=build-python /opt/cpython         /opt/cpython-src

COPY --from=build-ruby   /opt/ruby/miniruby   /usr/local/bin/ruby-dev
COPY --from=build-ruby   /opt/ruby            /opt/ruby-src

# dev ユーザは rustup & cargo を既に PATH で使える
WORKDIR /home/dev
CMD ["bash"]
# ビルド      
docker build -t bool-lab .

# 起動(ソース共有)
docker run -it --rm \
  -v "$PWD/demo:/home/dev/demo" \
  -v "$PWD/article:/home/dev/article" \
  bool-lab

各ファイルの準備

Ruby

puts "Ruby Boolean Exploration"

puts "\n== true / false のクラス =="
p true.class
p false.class

puts "\n== object_id で即値確認 =="
p true.object_id    # 常に20 (0x14)
p false.object_id   # 常に0

puts "\n== true / false の内部表現 (整数として) =="
puts "trueの内部値: #{true.inspect}#{true.object_id} (0x#{true.object_id.to_s(16)})"
puts "falseの内部値: #{false.inspect}#{false.object_id} (0x#{false.object_id.to_s(16)})"

puts "\n== nil は falsy? =="
p !!nil    # false
p !!0      # true

Python

print("Python Boolean Exploration\n")

print("== type(True), type(False) ==")
print(type(True), type(False))   # <class 'bool'>

print("\n== True, False は int のサブクラス? ==")
print(isinstance(True, int), isinstance(False, int))  # True, True

print("\n== id(True), id(False) を確認(シングルトンか?)==")
print(id(True), id(False))

print("\n== sys.getsizeof(True) のサイズ ==")
import sys
print(sys.getsizeof(True))

print("\n== falsyの観察 ==")
print(bool(None), bool(0), bool([]), bool({}))

Rust

cargo new rust_bool_demo && cd rust_bool_demo
fn main() {
    println!("Rust Boolean Exploration\n");

    println!("== boolのサイズ(メモリ上のサイズ) ==");
    println!("size_of::<bool> = {}", std::mem::size_of::<bool>());

    println!("\n== boolを整数へ変換 ==");
    let t: bool = true;
    let f: bool = false;
    println!("true as u8 = {}", t as u8);
    println!("false as u8 = {}", f as u8);

    println!("\n== boolのメモリアドレスを確認 ==");
    println!("&true  = {:p}", &t);
    println!("&false = {:p}", &f);
}

実行

Ruby

demo/demo.rb | tee ~/article/ruby_out.txt
Ruby Boolean Exploration

== true / false のクラス ==
TrueClass
FalseClass

== object_id で即値確認 ==
20
0

== true / false の内部表現 (整数として) ==
trueの内部値: true20 (0x14)
falseの内部値: false0 (0x0)

== nil は falsy? ==
false
true

Python

demo/demo.py | tee ~/article/python_out.txt
Python Boolean Exploration

== type(True), type(False) ==
<class 'bool'> <class 'bool'>

== True, False は int のサブクラス? ==
True True

== id(True), id(False) を確認(シングルトンか?)==
187650042234048 187650042234080

== sys.getsizeof(True) のサイズ ==
28

== falsyの観察 ==
False False False False

Rust

cd demo/rust_bool_demo
cargo run --release | tee ~/article/rust_out.txt
   Compiling rust_bool_demo v0.1.0 (/home/dev/demo/rust_bool_demo)
    Finished `release` profile [optimized] target(s) in 0.15s
     Running `target/release/rust_bool_demo`
Rust Boolean Exploration

== boolのサイズ(メモリ上のサイズ) ==
size_of::<bool> = 1

== boolを整数へ変換 ==
true as u8 = 1
false as u8 = 0

== boolのメモリアドレスを確認 ==
&true  = 0xffffe0c3f228
&false = 0xffffe0c3f22c

結果

言語 Boolean型の特徴(メモリ表現) 表現形式 サイズ 値の扱い方
Ruby 「即値」として特殊なタグ付き整数値で表現(ポインタでなく整数値) 即値(特殊整数) ポインタサイズ (64bit環境なら8byte) true=20 (0x14)false=0 と固定
Python bool型はint型のサブクラスで、True / False は固定されたシングルトンオブジェクト シングルトンオブジェクト オブジェクトヘッダを含めて28byte 常に同じアドレスに格納される
Rust 独立した「真偽値型」として定義され、1byteの整数値として表現 強型の独立した型 1 byte true=1, false=0 と明確

まとめ

今回は、各言語のBooleanについて深掘りしました。
皆さんの学習の一助になれば幸いです。

Discussion