Forum: Ruby Subclassing Struct.new

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Minkoo S. (Guest)
on 2006-02-28 13:03
(Received via mailing list)
Hi group.

Please have a look at the following:

irb(main):001:0> class F < Struct.new :n
irb(main):002:1>   def dec_n
irb(main):003:2>     n = n - 1
irb(main):004:2>   end
irb(main):005:1> end
=> nil
irb(main):006:0> f = F.new 1
=> #<struct F n=1>
irb(main):007:0> f.dec_n
NoMethodError: undefined method `-' for nil:NilClass
        from (irb):3:in `dec_n'
        from (irb):7
        from :0
irb(main):008:0>

I've tried to define a class which decrease n by 1, but failed. How can
I do that?

- Minkoo S.
Chiaro S. (Guest)
on 2006-02-28 13:15
(Received via mailing list)
On 2/28/06, Minkoo S. <removed_email_address@domain.invalid> wrote:
> Hi group.
>
> Please have a look at the following:

The following works for me.  I suspect you should have used self
inside the method

class F < Struct.new(:n)
    def dec_n
        self.n -= 1
    end
end

f = F.new 2
puts f.n == 2

f.dec_n
puts f.n == 1




-- Chiaroscuro --
Liquid Development Blog:
http://feeds.feedburner.com/blogspot/liquiddevelopment
Minkoo S. (Guest)
on 2006-02-28 13:24
(Received via mailing list)
It works! Thank you.

But, could you tell me why should I have to use self?

- Minkoo S.
Chiaro S. (Guest)
on 2006-02-28 13:46
(Received via mailing list)
On 2/28/06, Minkoo S. <removed_email_address@domain.invalid> wrote:
> It works! Thank you.
>
> But, could you tell me why should I have to use self?

The alternative would be to use @n, but I am not sure that Struct
organises these properties around individual instance variable.  it
probably keeps them in an internal hash, so you have to use the
accessor 'n'.  However, when you use it on the left handside you must
prefix with self, otherwise ruby thinks it is a variable n, rather
than a call to the attribute writer 'n='.

I am not sure if this is supposed to be a bug.. it's certainly a
surprising behaviour.

--

-- Chiaroscuro --
Liquid Development Blog:
http://feeds.feedburner.com/blogspot/liquiddevelopment
Minkoo S. (Guest)
on 2006-02-28 14:04
(Received via mailing list)
chiaro scuro wrote:
> However, when you use it on the left handside you must
> prefix with self, otherwise ruby thinks it is a variable n, rather
> than a call to the attribute writer 'n='.

It is strange because

n=1 is fine, but
n -= 1 is not.

> I am not sure if this is supposed to be a bug.. it's certainly a
> surprising behaviour.

Counter intuitive, at the very least. I really want this behavior to be
fixed.

Best,
Minkoo S.
Ross B. (Guest)
on 2006-02-28 14:32
(Received via mailing list)
On Tue, 2006-02-28 at 21:03 +0900, Minkoo S. wrote:
> chiaro scuro wrote:
> > However, when you use it on the left handside you must
> > prefix with self, otherwise ruby thinks it is a variable n, rather
> > than a call to the attribute writer 'n='.
>
> It is strange because
>
> n=1 is fine, but
> n -= 1 is not.

Well, n = 1 just assigns the fixnum 1 to a (new) local variable 'n'.
n -= 1 is expanded to n = n + 1.

Normally, n + 1 would end up calling your method because Ruby would have
to figure out whether it's a method or variable, but because in this
case Ruby has seen a bare assignment to 'n' by that point, it remembers
that and assumes 'n' is a local variable.

This local variable isn't yet initialized (the n + 1 would be it's
initializer), so n + 1 ends up being nil + 1, or (effectively) nil.+(1),
hence the "undefined method '+' for nil:NilClass".

Using self.n = 1 forces Ruby to treat the assignment as involving the
method 'n' on 'self'.

