Ambiguity between local variable assignment and writter method

does anyone else find it annoying that local variable assignment is
indistinguishable from a writter method.

def localvar=(x)
@localvar = x
end

plv = Proc.new { |x|
localvar = x
}

plv.call(‘whatever’)

the localvar writter method will not be called by the proc, rather a
local variable, local only to the proc itself, will be created. to
adjust, one has to prepend “self.” to the beginning localvar:
“self.localvar” yuk, code smell, as it is in contrast to the fact that
outside variables and all other methods can be seen without the use of
self from within the proc.

it’s really too bad that there is not a syntatical distiction between
local variable assignment and writter methods. if would make things
cleaner, i believe. removing the need for a number of self references.
effectively, i think, this probably means that it is too bad that local
variable assignments don’t have a differnt syntax for assignment. like:

localvar := x

~transami

JUST MORE OF MY EVERYDAY CONTEMPLATIONS ABOUT PROGRAMMING IN RUBY

does anyone else find it annoying that local variable assignment is
indistinguishable from a writter method.

def localvar=(x)
@localvar = x
end

plv = Proc.new { |x|
localvar = x

Why not use:

  self.localvar = x

}

plv.call(‘whatever’)

Paul

···

On Sat, Aug 10, 2002 at 03:00:28AM +0900, Tom Sawyer wrote:

Hi –

does anyone else find it annoying that local variable assignment is
indistinguishable from a writter method.

(Not ignoring the rest of the thread – just wanted to comment on the
underlying question.)

At first, I found it to be a minor but noticeable fly in the
ointment. However, I’ve come to think it’s a small price to pay,

Cons:

  1. you have to type what feels like an “extra” “self”.

Pros:

  1. in Ruby, you get to leave “self” off a lot, so having it not be
    100% of the time isn’t so bad. One can think of it as: you have
    to specify the receiver, except where it’s clear without it, and
    it’s clear without it much of the time (which I like).

  2. The “self.thing = x” form is, ultimately, completely consistent
    with Ruby syntax in general; we’re not being asked to do
    something anomalous. Even though this is a special case, it’s
    not special syntax. It’s just disambiguation.

  3. It’s one of the rites of passage into Ruby to have to master
    this, sort of like realizing that #{…} can interpolate more
    than just single variables :slight_smile:

Follow-up to #2: for that reason (i.e., providing a receiver is normal
Ruby syntax), I’d rather it were left like this than that any new
construct were added to avoid it. That seems like a potentially
never-ending spiral: define syntax; where it’s ambiguous, instead of
requiring strict/explicit usage within the syntax, introduce a new
construct; eventually, something will crop up with the new construct
that requires disambiguation; create new syntax for that… etc.

David

···

On Sat, 10 Aug 2002, Tom Sawyer wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

[On calling setter from inside the class]

Consider this:

class HalfDouble
attr_reader :double, :half

def double=(val)
@double = val
@half = @double / 2
end

def half=(val)
@half = val
@double = @half / 2
end
end

hd = HalfDouble.new

hd.double = 4

p hd.half
p hd.double

Then try to replace @double= with self.double= and @half= with
self.half= and see what happens…

Maybe I’m just being naive, but even though a one uses tongue to
translate his thought for the outside world, and ears to translate
what comes from the outside world into thought, I see nothing wrong in
using just thought for internal communication.

In other words, to me, using setters from inside the class seems a lot
like talking to oneself. :slight_smile:

Massimiliano

code smell.

Proc.new {
self.i_am_a_writter_method = 'so i need my self’
but_i_am_not(‘so i’m cool without it’)
self.there_could_be_a_lot_of_these = ‘that’s a lot of ego ;-)’
}

···

On Fri, 2002-08-09 at 12:05, Paul Brannan wrote:

Why not use:

  self.localvar = x


~transami

Cons:

  1. you have to type what feels like an “extra” “self”.
2. you have to know when you need the extra self and when you don't

3. code looks spotty with self used sometimes but not others

4. code is longer

5. writer methods have an EXCEPTION in their behavior

