Подтвердить что ты не робот

Как работает метод [квадратная скобка] в 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

Я не понимаю, как работает метод определения []?

Почему ключ за пределами [], но когда метод вызывается, он находится внутри []?

Может ли ключ быть без круглых скобок?

Я понимаю, что есть намного лучшие способы написать это, и я знаю, как писать свой собственный метод, который работает, но этот метод [] просто сбивает меня с толку... Любая помощь очень ценится, спасибо

4b9b3361

Ответ 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

то же самое работает с /, *, - и многими другими.