defined?

変数が定義されているかどうかは、defined?演算子で調べられます。defined?はメソッドではありません。

if defined?(x)
    print "x is defined.\n"
else
    print "x is not defined.\n"     # こちら
end

x = nil

if defined?(x)
    print "x is defined.\n"         # こちら
else
    print "x is not defined.\n"
end

最後は受けねらいです。

puts defined?(nil)      # => nil
puts defined?(true)     # => true
puts defined?(false)    # => false
puts defined?(Integer)  # => constant
puts defined?(3)        # => expression
puts defined?(String)   # => constant
puts defined?("String") # => expression
puts defined?(xxxx)     # => nil
puts defined?(puts)     # => method
puts defined?(defined?)
# parse error, unexpected ')'

irb: インタラクティブなRuby

irbを使うと、インタラクティブRubyを使うことができます。以下では「じゃ、そのクラスは何よ?」としつこく尋ねてみました。

irb(main):001:0> nil
=> nil
irb(main):002:0> nil.class
=> NilClass
irb(main):003:0> nil.class.class
=> Class
irb(main):004:0> nil.class.class.class
=> Class

ブロックパラメータは外部から継承

Rubyでは、ブロックパラメータと同じ名前の変数が前にあったらそれを使います。ブロックパラメータは新しいスコープを作るわけではないのでしょうか。これはちょっと驚きです。

a = [ 1, 2, 3 ]
rubyco = 100
p rubyco            # => 100
a.each { |rubyco|
    # ...
}
p rubyco            # => 3

もしも前になかったら、外に飛び出せるわけではないようです。

a = [ 1, 2, 3 ]
a.each { |rubyco|
    p rubyco
}
p rubyco

実行結果はこうなります。

1
2
3
undefined local variable or method `rubyco' for main:Object (NameError)

@@でクラス変数

Rubyでは、@@で名前を始めるとクラス変数になります。

class Rubyco
    @@x = 0

    def self.inc
        @@x += 1
    end

    def self.dec
        @@x -= 1
    end

    def self.value
        @@x
    end
end

p Rubyco.value      # => 0

Rubyco.inc
p Rubyco.value      # => 1

Rubyco.dec
p Rubyco.value      # => 0

定数の中身の変更

名前を大文字で始めると定数になります。定数に再代入すると警告がでますが、定数として参照しているオブジェクトの中身を変更しても警告はでません。

A = [ 1, 2, 3 ]
p A[0]          # => 1

A[0] = 100
p A[0]          # => 100

変数は型なし

Rubyでは、変数に型はありません。つまり、ある変数に異なる型のオブジェクトを代入することができます。

x = "hello"
p x.class

x = %r/hello/
p x.class

x = [ "hello" ]
p x.class

実行結果はこうなります。

String
Regexp
Array