Pros:

  1. in Ruby, you get to leave “self” off a lot, so having it not be
    100% of the time isn’t so bad. One can think of it as: you have
    to specify the receiver, except where it’s clear without it, and
    it’s clear without it much of the time (which I like).

counter-argument: “isn’t so bad” isn’t good enough, unless there are no
reasonable alternatives. if there is a good alternative, for all of the
time, why not take it?

  1. The “self.thing = x” form is, ultimately, completely consistent
    with Ruby syntax in general; we’re not being asked to do
    something anomalous. Even though this is a special case, it’s
    not special syntax. It’s just disambiguation.

counter-argument: don’t really see this as a PRO. you are right, it is
consistent and you can use self all you want, whether you need to or
not. that’s fine. i’m certainly not suggesting that we throw out self.
self is very essential.

  1. It’s one of the rites of passage into Ruby to have to master
    this, sort of like realizing that #{…} can interpolate more
    than just single variables :slight_smile:

counter-argument: such can never be a PRO, in fact, no offense, but it
smacks of ruby righteousness. it also flys in the face of POLS. you
don’t judge a thing “good” b/c it is difficult and overcoming the
difficulty gives you a sense of accomplishment. if that were the case we
should all be coding in machine code. :slight_smile:

Follow-up to #2: for that reason (i.e., providing a receiver is normal
Ruby syntax), I’d rather it were left like this than that any new
construct were added to avoid it. That seems like a potentially
never-ending spiral: define syntax; where it’s ambiguous, instead of
requiring strict/explicit usage within the syntax, introduce a new
construct; eventually, something will crop up with the new construct
that requires disambiguation; create new syntax for that… etc.

i agree. i don’t want to add any new constructs. and i don’t think we
need to in order to clear up this inconsistency. simply giving
precedence to writer methods would do it.

···

On Fri, 2002-08-09 at 22:50, dblack@candle.superlink.net wrote:


~transami

Very nice analogy! And good example, too.

···

----- Original Message -----
From: “Massimiliano Mirra” list@chromatic-harp.com

[On calling setter from inside the class]

Consider this:

class HalfDouble
attr_reader :double, :half

def double=(val)
@double = val
@half = @double / 2
end

def half=(val)
@half = val
@double = @half / 2
end
end

hd = HalfDouble.new

hd.double = 4

p hd.half
p hd.double

Then try to replace @double= with self.double= and @half= with
self.half= and see what happens…

Maybe I’m just being naive, but even though a one uses tongue to
translate his thought for the outside world, and ears to translate
what comes from the outside world into thought, I see nothing wrong in
using just thought for internal communication.

In other words, to me, using setters from inside the class seems a lot
like talking to oneself. :slight_smile:

Massimiliano

Tom Sawyer transami@transami.net writes:

self.localvar = x

code smell.

I don’t think it’s a smell: it is distinguishing different uses.

However, I’m wondering if we could be more succinct? For top-level
constants, we can write

::Fred

Could we similarly allow a ‘.’ at the start of a statement to be
shorthand for ‘self.’, so we could write

.setter = 123

meaning

self.setter = 123

If we had that, I might be tempted to use it for normal method calls
too.

Dave

Hi –

Cons:

  1. you have to type what feels like an “extra” “self”.
2. you have to know when you need the extra self and when you don't

Isn’t it good to have to know when you’re calling a method and when
you’re assigning to a local variable :slight_smile:

5. writer methods have an EXCEPTION in their behavior

It’s just a constraint, not an exception. Just as in some situations
you have to use parentheses, in some situations you have to name your
receiver.

Follow-up to #2: for that reason (i.e., providing a receiver is normal
Ruby syntax), I’d rather it were left like this than that any new
construct were added to avoid it. That seems like a potentially
never-ending spiral: define syntax; where it’s ambiguous, instead of
requiring strict/explicit usage within the syntax, introduce a new
construct; eventually, something will crop up with the new construct
that requires disambiguation; create new syntax for that… etc.

i agree. i don’t want to add any new constructs. and i don’t think we
need to in order to clear up this inconsistency. simply giving
precedence to writer methods would do it.