I don't think it's a bug, but I know it's tripped people (including me)
up before. From the implementation point of view it's probably the
lesser of two evils, though.
Minkoo S. (Guest)
on 2006-02-28 14:56
(Received via mailing list)
Ross B. wrote:
> Normally, n + 1 would end up calling your method because Ruby would have
> to figure out whether it's a method or variable, but because in this
> case Ruby has seen a bare assignment to 'n' by that point, it remembers
> that and assumes 'n' is a local variable.
>
> This local variable isn't yet initialized (the n + 1 would be it's
> initializer), so n + 1 ends up being nil + 1, or (effectively) nil.+(1),
> hence the "undefined method '+' for nil:NilClass".

Sigh. This reminds me of the rule that I have to use
"this->method_name( )" when I want call a method of T, parent class,
which is passed as template parameter. Anyway, it's not a perfect
world...

Best,
Minkoo S.
Chiaro S. (Guest)
on 2006-02-28 15:14
(Received via mailing list)
On 2/28/06, Ross B. <removed_email_address@domain.invalid> wrote:
> This local variable isn't yet initialized (the n + 1 would be it's
> initializer), so n + 1 ends up being nil + 1, or (effectively) nil.+(1),
> hence the "undefined method '+' for nil:NilClass".
>
> Using self.n = 1 forces Ruby to treat the assignment as involving the
> method 'n' on 'self'.
>
> I don't think it's a bug, but I know it's tripped people (including me)
> up before. From the implementation point of view it's probably the
> lesser of two evils, though.

It's really unrubesque and tricky.  What would be the consequences of
handling it as you would normally expect?  What would the side effects
be?


--

-- Chiaroscuro --
Liquid Development Blog:
http://feeds.feedburner.com/blogspot/liquiddevelopment
Ross B. (Guest)
on 2006-02-28 15:42
(Received via mailing list)
On Tue, 2006-02-28 at 22:14 +0900, chiaro scuro wrote:
> > lesser of two evils, though.
>
> It's really unrubesque and tricky.  What would be the consequences of
> handling it as you would normally expect?  What would the side effects
> be?
>

