Как работает метод [квадратная скобка] в Ruby?
Я прохожу через Программирование Ruby - прагматичное руководство для программистов и наткнулся на этот фрагмент кода:
class SongList
def [](key)
if key.kind_of?(Integer)
return @songs[key]
else
for i in [email protected]
return @songs[i] if key == @songs[i].name
end
end
return nil
end
end
Я не понимаю, как работает метод определения []?
Почему ключ за пределами [], но когда метод вызывается, он находится внутри []?
Может ли ключ быть без круглых скобок?
Я понимаю, что есть намного лучшие способы написать это, и я знаю, как писать свой собственный метод, который работает, но этот метод [] просто сбивает меня с толку... Любая помощь очень ценится, спасибо
Ответы
Ответ 1
Методы в рубине, в отличие от многих языков, могут содержать некоторые специальные символы. Один из них - синтаксис поиска массива.
Если вы должны были реализовать свой собственный хеш-класс, где, когда вы извлекаете элемент в свой хэш, вы хотели бы его отменить, вы могли бы сделать следующее:
class SillyHash < Hash
def [](key)
super.reverse
end
end
Вы можете доказать это, вызвав хэш со следующим:
a = {:foo => "bar"}
=> {:foo=>"bar"}
a.[](:foo)
=> "bar"
a.send(:[], :foo)
=> "bar"
Таким образом, def [] определил метод, который используется, когда вы делаете my_array["key"]
Другие методы, которые могут показаться вам странными:
class SillyHash < Hash
def [](key)
super.reverse
end
def []=(key, value)
#do something
end
def some_value=(value)
#do something
end
def is_valid?(value)
#some boolean expression
end
end
Чтобы уточнить, определение метода []
не связано с массивами или хэшами. Возьмем следующий (надуманный) пример:
class B
def []
"foo"
end
end
B.new[]
=> "foo"
Ответ 2
Это просто синтаксический сахар. Существуют определенные синтаксические шаблоны, которые транслируются в сообщениях. В частности,
a + b
совпадает с
a.+(b)
и то же самое относится к ==
, !=
, <
, >
, <=
, >=
, <=>
, ===
, &
, |
, *
> , /
, -
, %
, **
, >>
, <<
, !==
, =~
и !~
.
Кроме того,
!a
совпадает с
a.!
и то же самое относится к ~
.
Тогда
+a
совпадает с
[email protected]
и то же самое относится к -
.
Плюс,
a.(b)
совпадает с
a.call(b)
Существует также специальный синтаксис для сеттеров:
a.foo = b
совпадает с
a.foo=(b)
И последнее, но не менее важное: для индексирования есть специальный синтаксис:
a[b]
совпадает с
a.[](b)
и
a[b] = c
совпадает с
a.[]=(b, c)
Ответ 3
квадратные скобки - это имя метода как Array#size
, у вас есть Array#[]
как метод, и вы можете использовать его, как и любой другой метод:
array = [ 'a', 'b', 'c']
array.[](0) #=> 'a'
array.[] 1 #=> 'b'
array[2] #=> 'c'
последний имеет нечто вроде синтаксического сахара и делает то же самое, что и первый. Работа Array#+
аналогична:
array1 = [ 'a', 'b' ]
array2 = [ 'c', 'd' ]
array1.+(array2) #=> [ 'a', 'b', 'c', 'd' ]
array1.+ array2 #=> [ 'a', 'b', 'c', 'd' ]
array1 + array2 #=> [ 'a', 'b', 'c', 'd' ]
Вы даже можете добавить такие номера:
1.+(1) #=> 2
1.+ 1 #=> 2
1 + 1 #=> 2
то же самое работает с /
, *
, -
и многими другими.