2016-02-09 3 views
2

Недавно я задал вопрос (Equality test on three or more objects), где я пытался определить элегантный способ запуска теста равенства на множестве из трех или более объектов. Одним из решений оказалось, что-то вроде этого:Возможно ли, чтобы необъявленный перечислимый объект мог называть себя внутри блока?

array = [1,1,1,1] 
array.all? {|x| x == array.first } 

мне интересно, если можно было бы уменьшить это всего лишь одной линии, так что я мог бы сделать что-то , что будет истолковано как этот :

[1,1,1,1].all? {|x| x == [1,1,1,1].first } 
#=> true 

где-то я могу ссылаться на исходный объект на который вызывается блоком без предварительного объявить, что объект в предыдущей строке. В псевдо-коде, что я пытаюсь сделать что-то вроде этого:

[1,1,1,1].all? {|x| x == object_being_called_on_by_block.first } 
#=> true 

Я также попытался это, но не получилось:

[1,1,1,1].all? { |x| x == self.first } 

ответ

5

Это было часто задаваемый на SO, и часто запрашивается как функция на ядре Ruby. До сих пор основной разработчик Рубин рекомендует следующее:

[1,1,1,1].tap{|a| break a.all?{|x| x == a.first}} 

Если вы не возражаете о производительности, вы можете сделать:

[1,1,1,1].instance_eval{all?{|x| x == first}} 
+0

Я видел его однажды здесь: Http: // StackOverflow. com/questions/19834086/reference-the-invoking-object-in-the-pass-block-in-ruby, но не смог извлечь большую часть из этого примера. Это решение также кажется другим и более простым. Спасибо –

+0

ahh. поэтому в вашем втором примере вы могли бы использовать ключевое слово 'self', но оно было бы излишним. Попался. –