RubyistがPythonを使うとき — 似ているようで違う二つの言語の内情
Rubyのブロック、オープンクラス、暗黙のreturnがPythonではどうなるか
RubyとPythonは同じ時代に生まれた動的型付け言語だ。どちらもPerlの影響を受け、どちらも「開発者の幸せ」を重視すると言う。しかし並行して使うと哲学の違いが鮮明になる。
ブロックがない
RubyistがPythonで最初にぶつかる壁がこれ。
# Ruby — ブロックでリソース管理
File.open('data.txt') do |f|
puts f.read
end
# Python — with文(コンテキストマネージャ)
with open('data.txt') as f:
print(f.read())
結果は同じ。メカニズムが違う。Rubyにはブロックという汎用構造がある。Pythonは__enter__/__exit__プロトコルという専用メカニズムを作った。
Rubyブロックの強み:どんなメソッドにも渡せる。3.times { puts 'hello' }が自然にできる。Pythonではlambdaや関数を引数で渡す。できるけど、ブロックほど自然ではない。
全てが式(expression) vs 文(statement)
Rubyではほぼ全てが値を返す。
# Ruby — ifは式
status = if score >= 90 then 'A' else 'B' end
# 暗黙のreturn
def greet(name)
"Hello, #{name}"
end
# Python — ifは文
status = 'A' if score >= 90 else 'B'
# returnを必ず書く
def greet(name):
return f"Hello, {name}"
Pythonでreturnを書き忘れるとNoneが返る。Ruby習慣で最終行だけ書いてreturnを入れないと、デバッグに時間を取られる。
オープンクラス vs クローズドクラス
# Ruby — 既存クラスをどこでも開ける
class String
def shout
upcase + '!!!'
end
end
'hello'.shout # => 'HELLO!!!'
Python組み込み型はC実装で修正不可。「既存クラスを触らない」がPythonの哲学。Railsの3.days.agoを可能にする魔法 — Python世界ではやらない。予測可能だが、表現力は少し劣る。
Enumerable vs itertools + comprehension
# Ruby — メソッドチェーンが左から右に読める
users.select { |u| u.active? }.map(&:name).first(5)
# Python — リスト内包表記
[u.name for u in users if u.active][:5]
Rubyのチェーンは自然。Pythonの内包表記は独自文法 — 最初は違和感あるが慣れると簡潔。ただし3段階以上ネストすると読みにくい。そこでRubyのチェーンが恋しくなる。
明示的self vs 暗黙のself
Pythonのメソッド第一引数self、Rubyistにはかなり煩わしい。
Python:「明示は暗黙に勝る」(PEP 20)。Ruby:「プログラマの幸福のためにタイピングを減らす」。この差がself一つにも表れる。
結局どちらが良いか?
質問が間違っている。Rubyは「書いて気持ちいいコード」を追求し、Pythonは「誰が読んでもわかるコード」を追求する。RubyはDSL作成に強く、Pythonはチーム開発の一貫性に強い。
RubyistがPythonで一番辛いのは機能の欠如ではなく美学の違いだ。できることはほぼ同じ。「何が良いコードか」の答えが違う。
キーポイント
Rubyブロック → Pythonコンテキストマネージャ(with) + lambda — 汎用 vs 専用
Rubyは暗黙のreturn、Pythonは明示的return必須 — 忘れるとNone
Rubyオープンクラス vs Python封印された組み込み型 — monkey patching不可
Enumerableチェーン vs リスト内包表記 — 3段階超えるとチェーンが恋しい
明示的self vs 暗黙のself — 「明示は暗黙に勝る」vs「開発者の幸福」