This isn't necessarily based in fact (i.e. I've not surfed the source
just now) but I imagine it would be:

	* Harder to parse, with more ambiguous cases.
	* Generally slower, since local lookup would be 'the long way'
	  more often.
	* More difficult to follow the code six months down the line
	  (or on the next guy's screen).
Chiaro S. (Guest)
on 2006-02-28 15:48
(Received via mailing list)
On 2/28/06, Ross B. <removed_email_address@domain.invalid> wrote:
> This isn't necessarily based in fact (i.e. I've not surfed the source
> just now) but I imagine it would be:
>
>         * Harder to parse, with more ambiguous cases.
>         * Generally slower, since local lookup would be 'the long way'
>           more often.
>         * More difficult to follow the code six months down the line
>           (or on the next guy's screen).

I would disagree on the third point.

However, I guess that doing allowing 'selfless' attributes would cause
some worst inconsistency somewhere else.  i just wonder what it could
be.

--

-- Chiaroscuro --
Liquid Development Blog:
http://feeds.feedburner.com/blogspot/liquiddevelopment
Markus W. (Guest)
on 2006-02-28 15:54
(Received via mailing list)
Hello,


Minkoo S. wrote:

> Counter intuitive, at the very least. I really want this behavior to be
> fixed.

How should it be in your opinion?

I find it intuitive, cause the sense behind it is obviously.

Ruby assumes that a method call has the current object as receiver.
So it implied the "self." prefix"
But if there is a local var assignment it assumes that you like to use
this
local var instead.
Since the local var is determined by the enclosing block it is IMHO an
intuitive solution.

What do you ruby expect to do if it see some think like this?

def foo
  a = "hello"
end

Should it assign the local var "a" or should it call the method "a="?
If you say that it should assign the local var "a" just if there is no
method "a=".

What happend to your code if some day in the future you or some else
define
a methode "a=" to write the ivar @a. And you don't remember that your
method foo use a local var a?

with kind regards


Markus

PS
What should happend in this case?

def n
  @n
end

def n=(n)
    @n = n
end
Chiaro S. (Guest)
on 2006-02-28 16:37
(Received via mailing list)
On 2/28/06, Markus W. <removed_email_address@domain.invalid> wrote:
> Should it assign the local var "a" or should it call the method "a="?
> If you say that it should assign the local var "a" just if there is no
> method "a=".

thanks for pointing out the side effects of the other stylistic
choice. now it's much clearer why it was done this way.

> What happend to your code if some day in the future you or some else define
> a methode "a=" to write the ivar @a. And you don't remember that your
> method foo use a local var a?

my tests would fail, I guess.

I also program in VBA, where you have a 'property set' feature that is
roughly the equivalent of the 'name=' operator in Ruby and it has
never been a problem.  the few times this error slipped through, the
tests always caught it.

> What should happend in this case?
>
> def n
>   @n
> end
>
> def n=(n)
>     @n = n
> end

I guess the 'n' in '@n = n' would be the one most internally scoped,
i.e. the passed arg

--

-- Chiaroscuro --
Liquid Development Blog:
http://feeds.feedburner.com/blogspot/liquiddevelopment
unknown (Guest)
on 2006-02-28 16:46
(Received via mailing list)
Quoting chiaro scuro <removed_email_address@domain.invalid>:

> I am not sure if this is supposed to be a bug.. it's certainly a
> surprising behaviour.

Since variables are declared via first assignment, how could it be
done differently?

-mental
unknown (Guest)
on 2006-02-28 16:49
(Received via mailing list)
Quoting Ross B. <removed_email_address@domain.invalid>:

> From the implementation point of view it's probably the
> lesser of two evils, though.

It's really the only possible way; the variable-versus-writer
decision has to be made at parse time.

-mental
unknown (Guest)
on 2006-02-28 16:49
(Received via mailing list)
Quoting Minkoo S. <removed_email_address@domain.invalid>:

> n=1 is fine, but

Check again.  n=1 will parse as assignment to the local variable 'n'
too.

-mental
Chiaro S. (Guest)
on 2006-02-28 16:55
(Received via mailing list)
On 2/28/06, removed_email_address@domain.invalid 
<removed_email_address@domain.invalid> wrote:
> Quoting chiaro scuro <removed_email_address@domain.invalid>:
>
> > I am not sure if this is supposed to be a bug.. it's certainly a
> > surprising behaviour.
>
> Since variables are declared via first assignment, how could it be
> done differently?

I guess that in principle when you see an '=', you could lookup a
'name=' method before deciding that it is a local var assignment
rather than a method call.

I also understand that there will be perfromance issues with that.

did I miss something?
unknown (Guest)
on 2006-02-28 17:14
(Received via mailing list)
On Feb 28, 2006, at 9:55 AM, chiaro scuro wrote:
> I guess that in principle when you see an '=', you could lookup a
> 'name=' method before deciding that it is a local var assignment
> rather than a method call.
>
> I also understand that there will be perfromance issues with that.

The problem, of course, is that methods can come and go so you would
have to check every time the assignment was executed and I don't
think you would want the assignment to be to a local variable at one
point and then to be a method call at another.

It has to be determined statically.  So any 'solution' to the problem
would probably be to introduce some clear syntactical hint with
respect to local variables...


Gary W.
unknown (Guest)
on 2006-02-28 17:14
(Received via mailing list)
Quoting chiaro scuro <removed_email_address@domain.invalid>:

> I guess that in principle when you see an '=', you could lookup a
> 'name=' method before deciding that it is a local var assignment
> rather than a method call.
>
> I also understand that there will be perfromance issues with
> that.
>
> did I miss something?

In Ruby's grammar, expressions containing a name parse differently
depending on whether that name is a variable or a method.

Whatever rule is used has to be able to distinguish between the two
at parse-time; you can't rely on run-time information.

So, the current parsing rule is: "If you see an assignment to a bare
name, that name means a variable until the end of the block/method.
Until then it means a method call."

e.g.:

 def foo
   n # method
 end

 def bar
   n = 3
   n # variable
 end

 def baz
   n # method
   n = 3
   n # variable
 end

Note that it doesn't matter if the assignment is actually performed,
just that the parser sees it:

 def hoge
   n # method
   if false
     n = 3
   end
   n # variable
 end

(uninitialized variables are nil)

-mental
Chiaro S. (Guest)
on 2006-02-28 17:36
(Received via mailing list)
On 2/28/06, removed_email_address@domain.invalid 
<removed_email_address@domain.invalid> wrote:
>
> On Feb 28, 2006, at 9:55 AM, chiaro scuro wrote:
> The problem, of course, is that methods can come and go so you would
> have to check every time the assignment was executed and I don't
> think you would want the assignment to be to a local variable at one
> point and then to be a method call at another.

that wouldn't worry me. it's a rare event that tests would probably
catch anyway.
I understand that it has been implemented statically, and that the
whole mechanism would need changing, but don't you agree that this
syntactic tagging and static interpretation of '=' is a kind of
defensive programming that we could do well without?

> It has to be determined statically.  So any 'solution' to the problem
> would probably be to introduce some clear syntactical hint with
> respect to local variables...

-- Chiaroscuro --
Liquid Development Blog:
http://feeds.feedburner.com/blogspot/liquiddevelopment
unknown (Guest)
on 2006-02-28 17:51
(Received via mailing list)
Quoting chiaro scuro <removed_email_address@domain.invalid>:

> I understand that it has been implemented statically, and that
> the whole mechanism would need changing, but don't you agree that
> this syntactic tagging and static interpretation of '=' is a kind
> of defensive programming that we could do well without?

It's not a matter of being defensive... because variables and method
names are gramatically different, there are some constructs where
one is (gramatically) valid but not the other.  The decision has to
be made up-front, or the grammar drastically revised.

-mental
Chiaro S. (Guest)
on 2006-02-28 18:04
(Received via mailing list)
On 2/28/06, removed_email_address@domain.invalid 
<removed_email_address@domain.invalid> wrote:
> be made up-front, or the grammar drastically revised.
What I meant is that a feature of this grammar forces us to use this
style of programming.

I believe we can do without this style, because the rationale to
support it (without looking at the implementation details) is a
defensive programming argument.

I understand this would involve heavy work on the grammar.

Thanks for all your replies and explanations.  I am trying to get you
to agree on the fact that an '=' dynamic semantic lookup would be a
nice thing to have :-)

