Это ошибка в Method#to_proc? (Рубин 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: там все три формы печатают [] при вызове с пустым массивом.


person Sam Stokes    schedule 18.01.2011    source источник
comment
Обычно я скептически отношусь к тому, что кто-то думает, что нашел ошибку в самом языке, но я не вижу другого объяснения такому поведению, особенно если учесть, что в версии 1.9 это работает так, как ожидалось. Надеюсь, кто-то более мудрый может просветить нас, потому что мне это очень любопытно.   -  person Jimmy    schedule 18.01.2011
comment
Я не всегда нахожу ошибку в самом языке, но если нахожу, то использую Ruby.   -  person Josh Lee    schedule 06.10.2011


Ответы (1)


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

Я подозреваю, что причина, по которой это происходит, заключается в том, что Method#call имеет арность -1 (ожидание массива аргументов C), а Proc#call имеет арность -2 (ожидание массива аргументов Ruby).

В eval.c есть еще один полезный комментарий над определением Proc#call, который может пролить дополнительный свет на проблему:

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

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

person Conrad Irwin    schedule 18.01.2011
comment
Это исправлено в Ruby 1.9, поэтому я думаю, что это БЫЛО ошибкой :) - person sethvargo; 18.01.2011