*why* does
foo
seems to always means
self.foo
except that
foo= ...
means
local variable foo = ...
and not
self.foo=
I find this keeps breaking up an otherwise uniform style in code, and almost
leads me towards abandoning #foo=(value) as a setter, and using #foo(value)
instead (with some distinguished sentinel value to distinguish getter from
setter, which I hate!)
I know that otherwise one would somehow have to indicate local variables.
Was this the main reason for this choice?
Does this issue (distinguishing local variables) have to be dealt with
anyway in any other contexts e.g. block-local variables?
Thanks.
In message "Re: foo= ... the only exception to the implicit-self rule ?"
on Thu, 6 Oct 2005 13:16:49 +0900, "itsme213" <itsm...@hotmail.com> writes:
|I know that otherwise one would somehow have to indicate local variables.
|Was this the main reason for this choice?
Yes.
|Does this issue (distinguishing local variables) have to be dealt with
|anyway in any other contexts e.g. block-local variables?
Yes.
matz.
I agree and ten not to use them for this reason. I suspect most others
feel the same. One nice way to create a "setter" is:
def foo(val=NilClass)
unless val == NilClass
@foo = val
end
@foo
end
foo #=> nil
foo(10)
foo #=> 10
Facets has this by the way (in next release):
require 'facet/kernel/attr_setter'
attr_setter :foo
> I know that otherwise one would somehow have to indicate local variables.
> Was this the main reason for this choice?
Yes. I think it was considered simply too "dangerous" to give setter
methods precedence. I'm not sure why since there tend to be quite few
of them, but I can see how it might catch one by suprise if their was a
setter defined that one didn't know about.
Some have suggested allowing a prefixed dot to mean 'self.', which
would help a little. Eg.
.foo=
But all other suggestions I can recall seem just as bad as having to
use 'self.'
> Does this issue (distinguishing local variables) have to be dealt with
> anyway in any other contexts e.g. block-local variables?
Do you mean defining vars local to a block? Perhaps?
{ x := 1 }
I can only imagine it has been suggested before though.
T.
You can avoid the sentinal (at a small cost):
def foo(*args)
case args.size
when 1
@foo = args[0]
when 0
@foo
else raise ArgumentError, "Too many args, #{args.size}"
end
end
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
"Yukihiro Matsumoto" <ma...@ruby-lang.org> wrote in message
> |Does this issue (distinguishing local variables) have to be dealt with
> |anyway in any other contexts e.g. block-local variables?
>
> Yes.
Have you decided whether 2.0 will require all local vars to be distinguished
via some syntax (e.g. |...|), or will 2.0 continue the current special-case
handling for self.foo= ?
However, the bigger issue is that writer and reader are now embedded in a
single method, and its impossible to do things like extend the writer to do
notifications and the like.
I guess a set_x(val) is the other alternative. Not sure which I dislike more
:-(
"Joel VanderWerf" <vj...@path.berkeley.edu> wrote in message
news:4344B6AC...@path.berkeley.edu...
In message "Re: foo= ... the only exception to the implicit-self rule ?"
on Thu, 6 Oct 2005 14:36:48 +0900, "itsme213" <itsm...@hotmail.com> writes:
|Have you decided whether 2.0 will require all local vars to be distinguished
|via some syntax (e.g. |...|), or will 2.0 continue the current special-case
|handling for self.foo= ?
I have never planned for any kind of explicit local variable
declaration. So the latter would be an answer.
matz.
I'm amazed that you find either the above or foo(x) more appealing
than simply using self.foo = x. In my personal opinion, the
assignment is clear, and made clearer by the presence of 'self'.
The only alternative that I would ever (personally) endorse would be
some sort of sigil for local variables like there is for global,
instance, and class variables. (Ick, more punctuation. Ick, more
typying. Ick, breaks backwards compatibility. But: at least it would
be consistent with other variables.) Something like:
%foo = 12 #The randomly-chosen % means local variable.
foo = 12 #Method call with implicit self.
But...really, I'm reasonably happy with the way things are now.
> On Oct 6, 2005, at 1:31 AM, itsme213 wrote:
>
>> I guess a set_x(val) is the other alternative. Not sure which I
>> dislike more
>> :-(
>>
>
> I'm amazed that you find either the above or foo(x) more appealing
> than simply using self.foo = x. In my personal opinion, the
> assignment is clear, and made clearer by the presence of 'self'.
[snip]
> But...really, I'm reasonably happy with the way things are now.
I believe I have only ever run into this problem when using
instance_eval(). Is it more pervasive than that?
With instance_eval() it could be argued that I'm already making
questionable choices, and this is just punishment, I think. ;)
James Edward Gray II
On Thu, 6 Oct 2005, James Edward Gray II wrote:
> On Oct 6, 2005, at 8:51 AM, Gavin Kistner wrote:
>
>> On Oct 6, 2005, at 1:31 AM, itsme213 wrote:
>>
>>> I guess a set_x(val) is the other alternative. Not sure which I dislike
>>> more
>>> :-(
>>>
>>
>> I'm amazed that you find either the above or foo(x) more appealing than
>> simply using self.foo = x. In my personal opinion, the assignment is clear,
>> and made clearer by the presence of 'self'.
>
> [snip]
>
>> But...really, I'm reasonably happy with the way things are now.
>
> I believe I have only ever run into this problem when using instance_eval().
> Is it more pervasive than that?
It's always the case that
bareword = <anything>
is parsed as a local variable assignment, not a method call. It's
really not a big deal, though -- it's a small price to pay for all the
times we don't have to use an explicit 'self' receiver.
David
--
David A. Black
dbl...@wobblini.net
> Have you decided whether 2.0 will require all local vars to
> be distinguished
> via some syntax (e.g. |...|), or will 2.0 continue the
> current special-case
> handling for self.foo= ?
This would really make ruby ugly. One of the beauties about
ruby is that you don't have to declare your variables (type or
existance). There are currently deficiencies in the
flexibility of variable scoping (only def/class/module can make
real local variables as far as I know), but I would hope that
could be solved without adding variable declarations.
Take a look at my RCR 307. In this one, you can do this:
obj.foo(arg1,arg2) = value
which would be equivalent to:
obj.send(:foo=,arg1,arg2,value)
Well, there is no reason this RCR couldn't handle the no
receiver case:
foo(arg1,arg2) = value
And the no receiver/no arg case:
foo() = value
which would be equivalent to:
self.foo = value
Just like the case when you already are using a local variable
"foo" where you use "foo()" to call the method foo, the same
can be done for assignment.
But, I think the self.foo=value syntax would still be preferred
by most. I'm not sure why you dislike it so much to propose
making such radical changes.
We are also talking about inside the class, so you know the
implementation. Unless foo= is complex, you might want to just
inline it whenever you want to use it (typically @foo=value).
This will give you a performance boost since you are cutting
out a method call (runtime is probably dominated by the method
call mechanism in most cases).
__________________________________
Yahoo! Mail - PC Magazine Editors' Choice 2005
http://mail.yahoo.com
> On Oct 6, 2005, at 1:31 AM, itsme213 wrote:
>> I guess a set_x(val) is the other alternative. Not sure which I dislike
>> more
>> :-(
>
> I'm amazed that you find either the above or foo(x) more appealing than
> simply using self.foo = x. In my personal opinion, the assignment is clear,
> and made clearer by the presence of 'self'.
it's just my opinion, but i think this is clear as a whistle:
require 'traits'
class Widget
traits %w( colour width height style )
end
class Button < Widget
color 'blue'
width 42
height 42
sytle 'swirly'
end
and this
require 'traits'
class C
traits(TRAITS = %w( a b c d e f ))
def initialize *args
TRAITS.each{|t| send t, args.shift}
end
end
visually the reader/writer method (writer if given arg) can be very, very nice
on the eyes and fingers - i just takes getting used to, like dropping the ';'
and '$' when moving from perl to ruby. ;-)
i espcially like that i can do
def init hash = {}
hash.each{|k,v| send k, v}
end
instead of
def init hash = {}
hash.each do |k,v|
meth = "#{ k }="
send meth, v
end
end
which always feels hackish to me
> The only alternative that I would ever (personally) endorse would be some
> sort of sigil for local variables like there is for global, instance, and
> class variables. (Ick, more punctuation. Ick, more typying. Ick, breaks
> backwards compatibility. But: at least it would be consistent with other
> variables.) Something like: %foo = 12 #The randomly-chosen % means local
> variable. foo = 12 #Method call with implicit self.
i think a symbol for local vars makes a TON of sense and is, really, in
keeping with ruby's design since every other scope is signaled by a symbol.
the rule could be
foo = 42
# if method exists foo=, use it
# else local var
foo := 42 # force local var
or
!foo = 42 # force local var
%foo = 42 # force local var
the thing with local vars is that, if ruby ALSO changed to lookup to search
for methods FIRST, and then to fall back on local you really wouldn't have to
use the local symbol/marker exectp in cases where a local var shadows a
method in the scope of object instance.
> But...really, I'm reasonably happy with the way things are now.
me too.
cheers.
-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| Your life dwells amoung the causes of death
| Like a lamp standing in a strong breeze. --Nagarjuna
===============================================================================
On Thu, 6 Oct 2005, Ara.T.Howard wrote:
> i think a symbol for local vars makes a TON of sense and is, really, in
> keeping with ruby's design since every other scope is signaled by a symbol.
That ("in keeping with Ruby's design") is only true if you assume that
the non-local variables somehow represent the truth about Ruby's
design in a way that the local ones do not. I would suggest, however,
that the "bareword" nature of local variables is 100% as much part of
Ruby's design as the $var nature of globals, etc., is.
The thing is, it doesn't have to be a "winner-take-all" contest
between two abstractions (with symbol/without symbol). It's a system;
it can have components that differ from each other, and/or are similar
to each other, in any number of ways.
> It's always the case that
>
> bareword = <anything>
>
> is parsed as a local variable assignment, not a method call.
You're right, of course.
I was thinking of how Ruby cleverly distinguishes local variables
from method calls (described on page 329 of the Pickaxe2) and
confused myself. Sorry for the noise.
James Edward Gray II
> Hi --
>
> On Thu, 6 Oct 2005, Ara.T.Howard wrote:
>
>> i think a symbol for local vars makes a TON of sense and is, really, in
>> keeping with ruby's design since every other scope is signaled by a symbol.
>
> That ("in keeping with Ruby's design") is only true if you assume that the
> non-local variables somehow represent the truth about Ruby's design in a way
> that the local ones do not. I would suggest, however, that the "bareword"
> nature of local variables is 100% as much part of Ruby's design as the $var
> nature of globals, etc., is.
true. methods are barewords too though - sometimes. note that i don't
__mind__ typing 'self.var = 42' - it just would be even nicer not to.
although part of me thinks it's clear to always use 'self' since implicit self
can obfusicate method calls in 4000 lines of code, espcially when the attr was
set dynamically or via a variable.
it's a tough problem for sure.
> The thing is, it doesn't have to be a "winner-take-all" contest between two
> abstractions (with symbol/without symbol). It's a system; it can have
> components that differ from each other, and/or are similar to each other, in
> any number of ways.
agreed.
I'm not sure local precedence is worth it though. Consider:
require 'yaml'
eqmeths = []
ObjectSpace.each_object{|o|
s = o.methods.select{ |m| m.to_s =~ /=$/ }
eqmeths |= s
}
y eqmeths
---
- "[]="
- "=="
- "==="
- ">="
- "<="
- ui=
- debug=
- sync=
- lineno=
- pos=
- default=
- ssl_available=
- uid=
- euid=
- gid=
- egid=
- groups=
- maxgroups=
- abort_on_exception=
- priority=
- critical=
- families=
- private_types=
- anchors=
- bufsize=
- version=
- verify_data=
- only_signed=
- verify_signer=
- verify_chain=
- verify_root=
- only_trusted=
T.
Can you explain what you mean? I'm not getting it.
Sure. Simply that there are very few setter methods built-in to Ruby.
On top of which almost all are particular to very special contexts. So
there's very little chance of surprise if setter methods were in fact
to have precendence over locals. -- In other words, one would know
every setter and thus know to avoid using it.
OTOH, I suppose it might present some issues with dynamic methods.
Here's another list by Class/Module instance_method. Between this list
and the prior I think that all of them --and there's quite a bit of
overlap.
require 'yaml'
eqmeths = {}
[Module,Class].each { |mod|
ObjectSpace.each_object(mod) { |c|
s = []
s |= c.public_instance_methods(false).select{ |m| m.to_s =~ /=$/
}
s |= c.private_instance_methods(false).select{ |m| m.to_s =~ /=$/
}
s |= c.protected_instance_methods(false).select{ |m| m.to_s =~
/=$/ }
s.reject!{ |e| e !~ /\w/ }
eqmeths[c.name] = s unless s.empty?
}
}
puts
y eqmeths
---
YAML::PrivateType:
- type_id=
- value=
YAML::SpecialHash:
- default=
YAML::Syck::BadAlias:
- name=
YAML::BaseEmitter:
- options=
YAML::Stream:
- documents=
- options=
Process::GID:
- eid=
YAML::Syck::PrivateType:
- type_id=
- value=
YAML::Syck::DomainType:
- type_id=
- value=
- domain=
YAML::YPath:
- segments=
- flags=
- predicates=
Dir:
- pos=
YAML::Syck::Parser:
- options=
Thread:
- priority=
- abort_on_exception=
Hash:
- default=
Process:
- gid=
- egid=
- uid=
- maxgroups=
- euid=
- groups=
Struct::Tms:
- stime=
- utime=
- cstime=
- cutime=
Process::UID:
- eid=
YAML::DomainType:
- type_id=
- value=
- domain=
YAML::Syck::Node:
- type_id=
- value=
- anchor=
- kind=
IO:
- lineno=
- sync=
- pos=
YAML::Syck::Loader:
- bufsize=
- private_types=
- families=
- anchors=
T.
news:Pine.LNX.4.62.05...@harp.ngdc.noaa.gov...
> it's just my opinion, but i think this is clear as a whistle:
>
> color 'blue'
> width 42
It is clear. But by munging writer and reader into a single method, it makes
some kinds of manipulations of the methods difficult (e.g. programatically
generating synchronization based on readers and writers).
> But, I think the self.foo=value syntax would still be preferred
> by most. I'm not sure why you dislike it so much to propose
> making such radical changes.
I would be happy if all self calls required self.foo, or if self was
uniformly optional.
It's just that
bar
baz
self.foo=
foo
leaves the third line sticking out to me. Perhaps very much about personal
preference.
> We are also talking about inside the class, so you know the
It affects other places as well, such as instance_eval.
p.s. I didn't mean to gripe, I love the language :-)
you actually get both here. if you do
trait 'color' => blue
you can
p color
color 'blue'
self.color 'blue'
the code actually delegates the setting to the setter method so, if you were
over-ride you setter to something like
def color= c
raise unless %w( red blue green ).include? c
@color = c
end
the this
color 'mauve'
still works as expected.
not only that but every trait gets a query method too so you can
if color?
...
end
Using instance_eval breaks encapsulation anyways (you have full
access), so I don't see much differnce from self.foo= and
@foo=.
Personally, I think using instance_eval regularly is bad
practice since it breaks encapsulation. My guess is that many
times it is done so that some code doesn't have a specify a
receiver:
foo.bar {
abc(1,2,3)
xyz(4,5,6)
}
where #bar did an instance eval on the block using some object
in foo (including foo itself). I'd say this is better:
foo.bar { |o|
o.abc(1,2,3)
o.xyz(4,5,6)
}
where #bar simply yielded the object in foo to the block.
A little more typing, but you don't break encapsulation and you
don't have to question what "self" is in your blocks.