--

-- Chiaroscuro --
Liquid Development Blog:
http://feeds.feedburner.com/blogspot/liquiddevelopment
unknown (Guest)
on 2006-02-28 18:16
(Received via mailing list)
Quoting chiaro scuro <removed_email_address@domain.invalid>:

> I believe we can do without this style, because the rationale to
> support it (without looking at the implementation details) is a
> defensive programming argument.

But do we really want a situation where the names of local variables
become important to the external interface of a class?

If some mixin adds a method with the same name as a local variable
somewhere, we don't want things to suddenly break.

I think a better solution would be requiring explicit variable
declarations.  Let variables be unambiguously variables.

The implementation details would hairy too though.

-mental
Pit C. (Guest)
on 2006-02-28 19:02
(Received via mailing list)
removed_email_address@domain.invalid schrieb:
> ...
> But do we really want a situation where the names of local variables
> become important to the external interface of a class?
>
> If some mixin adds a method with the same name as a local variable
> somewhere, we don't want things to suddenly break.
> ...

100% agreed.

Classes like OpenStruct implement setter methods via method_missing. How
should they be handled?

Regards,
Pit
Hal F. (Guest)
on 2006-03-01 03:50
(Received via mailing list)
Minkoo S. wrote:
> n -= 1 is not.
>
>
>>I am not sure if this is supposed to be a bug.. it's certainly a
>>surprising behaviour.
>
>
> Counter intuitive, at the very least. I really want this behavior to be
> fixed.

Please explain what you mean.

Hal
Mark W. (Guest)
on 2006-03-01 04:10
(Received via mailing list)
"chiaro scuro" <removed_email_address@domain.invalid> wrote in message
news:removed_email_address@domain.invalid...

>However, I guess that doing allowing 'selfless' attributes would cause
>some worst inconsistency somewhere else.  i just wonder what it could
>be.

One explanation I've heard for this behavior is that if 'self' was
implied
in this case, but you actually -did- want to use a local variable with
the
same name, that some kind of prefix would be required (which would be
weirder than the current behavior).
Yukihiro M. (Guest)
on 2006-03-01 04:22
(Received via mailing list)
Hi,

In message "Re: Subclassing Struct.new"
    on Wed, 1 Mar 2006 00:13:13 +0900, removed_email_address@domain.invalid 
