Странно рубиновое поведение
Мне нужно проверить, является ли переменная массивом, и если нет, преобразовать ее в единицу, прежде чем приступить к дальнейшей обработке. Итак, мой код выглядит так:
class Test < Struct.new(:args)
def eval
p "1. #{args}"
args = (args.instance_of? Array) ? args : [args]
p "2. #{args}" # woah! [nil]?
# ...other things, with "args" being an array for sure..or not?!?
end
end
Я совсем новичок в ruby, так что, возможно, это не очень идиоматично, но мне кажется, что этот код должен по крайней мере работать. Вместо этого во второй раз я печатаю args
переменная, это [nil]
, Обратите внимание, что если я изменю метод eval
немного:
def eval
p "1. #{args}"
a = args
args = (a.instance_of? Array) ? a : [a]
p "2. #{args}"
end
все работает как положено. Итак, есть что-то очень специфичное для класса Struct, которого я не понимаю, или что-то подозрительное происходит здесь? (используя ruby 1.9.3-dev на macosx, используя rvm)
1 ответ
На самом деле есть идиома Ruby для того, что вы пытаетесь сделать: [*args]
, *
в этом контексте называется оператором сплат:
Если вы передадите массив, splat "сведет" массив в новый, если вы передадите один аргумент, он станет массивом из одного элемента.
Для странного поведения: мне кажется, что вы создаете локальную переменную args
в вашем eval
метод, который инициализируется nil
потому что это на LHS задания. Тогда троичный оценивается как ложный, потому что args
не является массивом и создает массив из текущего значения, которое по-прежнему nil
, Если args
будет переменная экземпляра (@args
), все будет работать так, как вы ожидаете. Другими словами, при наследовании от Struct
дам тебе args
а также args=
методы, это не даст вам @args
переменная экземпляра.