Запутался, когда использовать круглые скобки против блоков в Ruby - PullRequest
3 голосов
/ 16 марта 2012

на поверхности, Ruby очень похож на другие объектно-ориентированные языки, такие как Java, Php, C и т. Д.

но все становится немного странно, когда мы начинаем сталкиваться с блоками.

например, это работает

(0...8).max()
 => 7 

но это не

(0...8).map(puts "hello world")
hello world
ArgumentError: wrong number of arguments(1 for 0)

Очевидно, что метод map не принимает аргументы, а принимает блоки, поэтому передача вместо 1011 * на {} исправляет ошибку.

(0...8).map{puts "hello world"}
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
 => [nil, nil, nil, nil, nil, nil, nil, nil] 

И затем, есть некоторые методы, которые должны принимать оба - блоки и аргументы

8.downto(1){puts "hello world"}
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
 => 8 

Проблема, с которой я столкнулся, заключается в путанице, если я должен использовать (), {} или оба в данном методе. На основании чего принимается решение?

  • Исправлено ли это для каждого метода, и я просто должен помнить, что метод принимает (блоки или параметры)?
  • Или есть какие-то другие логические рассуждения, на основании которых принимается решение, если метод принимает блоки {} или параметры ()?

Пожалуйста, помогите мне понять

Ответы [ 3 ]

6 голосов
/ 16 марта 2012

Скобки после вызовов методов на самом деле необязательны.

(0...8).map{puts "hello world"} эквивалентно (0...8).map() {puts "hello world"}

Таким образом, вы не заменяете их.

Принятиеблоки полностью зависят от метода, они могут быть указаны в объявлении метода:

def method(param, &block)
  block.call
end

, что позволит получить доступ к блоку как к переменной изнутри метода и вызываться через block.call дляпример.

Их также можно использовать неявно с помощью ключевого слова yield:

def method(param)
  yield
end

Таким образом, вы должны обратиться к документации API, чтобы быть уверенным, что принято или нет.

2 голосов
/ 16 марта 2012

Вы используете скобки для передачи аргументов функции. Это всегда список объектов через запятую. Они могут быть результатом функции, но не обязаны. Функция, результатом которой они являются, всегда будет вызываться только один раз.

Пример:

x = Array.new
=> []
x.push(2)
=> [2]
x.push(7.modulo(4))
=> [2,3]

Вы используете блоки для передачи функционального поведения методу. Эти функции обычно предназначены для вызова с множеством разных аргументов или определенным количеством раз. puts "hello world" - это функция, которая печатает что-то, но возвращает только nil. Таким образом, вы почти никогда не будете пытаться использовать это как аргумент для функции (как если бы вы передавали nil этой функции), но обычно передаете это как блок функции, чтобы ее можно было вызывать несколько раз. *

Большую часть времени вам захочется, чтобы блок, передаваемый в функцию, использовал аргументы, чтобы она фактически выполняла что-то другое при каждом вызове.

Пример:

(0..8).each{ |number| 
  if number.odd?
    puts "#{number} is odd"
  end
}
=> 1 is odd
=> 3 is odd
=> 5 is odd
=> 7 is odd
=> => 0..8
2 голосов
/ 16 марта 2012

Должно быть задокументировано в API метода.

Если существует метод, который принимает аргумент, блок обычно является необязательным - в таком случае он используется для «уточнения» способа работы метода, например Hash.new, который может принимать аргумент (значение хеш-функции по умолчанию) и блок, который используется для выполнения умных действий во время инициализации значения ключа Но большинство методов, которые требуют блока, не принимают аргумент, например Array#select или Array#map.

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