writes:

|So, the current parsing rule is: "If you see an assignment to a bare
|name, that name means a variable until the end of the block/method.
|Until then it means a method call."

Yes, and in Ruby2.0, this will be changed to "if you see an assignment
to a bare name, that name means a variable in the current scope", so
that

| def foo
|   n # method
| end
|
| def bar
|   n = 3
|   n # variable
| end
|
| def baz
|   n # will be variable
|   n = 3
|   n # variable
| end
|
|Note that it doesn't matter if the assignment is actually performed,
|just that the parser sees it:
|
| def hoge
|   n # will be variable
|   if false
|     n = 3
|   end
|   n # variable
| end

See?

							matz.
Logan C. (Guest)
on 2006-03-01 04:57
(Received via mailing list)
On Feb 28, 2006, at 11:13 AM, removed_email_address@domain.invalid wrote:

> I think a better solution would be requiring explicit variable
> declarations.  Let variables be unambiguously variables.
>
> The implementation details would hairy too though.

Word. Speaking of which explicitly declared variables could help with
with the whole closure grabs every possible memory reference from
here to eternity. Then again, I like ruby, I can live with self.x =
if ruby can.
Ross B. (Guest)
on 2006-03-01 06:46
(Received via mailing list)
On Tue, 2006-02-28 at 23:48 +0900, removed_email_address@domain.invalid wrote:
> Quoting Ross B. <removed_email_address@domain.invalid>:
>
> > From the implementation point of view it's probably the
> > lesser of two evils, though.
>
> It's really the only possible way; the variable-versus-writer
> decision has to be made at parse time.

Hmm, yes now I think about it that makes sense. So in that case I guess
there couldn't even be a reliable method lookup...

I'm going to have to look into the code some more now :)
MenTaLguY (Guest)
on 2006-03-01 07:34
(Received via mailing list)
On Wed, 2006-03-01 at 11:19 +0900, Yukihiro M. wrote:
> Yes, and in Ruby2.0, this will be changed to "if you see an assignment
> to a bare name, that name means a variable in the current scope",

This is best for the user.  However...

Will the Ruby2.0 grammar no longer have variable/method ambiguities?

Otherwise, it'd be supremely nasty to parse.  As far as I can figure
out, you'd have to do it in multiple passes...

-mental
Minkoo S. (Guest)
on 2006-03-01 09:28
(Received via mailing list)
Yukihiro M. wrote:
> Yes, and in Ruby2.0, this will be changed to "if you see an assignment
> to a bare name, that name means a variable in the current scope", so
> that

Please englighten me:

> | def bar
> |   n = 3
> |   n # variable - make sense to me.
> | end

This make sense, but

> | def baz
> |   n # variable - Do we really need this uninitialized variable access?
> |   n = 3
> |   n
> | end

Thank you for the explanation.

Sincerely,
Minkoo S.
Yukihiro M. (Guest)
on 2006-03-01 09:41
(Received via mailing list)
Hi,

In message "Re: Subclassing Struct.new"
    on Wed, 1 Mar 2006 14:34:28 +0900, MenTaLguY 
<removed_email_address@domain.invalid>
writes:

|Will the Ruby2.0 grammar no longer have variable/method ambiguities?

I'm not sure what you meant by "ambiguities".  The identifiers not
assigned in the scope will be treated as method calls, as well as in
current behavior.

|Otherwise, it'd be supremely nasty to parse.  As far as I can figure
|out, you'd have to do it in multiple passes...

I'd use a technique called back patching to avoid multiple passes.

							matz.
Yukihiro M. (Guest)
on 2006-03-01 09:45
(Received via mailing list)
Hi,

In message "Re: Subclassing Struct.new"
    on Wed, 1 Mar 2006 16:28:37 +0900, "Minkoo S."
<removed_email_address@domain.invalid> writes:

|This make sense, but
|
|> | def baz
|> |   n # variable - Do we really need this uninitialized variable access?
|> |   n = 3
|> |   n
|> | end

For example, in cases like this:

  def foobar(ary)
    # we need to "declare" a variable here under the current behavior,
    # but no longer under the new behavior
    ary.each do |elem|
       if some_condition_on_elem(elem)
          found = elem     # "found" will be available during whole
