Help us understand the problem. What is going on with this article?

Rubyで「+ 1」と「+1」が違うとき

More than 1 year has passed since last update.

ただのタイポによるエラーだったのだけど、「なんでArgumentError?」と考えてみたら面白かったのでメモ。

# Hogeクラスをつくって
class Hoge
  attr_accessor :count
end
hoge = Hoge.new

# hoge.countに値を入れる
hoge.count = 1
p hoge.count
# => 1

# hoge.countを1増やす
hoge.count = hoge.count + 1
p hoge.count
# => 2

# hoge.countをもう1増やそうと思うと
hoge.count = hoge.count +1
# => 3になる、と思いきやエラーになる
# ArgumentError:
#   wrong number of arguments (given 1, expected 0)

なぜかというと、1のコードは2のコードと同じ。

# 1
class Hoge
  attr_accessor :count
end

# 2
class Hoge
  def count
    @count
  end

  def count=(count)
    @count = count
  end
end

Rubyの場合、メソッドの引数は()に入れて渡すのだけれど、省略可能になっている。

hoge.count + 1
# => これはgetterのcountメソッドにアクセスして、その返り値に +1している
# 評価順はこう
# (hoge.count) + 1
hoge.count +1
# => この場合+1がgetterの引数になっている
# 評価順はこう
# hoge.count(+1)

+1の(スペースが間に入らない)場合、呼び出されるのはgetterのcountで、
getterは引数を取るよう定義されていないのでArgumentErrorが発生する。
だから、こうすれば通るけど、jsでよくかかれるような+=とは違う結果になる。

hoge.count = 1
hoge.count = +1
# => 1
# +1されて2が返るのではなく、何度やっても1が返る
hoge.count = +1
# => 1
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away