Receiver reference method "Array # each"
This is very similar to the answer I gave here at fooobar.com/questions/2423873 / ... , but slightly different.
First, you can create an self
array-bound scope and then execute each
on that scope:
[1].instance_exec do
# in this scope, self is the array
# thus we can use just 'each' because the self is inferred
each do |x|
# note that since 'class' is a special keyword,
# it needs to be explicitly namespaced on self
puts self.class, x
end
end
# => prints Array, 1
You can create a utility function for this if you like:
def bound_each(enumerable, &blk)
enumerable.instance_exec { each &blk }
end
bound_each([1]) { |x| puts self.class, x }
# prints Array, 1
source to share
You can call your method each
in a block Object#tap
and refer to the original receiver as such.
[1, 2, 3].tap { |i| i.each { |j| p i.dup << j } }
# [1, 2, 3, 1]
# [1, 2, 3, 2]
# [1, 2, 3, 3]
#=> [1, 2, 3]
This is the receiving object [1, 2, 3]
and is passed to a block variable i
that we can use locally or in nested scopes like each
block.
Avoid modifying the receiving object, otherwise you might get unwanted results like an infinite array. Use dup
can eliminate this possibility.
source to share
This is an interesting question. This is not possible as far as I know - the closest I can do is use inject
(or reduce
) and explicitly pass the receiver as an argument. A bit pointless, but there might be a use case for it that I don't see:
a = [1,2,3]
a.inject(a) do |this, element|
this == a #=> true
this.include?(element) #=> true
this
end
Aside from looking a little redundant, you should be sure to return at this
the end of each iteration, as the return value will become this
in the next iteration. For this reason (and the fact that you can just reference your collection in a block each
, as in David's answer), I don't recommend using that.
Edit - as Plain Lime pointed out in the comments - I missed the obvious one Enumerator#with_object
, which has the same (rather pointless) one but without the lack of backtracking this
at the end of each iteration. For example:
a = [1,2,3]
a.map.with_object(a) do |element, this|
this == a #=> true, for each iteration
end
I still don't recommend using this.
source to share