Метод, который возвращает доход для объекта в Ruby - PullRequest
4 голосов
/ 28 сентября 2011

Есть ли в Ruby метод, который возвращает содержимое блока, переданного объекту?

Например, что если у меня есть объект, который я хочу поместить в массив?

В идеальном мире мы бы сделали (то, что я ищу):

"string".reverse.upcase.something{ |s| send(s) }

, что бы вернуть массив с моим объектом, как эквивалентно:

send("string".reverse.upcase)

который не может быть цепным, если у меня есть объект, с которого можно начать, и он может запутаться в более сложных сценариях.

Таким образом, метод something вернет оценку блока, как Array#map, но только для одного элемента.

Ответы [ 4 ]

4 голосов
/ 28 сентября 2011

Я не знаю, встроена ли такая вещь, но вы можете легко сделать это самостоятельно:

class Object
  def something(&block)
    block.call(self)
  end
end

p "foo".something { | o | [o] }
p 23.something { | x | p x; 42 }

дает

["foo"]      # object "foo" put into an array
23           # object handed to block
42           # something return block's result
1 голос
/ 11 октября 2017

Через шесть лет после первоначального вопроса в Ruby 2.5.0 было введено Object#yield_self, затем сокращено в Ruby 2.6 до #then:

 class Object
   def yield_self(*args)
     yield(self, *args)
   end
 end

[...]

Выполняет блок и возвращает его вывод.

( Ruby Feature # 6721 )

Например:

2.then{ |x| x*x }  # => 4
1 голос
/ 15 апреля 2014

Иногда мне хочется подобной функции в стандартной библиотеке.Например, имя может быть with или with_it

(повторение предыдущего кода с новым именем)

class Object
  def with_it(&block)
    block.call(self)
  end
end

Пример использования:

x = [1, 2, 3, 4, 5].map {|x| x * x }.with_it do |list|
   head = list.unshift
   list << head * 10
   list.join " / "
end

В отличие отto:

list = [1, 2, 3, 4, 5].map {|x| x * x }
head = list.unshift
list << head * 10
x = list.join " / "

В то время как последний легче понять, преимущество первого заключается в том, что переменные list и head ограничены, и, на мой взгляд, присвоение x более понятно (присвоение x должно быть вставлено в последнюю строку кода).Скоупинг был бы выгоден, если бы код был частью более крупного метода.

Таким образом, другой вариант использования with_it - поместить код в отдельный метод.Например:

def mult_head_and_join(list)
    head = list.unshift
    list << head * 10
    list.join " / "
end

x = mult_head_and_join [1, 2, 3, 4, 5].map {|x| x * x }

Не уверен, с чем здесь заключить, но, думаю, я бы проголосовал за включение with_it в стандартную библиотеку

1 голос
/ 28 сентября 2011

Вы ищете Object.tap ?

...