A method that applies self to a proc

2019-09-06 00:04发布

I want to have a method defined on Object that takes a block and applies the receiver to the block. An implementation will be like the following:

class Object
    def apply ≺ pr.call(self) end
end

2.apply{|x| x * 3} # => 6

Is there already a standard way to do this or a well known library that has a method with similar use? If so, I didn't want to reinvent the wheel.

It happens to me very often that, I have a method that takes an optional block, and when there is no block, I want to return some return_value calculated within the method, but when there is a block, I want to return the return value of the return_value applied to the block. For now, I have bunches of lines like:

def method ..., &pr
  ...
  pr ? pr.call(return_value) : return_value
end

but I want to consistently write

def method ..., &pr
  ...
  pr ? return_value.apply(&pr) : return_value
end

or even better, with a slightly modified definition of apply,

def method ..., &pr
  ...
  return_value.apply(&pr)
end

3条回答
我欲成王,谁敢阻挡
2楼-- · 2019-09-06 00:22

I guess Object.tap is what you are looking for:

"Abc".tap do |str|
  puts str
end
查看更多
ら.Afraid
3楼-- · 2019-09-06 00:22

(Aftwer reading OP's edit) AFAIK the canonical way to write this is:

def purpose(*args)  #no &bl or &pr
  res = 42 #huge calculation
  return res unless block_given?
  yield res
end

p purpose(1,2)
purpose{|n| puts "from the block: #{n}"}
查看更多
可以哭但决不认输i
4楼-- · 2019-09-06 00:32

Is that not identical to def apply; yield self; end? – steenslag

@steenslag Yes. It is. I want to have that effect with self as the receiver. – sawa

Is this what you mean?

2.instance_eval { * 3 }
# => 6

Unfortunately, that doesn't work. instance_eval simply runs code as if the receiver was self. Operators don't presume self as the receiver, so you'd actually have to write this:

2.instance_eval { self * 3 }
# => 6

However, as a proof of concept, this is possible:

Numeric.send(:define_method, :plus) { |x| self + x }
2.instance_eval { plus 3 }
# => 5
查看更多
登录 后发表回答