Рубиновый метод с параметрами в двойных скобках - PullRequest
0 голосов
/ 08 февраля 2019

Я встретил следующий код в библиотеке erb.Обратите внимание на двойной (( )):

class MyTest
  def location=((filename, lineno))
    @filename = filename
    @lineno = lineno if lineno
  end
end

Следующий метод locatia= представляет собой другую версию без (( )) для тестирования:

class MyTest    
  def locatia=(filename, lineno)
    @filename = filename
    @lineno = lineno if lineno
  end
end

Я получил такой результат:

a = MyTest.new
a.location = "foo", 34
a # => #<MyTest:0x2a2e428 @filename="foo", @lineno=34>

b = MyTest.new
b.location = "foo"
b # => #<MyTest:0x2a2e338 @filename="foo">

c = MyTest.new
c.locatia = "foo", 34
c # >> `locatia=': wrong number of arguments (given 1, expected 2) (ArgumentError)

Версия с двойными скобками работает нормально.Тот с одним проваливается.Он должен быть указан на некотором уровне исходного кода.Есть какие-нибудь подсказки?

Ответы [ 2 ]

0 голосов
/ 08 февраля 2019

Немного необычно видеть это в рабочем коде, но здесь происходит расширение списка в списке аргументов:

def location=((filename, lineno))
end

Что это означает, что вы называете это так:

x.location = 1,2

Где те получают , расширенные на два отдельных аргумента.Метод мутатора может принимать только один аргумент, но этот аргумент может быть списком, и вы можете расширить этот аргумент до нескольких значений.

Обычно вы видите это в итераторах, как:

{ a: 'b', c: 'd' }.each_with_index.map do |(k,v), i|
  # k, v come in as a pair, i is separate
end

Хотядаже тогда это довольно редко.

Вы можете увидеть это и в других случаях:

a = [ 1, 2 ]
b = 3

# Without list expansion, just one-to-one assignment
x, y, z = a, b
# x => [ 1, 2 ]
# y => 3
# z => nil

# With list expansion
(x, y), z = a, b
# x => 1
# y => 2
# z => 3
0 голосов
/ 08 февраля 2019

Разрушение.

location= принимает один параметр.Предполагается, что этот параметр является массивом, и он структурирован так, что первый элемент массива переходит в filename, а второй в lineno.Внешние скобки - это нормальные (обычно необязательные) скобки определения метода;внутренние скобки указывают структуру первого (и единственного) параметра.

Вот еще один пример разрушения на работе:

{ foo: 17, bar: 34 }.each.with_index { |(key, value), index|
  p [key, value, index]
}
# => [:foo, 17, 0]
#    [:bar, 34, 1]

Hash#each генерирует пары [key, value];Enumerator#with_index генерирует пары [value, index].Примените их оба, и вы получите [[key, value], index], переданный в блок.Мы могли бы просто сделать это:

{ foo: 17, bar: 34 }.each.with_index { |pair, index|
  key = pair[0]
  value = pair[1]
  p [key, value, index]
}

, но это намного проще с деструктуризацией.Мы могли бы даже написать (key, value) = pair (или key, value = pair, так как массивы с одним значением автоматически деструктурируются при назначении с несколькими значениями) в качестве другого примера разрушения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...