From: merch-redmine@... Date: 2018-07-11T05:03:48+00:00 Subject: [ruby-core:87901] [Ruby trunk Feature#14904] Make it possible to run instance_eval with zero-arguments lambda Issue #14904 has been updated by jeremyevans0 (Jeremy Evans). prijutme4ty (Ilya Vorontsov) wrote: > My use case is just a simple example showing why current behavior isn't as good as it can be. > > That's not about lambdas at all. That's about instance_eval being more clever, because there's no reason to yield receiver to a block when block can't handle it. It doesn't make lambda functions weaker, just about correct use of blocks of different arity by instance_eval. One problem here is the slippery slope. There are probably many core methods that take blocks where arguments are yielded, where potentially you could use them with zero argument lambdas. `Integer#times` comes to mind as the most obvious example. Having all these methods do block arity checking and changing what they yield based on the arity leads to added complexity, and I don't think adding such complexity is a good tradeoff. Especially in this case where you can just use `instance_exec`. ---------------------------------------- Feature #14904: Make it possible to run instance_eval with zero-arguments lambda https://bugs.ruby-lang.org/issues/14904#change-72911 * Author: prijutme4ty (Ilya Vorontsov) * Status: Open * Priority: Normal * Assignee: * Target version: ---------------------------------------- At a moment #instance_eval always yields an object to a given block. Though if we passed lambda as a block for instance_eval, its work depend on number of arguments. But I see no reason for such strictness when lambda gets zero arguments. In that case instance_eval can just skip yielding receiver to its block. It will reduce surprise for a newcomers who don't know the difference between proc and lambda. I got to this problem with code similar to this: ``` module ConfigParams def add_config_parameter(param_name, **kwargs, &block) # ... define_method(param_name){ kwargs[:default].call(self) } end end class KeyBindings extend ConfigParams add_config_parameter :undo add_config_parameter :redo, default: ->{ "shift+#{undo}" } end kb = KeyBindings.new kb.undo = 'ctrl+z' puts kb.redo # => shift+ctrl+z kb.redo = 'ctrl+y' ``` I want to allow user to express defaults with lambda which will be later evaluated in the context of an instance. It's a bit more readable than: ``` add_config_parameter :redo, default: proc{ "shift+#{undo}" } ``` And anyway, it'd be good if a user preferred to change proc into lambda didn't get strange exceptions. I've already found different solution - to use instance_exec instead of instance_eval. But I'm still sure that life could be easier it instance_eval handled zero-argument lambdas properly. Related: #10513 -- https://bugs.ruby-lang.org/ Unsubscribe: