Subclassing Struct.new

Quoting chiaro scuro [email protected]:

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

[email protected] 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

On 2/28/06, [email protected] [email protected] 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 :slight_smile:

– Chiaroscuro –
Liquid Development Blog:
http://feeds.feedburner.com/blogspot/liquiddevelopment

“chiaro scuro” [email protected] wrote in message
news:[email protected]

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

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

Hi,

In message “Re: Subclassing Struct.new”
on Wed, 1 Mar 2006 00:13:13 +0900, [email protected] 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.

On Feb 28, 2006, at 11:13 AM, [email protected] 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.

On Tue, 2006-02-28 at 23:48 +0900, [email protected] wrote:

Quoting Ross B. [email protected]:

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

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.

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

Hi,

In message “Re: Subclassing Struct.new”
on Wed, 1 Mar 2006 14:34:28 +0900, MenTaLguY [email protected]
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.

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

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

Hi,

In message “Re: Subclassing Struct.new”
on Wed, 1 Mar 2006 16:28:37 +0900, “Minkoo S.”
[email protected] 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.

Hi,

In message “Re: Subclassing Struct.new”
on Thu, 2 Mar 2006 11:34:20 +0900, “Caleb C.”
[email protected] 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.

On 2/28/06, Yukihiro M. [email protected] 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.

On 3/1/06, Yukihiro M. [email protected] 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.

Hi Markus, sorry if it took me a while to answer back. It was a busy
week.

On 3/1/06, Markus W. [email protected] 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 :slight_smile:

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] : Defensive programming - Wikipedia

– Chiaroscuro –
Liquid Development Blog:
http://feeds.feedburner.com/blogspot/liquiddevelopment