#foobar.
          break
       end
    end
    some_work_with_found_elem(found)
    return found
  end

							matz.
Markus W. (Guest)
on 2006-03-01 12:03
(Received via mailing list)
Hi chiaro,

I'm not a regular programmer. So I guess I don't have a chance to
discuss
with you and the right level. ;-)

For me the subject we discuss it is a matter of taste. And for my taste
the
ruby way is OK.

I like it the way it is and for me it is not surprising and thats why I
wrote my post.

> my tests would fail, I guess.

Yes this should happen.


> I also program in VBA, where you have a 'property set' feature that is
> roughly the equivalent of the 'name=' operator in Ruby and it has
> never been a problem.  the few times this error slipped through, the
> tests always caught it.

Wouldn't it be better if they don't appear at the first place?

Maybe you could explain me why the other way is better.
I'm open minded so your opinion would really helps do to extend my
knowledge.


with kind regards

Markus
Caleb C. (Guest)
on 2006-03-02 04:34
(Received via mailing list)
On 2/28/06, Yukihiro M. <removed_email_address@domain.invalid> wrote:
> |   n # variable
> | end
> |
> | def baz
> |   n # will be variable
> |   n = 3
> |   n # variable
> | end

So, then, what will you do with this:

def foo
   bar %(
      bar=1
   )
end

Should the first bar be a variable or method? If you assume it's a
method initially, the rest looks like a string, and there's no
apparent assignment in the rest of the method to clue the parser in
that it needs to go back and make it a variable instead. Granted, this
example is pathological, but I think there might be less pathological
cases that have the same problem.

I think that the current rule that local variables are declared on
first assignment is a good one. Yes, it leads to confusion in a few
cases, mostly for those who aren't aware that this is one of ruby's
few gotchas. But Ruby is hard enough to parse now; I need to look an
arbitrary number of tokens into the past to determine if a name is a
local var or not. I'd rather not have to look an arbitrary number of
tokens into the future(!) as well. Especially as there seems to be
little need for this new feature. (Unassigned locals will (presumably)
always be nil before the first assignment anyway; why would you want
to use a variable before its first (lexical) assignment? Your example
with the local variable in a block didn't seem to address that
question.)

If you are going to make this change, I (and others trying to write
ruby parsers) would appreciate an explanation of exactly when a local
variable can be back-declared, and how to handle pathological cases
like I gave above.
Yukihiro M. (Guest)
on 2006-03-02 09:29
(Received via mailing list)
Hi,

In message "Re: Subclassing Struct.new"
    on Thu, 2 Mar 2006 11:34:20 +0900, "Caleb C."
<removed_email_address@domain.invalid> writes:

|So, then, what will you do with this:
|
|def foo
|   bar %(
|      bar=1
|   )
|end
|
|Should the first bar be a variable or method? If you assume it's a
|method initially, the rest looks like a string, and there's no
|apparent assignment in the rest of the method to clue the parser in
|that it needs to go back and make it a variable instead. Granted, this
|example is pathological, but I think there might be less pathological
|cases that have the same problem.

Hmm, you make me remember a trick in the parser (which I made).

|I think that the current rule that local variables are declared on
|first assignment is a good one. Yes, it leads to confusion in a few
|cases, mostly for those who aren't aware that this is one of ruby's
|few gotchas. But Ruby is hard enough to parse now; I need to look an
|arbitrary number of tokens into the past to determine if a name is a
|local var or not. I'd rather not have to look an arbitrary number of
|tokens into the future(!) as well. Especially as there seems to be
|little need for this new feature. (Unassigned locals will (presumably)
|always be nil before the first assignment anyway; why would you want
|to use a variable before its first (lexical) assignment? Your example
|with the local variable in a block didn't seem to address that
|question.)

My original intention is _not_ to use local variables before their
first assignment, but to extent their scope to by their outer most
appearance in the method.  But at the same time, I expect the new rule
to solve

   print foo if foo = bar()

problem.  I will ponder the new rule (and implementation) bit more.

							matz.
