Это ошибка в методе # to_proc? (Ruby 1.8.7)

Учитывая следующий метод, который принимает один аргумент:

def foo(arg); p arg; end

Я могу вызвать его с пустым массивом:

foo([])
# prints []

Я также могу сохранить его как объект Method и вызвать его с помощью пустого массива с тем же результатом:

method(:foo).call([])
# prints []

Однако, если я преобразовываю объект Method в Proc и вызываю его с пустым массивом, я получаю ArgumentError:

method(:foo).to_proc.call([])
# ArgumentError: wrong number of arguments (0 for 1)
#   from (irb):4:in `foo'
#   from (irb):4:in `to_proc'
#   from (irb):10:in `call'

Я ожидал, что он будет вести себя так же, как в предыдущих двух случаях. Вместо этого, похоже, он ведет себя так, как будто я написал foo(*[]). Однако, если я назову его непустым массивом, он будет вести себя так, как я ожидал:

method(:foo).to_proc.call([1])
# prints [1]

Поэтому он разрушает аргумент, но только если аргумент оказывается пустым массивом. И только если я назову Method#to_proc.

Есть ли пробел в моем понимании того, как работают Method или Proc, или это ошибка?

Я запускаю Ruby 1.8.7-p299. Я наблюдаю такое же поведение в 1.8.6-p399 и 1.8.7-head. Однако я не вижу его в 1.9.1-p378: все три формы печатают [] при вызове с пустым массивом.

Ответы

Ответ 1

Это почти наверняка ошибка,

Я подозреваю, что причина, по которой это происходит, заключается в том, что вызов метода # имеет значение arty -1 (ожидание массива аргументов C), а вызов ProС# имеет arity -2 (ожидая массив Ruby аргументов).

Там еще один полезный комментарий в eval.c выше определения вызова ProС#, который может пролить свет на проблему:

/* CHECKME: правильны ли семантики проверки аргументов? */

Возможно, мы должны изменить это на FIXME: p