Передача пустого хеша через двойной знак в рубине
Идея похожа на то, что вы сделали бы с декоратором в python, я не знаю, какие аргументы использует метод, поэтому я передаю *args, **kwargs в общем случае
Проблема возникает, когда я хочу передать пустой хеш как kwargs методу, который не принимает аргументов
def my_method
'I have run correctly'
end
args = []
kwargs = {}
my_method *args, **kwargs
=> ArgumentError: wrong number of arguments (given 1, expected 0)
Интересно, что только переменная kwargs кажется проблемой, так как:
my_method *args, **{}
=> 'I have run correctly'
Если вы можете предложить способ фактической передачи объекта метода в качестве параметра функции, это также было бы идеально.
1 ответ
Вы не можете передать произвольное количество аргументов в метод ruby, не объявив его в определении метода. Проходя просто *args
работает, потому что * args пусто, это в основном так, как будто вы не передаете аргументы методам, чего и ожидает my_method. С kwargs
, вы передаете пустой хеш в качестве аргумента. Так как метод объявлен без аргументов, возникает ошибка.
В общем случае способ сделать это в ruby будет примерно таким:
def my_method(*args, **kwargs)
'I have run correctly'
end
Если метод ruby может принимать неопределенное количество аргументов или аргументов ключевого слова, он должен быть явным в определении метода.
Однако чаще вы увидите такие идиомы:
def my_method(arg, opts={})
# do something
end
# Invoke the method like this:
# args == ['argument', 'another argument']
# opts == {opt1: 'val1', opt2: 'val2'}
my_method('some argument', opt1: 'val1', opt2: 'val2')
Что касается вашего наблюдения о my_method *args, **kwargs
действуя иначе, чем my_method *args, **{}
... Сначала я скажу, что если ваша мотивация в первую очередь связана с изучением Ruby, то я бы еще раз подчеркнул свою мысль о том, что kwargs обычно не используются в Ruby, по крайней мере, не так, как они используются в Python.
И после этого я скажу, что это очень странно.
Я замечаю, что:
[**kwargs] # => [{}]
[**{}] # => []
# And even more interesting:
[**{}.itself] # => [{}]
Так что я правильно сказал, что **kwargs
интерпретатор жалуется, потому что вы передаете пустой хэш методу, который не ожидает никаких аргументов. Но относительно того, почему это отличается от **{}
, Я не уверен. Я копаюсь сейчас, но мое нынешнее подозрение честно, что это случайность переводчика. Нет причин, по которым они должны оцениваться по-разному только потому, что один из двух назначен переменной...
Более того, использование оператора двойных сплатов не очень распространено, в основном из-за предпочтения opts={}
идиома описанная выше. Также это не тот случай использования, с которым многие столкнутся на практике. Программист должен был бы явно передать пустой хэш такому методу, когда они могут (независимо от того, kwargs или опции) просто пропустить аргумент. Так что да... Я думаю, что это может быть случайностью переводчика.