Feature #8563
closedInstance variable arguments
Description
Often times, people want to assign given arguments to instance variables, especially inside the method initialize:
I propose to let method definition take instance variables as arguments so that:
would be equivalent as above.
Updated by nobu (Nobuyoshi Nakada) about 13 years ago
- Category set to syntax
- Status changed from Open to Assigned
- Assignee set to matz (Yukihiro Matsumoto)
- Target version set to 3.0
Updated by phluid61 (Matthew Kerwin) about 13 years ago
Question: would this be valid?
Asking here, because #5825 as written only talks about initialize method, and the above construct wouldn't make sense there.
Updated by matz (Yukihiro Matsumoto) about 13 years ago
Updated by sawa (Tsuyoshi Sawada) about 13 years ago
Updated by nobu (Nobuyoshi Nakada) about 13 years ago
Updated by headius (Charles Nutter) about 13 years ago
Worth pointing out that blocks used to support this:
Basically, it supported anything you can have on the LHS of a normal assignment:
I believe it was taken out in 1.9 because it made argument processing a lot more complicated, but then 1.9 added the ability to do multiple-assignment grouping, default values, and other masgn features to all argument lists anyway. It doesn't seem like it would be too terribly complicated to add this back in, but I wonder about the OTHER reasons that non-local variable assignment was removed from argument lists in the first place.
As for the utility of the feature, I'd like it but I can live without it. It does seem rather un-Ruby to have to declare locals and do the assignment when all you want is to set an instance variable...especially when you have a lot of instance variables.
Note also that for a trivial initialize, where the only line is a multiple-assignment to set instance variables, every initialize call pays the cost of creating an Array for the masgn (see my rejected request in https://bugs.ruby-lang.org/issues/6668).
Updated by Anonymous about 13 years ago
@matz (Yukihiro Matsumoto): If define_attr_initialize is an option, then there is a question of named / ordered qualifier, either as:
or as (and I like this second option better):
Both of these would obviously stand for (using @sawa's notation):
Besides that, I feel that attr_reader, attr_writer, attr_accessor could use:
Which also brings to my mind, that now that we have named args firmly in place, following
syntactic flavors of Module#attr_... beg to exist:
Updated by phluid61 (Matthew Kerwin) about 13 years ago
boris_stitnicky (Boris Stitnicky) wrote:
Which also brings to my mind, that now that we have named args firmly in place, following
syntactic flavors ofModule#attr_...beg to exist:
If you propose this as a feature, I will +1 it. Also I have some questions about it which probably should not pollute the current feature request.
Updated by Anonymous about 13 years ago
If you propose this as a feature, I will +1 it. Also I have some questions about it which probably should not pollute the current feature request.
I have proposed is as #8564.
Updated by nobu (Nobuyoshi Nakada) over 10 years ago
- Description updated (diff)
Updated by nobu (Nobuyoshi Nakada) almost 10 years ago
- Has duplicate Feature #12578: Instance Variables Assigned In parameters ( ala Crystal? ) added
Updated by Eregon (Benoit Daloze) almost 10 years ago
Anonymous wrote:
@matz (Yukihiro Matsumoto): If
define_attr_initializeis an option, then there is a question of named / ordered qualifier, either as:
You could have simply:
But this starts to look much like a macro to me.
One problem with the proposed define_attr_initialize is once some extra behavior needs to be added to initialize,
there is no choice but to desugar everything (write ivar assignments manually).
The original proposition does not have this issue.
IMHO many constructors usually need some custom behavior after some time,
and so paying the "cost" upfront of doing manual assignments is worth it in many cases.
Updated by rosenfeld (Rodrigo Rosenfeld Rosas) almost 10 years ago
Even if define_attr_initialize would accept a block to enhance the initializer besides initializing instance variables it doesn't support default arguments. I'd certainly prefer the original proposal which I find more useful. It's not obvious what array.each(&:to_i) does either but people get used to it because it's handy. I think it's the same about this proposal although it's quite familiar for people using this feature in other languages like CoffeeScript and Crystal among others.
Updated by rosenfeld (Rodrigo Rosenfeld Rosas) almost 10 years ago
Also it doesn't handle variable arguments, extra options that shouldn't be assigned to instance variables or &block.
Updated by nobu (Nobuyoshi Nakada) over 9 years ago
- Has duplicate Feature #12820: Shorter syntax for assigning a method argument to an instance variable added
Updated by marcandre (Marc-Andre Lafortune) over 8 years ago
matz (Yukihiro Matsumoto) wrote:
Arguments are giving names to passed values, which is different from attribute (instance variables) initialization. I think they should be separated clearly.
This may be a valid theoretical distinction, but what does this change in practice?
I feel there would be about no additional cognitive load if this was accepted. It is most probably the most requested feature
This is not surprising, since a majority of initialize with arguments is doing that!
And for most of the cases, only
initializeneeds this kind of initialization.
Indeed. This doesn't change the case that a majority of initialize methods needs this kind of initialization.
Here's an example Rails app (which I didn't write): https://github.com/WikiEducationFoundation/WikiEduDashboard/search?utf8=%E2%9C%93&q=def+initialize&type=
A gem I'm using a lot these days: https://github.com/whitequark/parser/search?utf8=%E2%9C%93&q=def+initialize&type=
Since keyword arguments, I feel that's even more true, since Struct is no longer as useful.
With all due respect, this is not a good idea and it can't solve the issue. As was pointed out, there are many more cases that it doesn't handle:
- keyword arguments (that's absolutely major!)
- defaults
- dealing with other arguments
- doing extra code
I'd also mention the additional cognitive load involved.
Note that it has always been trivial to implement define_attr_initialize in pure Ruby. I've never seen such code though.
Take the top 100 gems, a few web apps, make an inventory of the initialize with parameters. I'm betting that the vast majority of these methods would be simplified by allowing instance variable arguments. I doubt that define_attr_initialize would help any but a small minority.
Updated by ko1 (Koichi Sasada) over 8 years ago
Not so serious idea.
Updated by matz (Yukihiro Matsumoto) over 8 years ago
- Status changed from Assigned to Rejected
My opinion has not been changed from https://bugs.ruby-lang.org/issues/8563#note-3
I am strongly against code like
I don't care about define_attr_initialize not being "the solution".
Matz.
Updated by ko1 (Koichi Sasada) over 8 years ago
Oops.
class Binding
def set_attributes(attrs = self.eval('method(__method__).parameters.map{|t, v| v}'))
attrs.each{|attr|
self.receiver.instance_variable_set(:"@#{attr}", self.local_variable_get(attr))
}
end
end
class C
def initialize a, b
x = y = nil
binding.set_attributes
end
end
p C.new(1, 2) #=> #<C:0x000001f30a8b95d0 @a=1, @b=2>