変わってから３年半ずっと気づかなかったRubyの変化にちょっと感動した

# はじめに

3年以上、気づかなかった Ruby のちょっとした変化に、最近、ようやく気づいて、そして、ちょっとだけ感動しました。

# Ruby の ArgumentError

次のスクリプトを実行するとArgumentError になります。

```ruby:arg.rb
def add(x, y)
  x + y
end

add(1)
```

そう、こんなエラーメッセージが出るのです。

```
$ ruby arg.rb
Traceback (most recent call last):
        1: from arg.rb:5:in `<main>'
        arg.rb:1:in `add': wrong number of arguments (given 1, expected 2) (ArgumentError)
```

アレッ？ こんなわかりやすいエラーメッセージだったっけ？ なんか違ったような...

# Ruby 2.2.9 以前

調べてみたら、Ruby 2.2.9 ではエラーメッセージが違っていました。

```
$ ruby arg.rb
arg.rb:1:in `add': wrong number of arguments (1 for 2) (ArgumentError)
        from arg.rb:5:in `<main>'
```

違いがわかりますか？ ちょっとした違いですが、

```
(1 for 2)
```

となってます。私は、こっちのメッセージの方に馴染みがありました。
馴染みはあるものの、このメッセージは、引数1つのメソッドに2つ引数渡してるからエラーなのか、引数2つのメソッドに引数1つで呼び出しているからエラーなのか、パっと見わかりにくいなあと思ってました。

```
(given 1, expected 2)
```

の方が引数2つを想定しているメソッドに引数1つしか渡してないからエラーというのがわかりやすいですよね。

# ちょっとしたことだけど感動

ちょっとした修正ですが、プログラマに易しい方向に Ruby が進化している良い修正だなと思いました。

調べてみたら、この修正がされるように行動を起こしている人達がちゃんといたのでした（当たり前ですが）。
不便なことをそのまま良しとせず、[要望を出す人](https://bugs.ruby-lang.org/issues/9025)がいて、その[要望に応える人](https://github.com/ruby/ruby/commit/927e18b3701662975182d1c0caeb9477af70817e)がいて、そういう行動を起こす人たちがいて、Ruby（や他のオープンソース・ソフトウェア）は進化し続けるんですねえ。

# おまけ

他の言語はどうなのか調べてみました。

## Python

Python で調べてみました。バージョン 3.7.3 です。

```python:arg.py
def arg(x, y):
    x + y

arg(1)
```

Python は TypeError で 引数 `y` が足りてないと教えてくれるんですね。

```shell
$ python arg.go
Traceback (most recent call last):
  File "arg.py", line 4, in <module>
    arg(1)
TypeError: arg() missing 1 required positional argument: 'y'
```

## JavaScript

JavaScript も調べてみました。 node 10.16.0 です。

```javascript:arg.js
function add(x, y) {
  return x + y;
}

add(1)
```

そうです。 JavaScript は引数が違ったくらいじゃエラーメッセージは出ないのです。

## Go

Go も調べてみました。 バージョンは、1.12.6です。

```go:arg.go
package main

func add(x int, y int) int {
	return x + y
}

func main() {
	add(1)
}
```

実際の関数をコールしたときの引数( `have` )と、関数の引数の情報 ( `want` ) を出力してくれます。

```shell
$ go build arg.go
# command-line-arguments
./arg.go:8:5: not enough arguments in call to add
        have (number)
        want (int, int)
```

## Elixir

Elixir も調べてみました。 バージョンは、1.8.2 です。

```elixir:arg.exs
defmodule Arg do
  def add(x, y) do
    x + y
  end
end

Arg.add(1)
```

エラーはエラーでも `UndefinedFunctionError` になります。Elixir は引数の数が違う同じ名前の関数を定義できるためですね。

```shell
$ elixir arg.exs
** (UndefinedFunctionError) function Arg.add/1 is undefined or private. Did you mean one of:

      * add/2

    Arg.add(1)
    (elixir) lib/code.ex:767: Code.require_file/2
```

## C

C言語も調べてみました。処理系によって異なるでしょうが、gcc 5.4.0 です。

```c:arg.c
int add(int x, int y) {
  return x + y;
}

int main(int argc, char **argv) {
  add(1);
  return 0;
}
```

思ったよりも親切なエラーメッセージです。

```
$ gcc arg.c
arg.c: In function ‘main’:
arg.c:6:3: error: too few arguments to function ‘add’
   add(1);
   ^
arg.c:1:5: note: declared here
 int add(int x, int y) {
     ^
```

# 参考情報

- [vm_insnhelper.c: improved error message for "wrong number...(The Ruby Language git repositories)](https://git.ruby-lang.org/ruby.git/commit/?id=927e18b3701662975182d1c0caeb9477af70817e)
- [vm_insnhelper.c: improved error message for "wrong number...(GitHub)](https://github.com/ruby/ruby/commit/927e18b3701662975182d1c0caeb9477af70817e)
- [Clarify the error message when calling a method with the wrong number of arguments](https://bugs.ruby-lang.org/issues/9025)