Reputation: 2328
I am just starting to do Groovy after mostly doing ruby.
It has a default 'block argument', it
, as it were, not officially the terminology for Groovy, but I'm new to Groovy.
(1..10).each {println(it)}
What about Ruby? Is there a default I can use so I don't have to make |my_block_arg|
every time?
Thanks!
Upvotes: 2
Views: 509
Reputation: 173552
From Ruby 2.7 onwards, you can use numbered block arguments:
(1..10).each { puts _1 }
Granted, this hasn't been very well documented; some references are still using @1
, but the above is tested on the official 2.7 version.
Upvotes: 0
Reputation: 21110
Like Andrey Deinekos answer explained there is no default. You can set the self
context using BasicObject#instance_eval or BasicObject#instance_exec. I don't recommend doing this since it can sometimes result in some unexpected results. However if you know what you're doing the following is still an option:
class Enumerator
def with_ie(&block)
return to_enum(__method__) { each.size } unless block_given?
each { |e| e.instance_eval(&block) }
end
end
(1..10).each.with_ie { puts self }
# 1
# 2
# 3
# 4
# 5
# 6
# 7
# 8
# 9
# 10
#=> 1..10
(1..10).map.with_ie { self * self }
#=> [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
(-5..5).select.with_ie { positive? }
#=> [1, 2, 3, 4, 5]
If you want to call one method you might as well do (-5..5).select(&:positive?)
, but when the objects you're iterating over have actual attributes it might be worth the trouble. For example:
people.map.with_ie { "#{id}: #{first_name} - #{last_name}" }
Keep in mind that if you have an local variable id
, first_name
or last_name
in scope those are used instead of the methods on the object. This also doesn't quite work for hashes or Enumerable methods that pass more than one block argument. In this case self
is set to an array containing the arguments. For example:
{a: 1, b: 2}.map.with_ie { self }
#=> [[:a, 1], [:b, 2]]
{a: 1, b: 2}.map.with_ie { self[0] }
#=> [:a, :b]
Upvotes: 1
Reputation: 52357
No, you don't have a "default" in Ruby.
Though, you can do
(1..10).each(&method(:puts))
Upvotes: 2