Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

foo= ... the only exception to the implicit-self rule ?

1 view
Skip to first unread message

itsme213

unread,
Oct 6, 2005, 12:12:09 AM10/6/05
to
Sorry to ask this again, but...

*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.

Yukihiro Matsumoto

unread,
Oct 6, 2005, 12:37:21 AM10/6/05
to
Hi,

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.


Trans

unread,
Oct 6, 2005, 12:55:37 AM10/6/05
to

itsme213 wrote:
> Sorry to ask this again, but...
>
> *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 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.

Joel VanderWerf

unread,
Oct 6, 2005, 1:31:34 AM10/6/05
to
itsme213 wrote:
..

> 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!)

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


itsme213

unread,
Oct 6, 2005, 1:34:35 AM10/6/05
to
Thanks Matz.

"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= ?


itsme213

unread,
Oct 6, 2005, 3:27:48 AM10/6/05
to
True.

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...

Yukihiro Matsumoto

unread,
Oct 6, 2005, 5:30:33 AM10/6/05
to
Hi,

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.


Gavin Kistner

unread,
Oct 6, 2005, 9:51:16 AM10/6/05
to
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'.

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.


James Edward Gray II

unread,
Oct 6, 2005, 10:15:06 AM10/6/05
to
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?

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

David A. Black

unread,
Oct 6, 2005, 10:20:38 AM10/6/05
to
Hi --

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


Eric Mahurin

unread,
Oct 6, 2005, 10:23:12 AM10/6/05
to
--- itsme213 <itsm...@hotmail.com> wrote:

> 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


Ara.T.Howard

unread,
Oct 6, 2005, 10:35:07 AM10/6/05
to
On Thu, 6 Oct 2005, 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'.

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
===============================================================================

David A. Black

unread,
Oct 6, 2005, 11:14:14 AM10/6/05
to
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.

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.

James Edward Gray II

unread,
Oct 6, 2005, 11:28:10 AM10/6/05
to
On Oct 6, 2005, at 9:20 AM, David A. Black wrote:

> 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


Ara.T.Howard

unread,
Oct 6, 2005, 11:42:55 AM10/6/05
to
On Fri, 7 Oct 2005, David A. Black wrote:

> 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.

Trans

unread,
Oct 6, 2005, 12:09:09 PM10/6/05
to

Yukihiro Matsumoto wrote:
> Hi,
>
> 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.

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.

David A. Black

unread,
Oct 6, 2005, 1:17:29 PM10/6/05
to
Hi --

Can you explain what you mean? I'm not getting it.

Trans

unread,
Oct 6, 2005, 2:15:09 PM10/6/05
to
> 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.

itsme213

unread,
Oct 6, 2005, 10:23:02 PM10/6/05
to

"Ara.T.Howard" <Ara.T....@noaa.gov> wrote in message

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).

itsme213

unread,
Oct 6, 2005, 10:23:48 PM10/6/05
to

"Eric Mahurin" <eric_m...@yahoo.com> wrote in message

> 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 :-)


Ara.T.Howard

unread,
Oct 6, 2005, 11:21:20 PM10/6/05
to

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

Eric Mahurin

unread,
Oct 6, 2005, 11:43:29 PM10/6/05
to
--- itsme213 <itsm...@hotmail.com> wrote:
> > We are also talking about inside the class, so you know the
>
> It affects other places as well, such as instance_eval.

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.

0 new messages