(At one point you suggested “localvar := x”, though I won’t argue if
you’ve reconsidered :slight_smile: Anyway – with regard to defaulting to writer
methods, rather than to local variables: the problem arises that you
can’t know what will be present at a given point in the execution of
the program. For example (pointless code, but just for illustration):

class A
def initialize(n)
thing = n
puts "Initializing with argument #{thing}."
end
end

class B < A
attr_writer :thing
end

What happens when you now say:

b = B.new(123)

Does “thing = n”, from B’s superclass, now suddenly mean
"self.thing = n", rather than assigning to a local variable?
(Obviously part of the picture is that subclasses of A cannot and must
not know anything about the names of local variables in instance
methods of A.)

In other words: the meaning of “thing = n” has to be determined, once
and for all, when it’s first encountered; and the only thing it can
definitely be in every single case is a local variable assignment.

(I think this is related to what Dave was saying about subclasses in
response to Rich, though that’s in a slightly different context.)

David

···

On Sat, 10 Aug 2002, Tom Sawyer wrote:

On Fri, 2002-08-09 at 22:50, dblack@candle.superlink.net wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Tom Sawyer wrote:

5. writer methods have an EXCEPTION in their behavior

The real base of the exception is that Ruby allows some rather wierd
symbols in the method names. Personally I’d be more likely to alias my
writer methods to set_* methods, if I found myself using them alot from
inside the class and annoyed at all the selfs. (But then again, C++ and
Java will do the first to your brain and the latter don’t apply to me
that much :slight_smile:

The exception is also tied to the ambiguity of optional parenthesis,
allowed spaces between name and = when calling, and in general its a
very exceptional thing to begin with, to help code outside the class be
readable. One might use stricter call syntax on the inside of the class
to get rid of the ambiguity without self, i.e.
class X
attr_accessor :x
def test
x=(5) # == self.x=5
x =(5) # == x = 5
x= (5) # == x = 5
end
end
But that seems like a bug waiting to bite also.

i agree. i don’t want to add any new constructs. and i don’t think we
need to in order to clear up this inconsistency. simply giving
precedence to writer methods would do it.

Dave mentioned the performance issue, which I believe would be very
significant. Upon parsing, every local variable assignment cannot be
interpreted and optimized as a local variable assignment, but has to
have a check to see if there was a method with that name at runtime,
each and every time. Or you could do the decision only once at parsing
time, and be dependant on the order of definition of methods. (I.e. put
the writer methods below the method in question, and you’re screwed.)

So I don’t think giving precedence to writer methods will suffice.

···


([ Kent Dahl ]/)_ ~ [ http://www.stud.ntnu.no/~kentda/ ]/~
))_student
/(( _d L b_/ NTNU - graduate engineering - 5. year )
( __õ|õ// ) )Industrial economics and technological management(
_
/ö____/ (_engineering.discipline=Computer::Technology)

Tom Sawyer wrote:

Why not use:

 self.localvar = x

code smell.

Proc.new {
self.i_am_a_writter_method = 'so i need my self’
but_i_am_not(‘so i’m cool without it’)
self.there_could_be_a_lot_of_these = ‘that’s a lot of ego ;-)’
}

To me it seems that efficiency issues can dominate here (as to which
form should be used). The argument for having a setter method be the
same as a direct reference (for externally accessible variables) seems
impecable. The caller shouldn’t need to know.

Internal use, however, can be quite different. Sometimes the validation
methods can be a bit expensive (e.g.: Is value actually referred to in
the file?) Even an expensive check may be highly desireable when an
external call is being made, but internally, calls that are known to be
safe should be able to short-circuit the validation, and set the method
directly. Otherwise processing can become unbearably slow. And this is
a kind of slowness that changing languages won’t fix.

···

On Fri, 2002-08-09 at 12:05, Paul Brannan wrote:


– Charles Hixson
Gnu software that is free,
The best is yet to be.

But what will I get from: puts .setter = 123

Well, I know that this probrem is considered one of pit hole. But
this syntax may lead implicitly us to a style: Use @var rather than
var() even if that is a simple attribute. Indeed I prefer @var or
@var=val bacause the semantics of theml are simpler and clearer then
#var() or #var=(val).

In addition, @var is slightly faster than var(); Absolute differnce is
ignorable small, of course, but relative diff isn’t so small.

require “benchmark”

class C
attr eval(":var"), true;

def benchmark(n)
  Benchmark::bmbm do |test|
    test.item("var()"){ n.times{ var() } }
    test.item("@var"){ n.times{ @var } }
  end
end

end

C.new.benchmark(1000000)

generates:

Rehearsal -----------------------------------------
var() 0.960938 0.000000 0.960938 ( 0.970511)
@var 0.703125 0.000000 0.703125 ( 0.729765)
-------------------------------- total: 1.664062sec

          user     system      total        real

var() 0.960938 0.000000 0.960938 ( 1.004252)
@var 0.695312 0.000000 0.695312 ( 0.712950)

– Gotoken

···

At Sat, 10 Aug 2002 03:44:45 +0900, Dave Thomas wrote:

Could we similarly allow a ‘.’ at the start of a statement to be
shorthand for ‘self.’, so we could write

.setter = 123

meaning

self.setter = 123

If we had that, I might be tempted to use it for normal method calls
too.

class A
def initialize(n)
thing = n
puts "Initializing with argument #{thing}."
end
end

class B < A
attr_writer :thing
end

What happens when you now say:

b = B.new(123)

(I think this is related to what Dave was saying about subclasses in
response to Rich, though that’s in a slightly different context.)

i see. yes, that would be a problem. although there are plenty of
particulars of knowing how the superclass and the subclass will
interact, so i do not see that as going against it. the fact that the
interaction is not a one-thing-to-its-like-thing but rather a local
varible assignment interacting/interferring with a method, that is
problematic. and this just would not work. you are right.

and i am assumming too that Rich’s idea has the same problem.

yes, i did suggest := and/or .= earlier, but only as speed convience. i
would not not vote for it.

now there only seems two options left, and they are both constructions.
the construction just stated above (:=) or, and i think the proper way
to have done it, a prefix symbol for local variables.

%localvariable = 'i am me, not some method'

unfortunately that’s just not going to go over well with the population
at large. and i can only wish that it was included early on. all
variables would have a prefix (%, @, @@, $) and methods would not, Ruby
might be a tad faster, and our conversation would never had to exist.
:wink:

~transami

p.s outside of another solution. i have to fall back, unless you all
like %, yeah right! :-}

thanks!

But what will I get from: puts .setter = 123

good question

Well, I know that this probrem is considered one of pit hole. But
this syntax may lead implicitly us to a style: Use @var rather than
var() even if that is a simple attribute. Indeed I prefer @var or
@var=val bacause the semantics of theml are simpler and clearer then
#var() or #var=(val).

unfortunately, this is actually bad form. if a class instance variable
is set up to be accessed via accessor methods, they should be used at
all times. even internally. while, it is functionally equal for the
simplist case, writter methods may do other things as well, like
validate the argument.

···

On Fri, 2002-08-09 at 13:01, GOTO Kentaro wrote:


~transami

GOTO Kentaro gotoken@notwork.org writes:

But what will I get from: puts .setter = 123

Gotoken:

I’m guessing that the parser can distinguish the 'start of something’
state from the rest (where ‘something’ is to be discussed :slight_smile: So, in
the case you give Ruby would pass the ‘setter’ message to the object
in the variable ‘puts’. However, if we disambiguate with parentheses:

puts(.setter = 123)

would execute as puts(self.setter = 123)

Well, I know that this probrem is considered one of pit hole. But
this syntax may lead implicitly us to a style: Use @var rather than
var() even if that is a simple attribute. Indeed I prefer @var or
@var=val bacause the semantics of theml are simpler and clearer then
#var() or #var=(val).

This is an interesting issue: should internal users go via the setter
method or access the instance variable directly. Clearly it depends on
the circumstances, but I often find myself writing accessors that do
things such as lazy evaluation, or which set dirty flags for
persistent objects, and where I really do need to go via the method
form. For those times, it’s nice to have a shortcut, but it isn’t
something I’d fight hard for… :slight_smile:

Regards

Dave

now there only seems two options left, and they are both constructions.
the construction just stated above (:=) or, and i think the proper way
to have done it, a prefix symbol for local variables.

%localvariable = ‘i am me, not some method’

You’re kidding, right? I think one of the things that makes Perl so unreadable is the
amount of $$wildlife @growing %out[$of] =~ /the/ ${@writing} $! It’s nice the way ruby
doesn’t go over the top with it, and perhaps even at times uses it to improve readability.

unfortunately that’s just not going to go over well with the population
at large. and i can only wish that it was included early on. all
variables would have a prefix (%, @, @@, $) and methods would not, Ruby
might be a tad faster, and our conversation would never had to exist.
:wink:

I’d say locals don’t use prefixes (prefices?) since locals are (one of) the most common
identifiers used, and that sort of junk ought to be minimized.

I’d personally rather lose the o.member = ‘something’ notation for method calling. As
David Alan Black mentioned:

Isn’t it good to have to know when you’re calling a method and when
you’re assigning to a local variable :slight_smile:

Anyhow, I wouldn’t consider anything backward-incompatible likely to be worthy of
Rubydom.

···

~transami

p.s outside of another solution. i have to fall back, unless you all
like %, yeah right! :-}

thanks!

Hi, Tom. I see a pattern to all of your expectations for Ruby. Are you a
Smalltalker?

I can’t agree with that.

Surely a class is allowed to reference its own
member data as it chooses. If it bypasses some
kind of needed extra work in the setter, that’s
simply a bug in the code.

If anything has the right and the need to know
the class’s internals, it is the class itself
and the programmer creating it.

Hal

···

----- Original Message -----
From: “Tom Sawyer” transami@transami.net
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Friday, August 09, 2002 2:13 PM
Subject: Re: ambiguity between local variable assignment and writter method

Well, I know that this probrem is considered one of pit hole. But
this syntax may lead implicitly us to a style: Use @var rather than
var() even if that is a simple attribute. Indeed I prefer @var or
@var=val bacause the semantics of theml are simpler and clearer then
#var() or #var=(val).

unfortunately, this is actually bad form. if a class instance variable
is set up to be accessed via accessor methods, they should be used at
all times. even internally. while, it is functionally equal for the
simplist case, writter methods may do other things as well, like
validate the argument.

For me, this is more a point of style. When I write non-trivial
accessors, I tend to name the internal variable differently
from the method name

class Misc
def val=(v)
# do stuff
@in_val = v
# do other stuff
end
end

If the accessor is trivial, I usually leave them the same.

···

On Sat, Aug 10, 2002 at 04:30:28AM +0900, Dave Thomas wrote:

This is an interesting issue: should internal users go via the setter
method or access the instance variable directly. Clearly it depends on
the circumstances, but I often find myself writing accessors that do
things such as lazy evaluation, or which set dirty flags for
persistent objects, and where I really do need to go via the method
form. For those times, it’s nice to have a shortcut, but it isn’t
something I’d fight hard for… :slight_smile:

Regards

Dave


Alan Chen
Digikata LLC

well i think the shortcut of .setter is really backways-around, not
really fumigating the “smell”. though certainly it is at least a bit
cleaner.

the fact that all other methods get picked up without using self, just
smacks of EXCEPTION. the exception for #setter= methods, and exceptions
always smack of smell.

why couldn’t ruby just check to see if there was such a setter method
first, prior to assuming it a local variable assignment? the only
consequence of this would be that you could not use local variable names
identical to your method names. something i tend to do anyway.

~transami

···

On Fri, 2002-08-09 at 13:30, Dave Thomas wrote:

This is an interesting issue: should internal users go via the setter
method or access the instance variable directly. Clearly it depends on
the circumstances, but I often find myself writing accessors that do
things such as lazy evaluation, or which set dirty flags for
persistent objects, and where I really do need to go via the method
form. For those times, it’s nice to have a shortcut, but it isn’t
something I’d fight hard for… :slight_smile: