他の言語に慣れた人がRubyを使ったときにつまずきがちな9つのポイント

他の言語に慣れた人がPythonを使ったときにつまずきがちな9つのポイントの続編。ささださんも書いています see: だいありー

0は真, 空文字列も真

C言語などと違って、0は偽ではない。PythonJavaScript, PHPと違って空文字列も偽ではない。

>if 0 then print "true!\n" end
true!

> if "" then print "true!\n" end
(irb):1: warning: string literal in condition
true!

括弧がなくても0引数での関数呼び出しが起きる

PythonJavaScriptでは式中に現れた関数名は関数を指す。しかしRubyでは0引数での呼び出しが行われる。

# Python
>>> def foo(): print "foo!"
... 
>>> foo
<function foo at 0x100445f50>
# Ruby
> def foo() print "foo!\n" end
=> nil
> foo # メソッド呼び出しが起きる
foo!
=> nil

変数はすべて参照

> a = []
> b = a
> b << 1
> a
=> [1]

ソースコードエンコーディング

Ruby1.9ではソースコードエンコーディングを指定せずにソースコード中でASCII以外の文字を使うとシンタックスエラーになる。

$ cat > t.rb
p "ほげ"
$ ruby1.9 t.rb 
t.rb:1: invalid multibyte char (US-ASCII)
t.rb:1: invalid multibyte char (US-ASCII)

PythonScheme同様の方法でソースコードエンコーディングを指定できる。詳しいことはこちら:多言語化

# -*- coding: utf-8 -*-
p "ほげ"

1.8で下記のようなコードをSJISで書くと構文エラー(unterminated string meets end of file)になる。ruby起動時のオプションに-Ksを指定する必要がある。

print "機能"

JIS規格に準拠した処理系が、ソースコードにUS-ASCII以外の文字が入っていた場合にどういう挙動をするかは未規定である。

整数がオーバーフローしない

整数の加減乗除やシフト演算で整数(Fixnum)の範囲を超えた場合、Cなどのようにあふれたビットを捨てて範囲内に収めるのではなく、上限のないBignumに変換される。そして文字列表示を見ても区別がつきにくい。

> x = -4611686018427387904
> x.class
=> Fixnum
> x /= -1
=> 4611686018427387904
> x.class
=> Bignum

Cで書かれたアルゴリズムを逐語訳したりすると、かなり気づきにくいバグが入ってしまう。

同名のクラス定義があった場合、衝突せずに合成される

class Foo
  def x; 1 end
end

class Foo
  def y; 2 end
end

p Foo.new.x #=> 1 と表示される
p Foo.new.y #=> 2 と表示される

場合によっては便利に使えるケースもあるかも知れない。ソースコードを読む人が意図的に合成されていることを知らないと混乱しそうではある。

あと3つは募集中です