Caleb C. (Guest)
on 2006-03-02 21:18
(Received via mailing list)
On 3/1/06, Yukihiro M. <removed_email_address@domain.invalid> wrote:
> My original intention is _not_ to use local variables before their
> first assignment, but to extent their scope to by their outer most
> appearance in the method.

I'm trying to understand the distinction... I think I see. It's
cases where the assignment happens (or might happen?) after
a use at runtime, but also, the use comes before the assignment
in the lexical order.

> But at the same time, I expect the new rule
> to solve
>
>    print foo if foo = bar()

The perfect example. This, I agree ought to work as expected. I'm
not sure I can see an easy way to make it work, but it seems like
there might be a special case... on the other hand, maybe just
a special case isn't good enough. What about this:

until foo && foo.k
  foo=readfoo
end

Sort of silly, there's a better way to do this. But the question is, do
you want foo to be a variable on the first line? And this case:

> | def baz
> |   n # will be variable
> |   n = 3
> |   n # variable
> | end

is clearly always use before definition. Should this cause a warning or
something then?

> I will ponder the new rule (and implementation) bit more.

One thought I had: if there isn't a clever trick for inline if, maybe
the
best way is to keep the existing semantics and issue a warning if
there's a method call with a name that subsequently is used for a
local variable in the same scope. That shouldn't be too hard.
Chiaro S. (Guest)
on 2006-03-04 19:30
(Received via mailing list)
Hi Markus, sorry if it took me a while to answer back.  It was a busy
week.

On 3/1/06, Markus W. <removed_email_address@domain.invalid> wrote:
> Hi chiaro,
> For me the subject we discuss it is a matter of taste. And for my taste the
> ruby way is OK.
> I like it the way it is and for me it is not surprising and thats why I
> wrote my post.

The reason I find it surprising is that I expect to read from
something and to write to something using the same name to identify
the thing I am reading from or writing to.

I find this symmetry beautiful and intuitive.

If 'puts n' prints out the value of n, then I expect 'n = something'
to change the value of n.  I don't want to be concerned with the fact
that n is a local variable or a method that provides me with access to
an instance variable.

With the current system I would have to specify 'self.n = something'
to make the assignment.  This is unrebesque to me, since it forces me
to see (and to understand) the inner workings of the system, rather
than focus on my problem.

Yet, the discussion on this thread pointed out why it is necessary (see
later)

> > never been a problem.  the few times this error slipped through, the
> > tests always caught it.
> Wouldn't it be better if they don't appear at the first place?

This is a matter of attitude.  I used to be all for 'defensive
programming' [1], but I find that tests can allow me to move faster
while catching errors fast.

I prefer to write code where the semantics of what I am doing are
clear to me, rather than having to satisfy the needs of the parser.
This means that I can be more relaxed and I do not need to specify the
syntactic nature of what I am accessing (local var, instance
attribute, etc..) unless it is necessary to solve an ambiguous
situation.


> Maybe you could explain me why the other way is better.
> I'm open minded so your opinion would really helps do to extend my
> knowledge.

I hope I made my point :-)

The reason why we cannot get rid of the self, as far as I have
understood it, it is related to the use of mixins.  If we didn't have
mixins I would simply propose to resolve the nature of our 'n' sign at
runtime.  If there is an argument 'n', then that argument is 'n'
within our scope, and we would need an explicit 'self.n' to access our
'n' method/accessor.  If there is no 'n' argument, then we look for
'n' methods and finally for 'n' local variables.

If you use mixins however you can have an unpredictable name clash
between names that were intended to be used as local variables within
the mixin and names that you are using as methods in your class.  This
is an error that is very hard to spot, since you are not even supposed
to know what these offending local variable names of the mixin are.
They are inner workings of the mixin; they are not part of the mixin
'interface' and they should not conflict with your class.

This looks like a problem that is almost impossible to solve in a
non-defensive way.. forcing us to use self in the former case as well,
to protect us from an eventual mixin name clash ambiguity.

I just wish there could be a way to solve the mixin name clashes and
get rid of the 'self' when using the assignment operator on a method.


[1] : http://en.wikipedia.org/wiki/Defensive_programming
--

-- Chiaroscuro --
Liquid Development Blog:
http://feeds.feedburner.com/blogspot/liquiddevelopment
This topic is locked and can not be replied to.