Pass block passed to method to another method in Ruby
Solution 1
You can reference the block explicitly
def discard(&block)
self - self.keep(&block)
end
or implicitly
def discard
self - self.keep(&Proc.new {})
end
In your case, I would suggest the first approach.
Solution 2
In the second example, &Proc.new {}
doesn't pass a block, it creates a new empty one. One should omit {}
and write it as self.keep(&Proc.new)
or just keep(&proc)
as self.
is redundant and proc
is the recommended synonym for Proc.new
:
# passes on the block or the absence of a block
def discard(&block)
self - keep(&block)
end
# passes on the block and fails if no block given
def discard
self - keep(&proc)
end
Both Proc.new
and proc
without a block use the block of the current method.
&proc
will fail if discard
doesn't get a block. So the first example is the best if you want to pass the block or the absence of a block (&nil
passes no block at all). The second example (as I changed it) is the best if missing block is an error.
In both cases, each time 'discard' is called, a new 'Proc' object is created, and it's not free.
Kappie001
Updated on October 14, 2020Comments
-
Kappie001 over 3 years
I'm trying to write a clone of the ruby
keep_if
anddelete_if
array methods. Here is my code.module Strain def keep self.inject([]) do |extracts, element| yield(element) ? extracts << element : extracts end end def discard self.inject([]) do |extracts, element| !yield(element) ? extracts << element : extracts end end end class Array include Strain end
This works. But I want to do something like:
def discard self - self.keep &block end
Desired behaviour:
[1, 2, 3].discard { |number| number < 2 } # => [2, 3]
So I need to pass the block that is passed to the
discard
method, to be passed on to thekeep
method. How do I achieve this? -
Kappie001 over 10 yearsThanks! I ended up solving it without passing the block, but I learned something nonetheless.
-
New Alexandria over 10 yearsI'm surprised that's all this answer needed. It sounded like a more complicated solution was desired. I'll try to formulate and ask the original way I read the question