Replying to multiple posts:
>> FWIW, Ruby doesn't have nested procedures like that.
> According to my copy of Ruby, it does.
Looks can be deceiving:
$ cat nest_def.rb
class Foo
def a
puts "in a"
def b
puts "in b"
end
b
end
end
f = Foo.new
p Foo.instance_methods(false)
f.a
p Foo.instance_methods(false)
f.b
$ ruby nest_def.rb
["a"]
in a
in b
["b", "a"]
in b
A def inside a method definition defines a method in
self's class. It is not local to the enclosing method definition.
Wow, I did not realize that. That changes my thinking a lot.
>> > I am trying to understand Ruby with some metaprogramming practice. But
>> > I still feel that this is a really backwards step in language design.
>> > It's like telling me I should use GOTO in original BASIC instead of
>> > trying to bend the language to simulate while loops. Would any sane
>> > modern programmer do that?
>> I don't think it's a good analogy. Ruby is more oriented towards
>> little objects and message passing than Pascal-like nested
>> procedures.
> Then why the first-class code blocks? Certainly makes Ruby a
> functional language, if only for blocks.
Yes, Ruby has a good deal of functional features and they
fit in very nicely with the current scoping rules.
Although I'm not sure what you mean with "first class" code
blocks. The block syntax is actually tied to message passing.
Well, blocks aren't first class per-se, but they can easily be turned
into first-class procs.
>> I'm sure we could work out an elegant solution to some higher
>> level goal than "accessing local variables", especially when it
>> comes to metaprogramming.
> The ability to access local vars in enclosing scopes is strictly
> unnecessary. But the same could also be said for instance_variable_get/
> defined?/set.
Ruby does let you access local vars in enclosing scopes. It's
only that your definition of enclosing scope differs from Ruby's.
Try to write some programs and you'll see it all fits together nicely.
Many design decisions may seem arbitrary. We could also debate
the whole day about explicit self, assigning to local variables in
outer scopes, etc. in Python. It's useless.
In the end, you'll find out what looks like a big problem now
actually isn't. The most important usecase for your desired
scoping rules would be nested functions, and Ruby doesn't
have them. And for the other use cases, constants, class-
and module instance variables suffice. OTOH, you can nest
blocks as much as you like and scoping is what you expect.
I recognize that access to nonlocal vars can be simulated with
instance variables. It does seem weird to allow two different
paradigms that interact with each other in a confusing - or at the
least non-trivial - matter (just look at my confusion).
I guess my big beef with Ruby is that it is too complex and bloated
with features that often are inconsistent or lack symmetry with each
other. It's too "magical", making it hard to learn exactly how the
language works. From a language design perspective, Ruby really seems
like a mess to me, although with moments of brilliance. Most of the
time, when I'm metaprogramming, I'm guessing and looking at the
output, hoping I got so-and-so quirk correct.
Actually, I think this all could be mitigated to a certain extent if
the documentation for Ruby were improved. I could not find an official
language reference besides the API documentation, which is not
sufficient by itself. Obviously it did not contain much information on
scoping or non-API language features.
>> Keep in mind that you are looking at just one side of the coin. There's
>> a flip side to it. Preventing local variables from willy-nilly
>> infecting your methods is a Good Thing, and is usually what you want.
> I agree, it's a good thing.
Here you agree, but earlier in the same post you disagree:
Yuh-Ruey Chen wrote:
> I've also noticed that there is a break in symmetry between |def| and |
> define_method| besides this block issue. Compare:
The break in symmetry is intentional because it prevents local variables
from willy-nilly infecting your methods, which you agreed is a good
thing.
I agreed in the sense that without extra syntax, it would be fragile,
but as my example pointed out, it doesn't necessarily have to be
fragile.
> These would be functionally equivalent if there were some way,
> analagous to the former's |self.x|, to access vars in enclosing
> scopes. I'd argue that such a symmetry would be elegant.
> x = 10
> def foo
> x # accessed outside x
> end
> wouldn't be a good thing, because adding a new method called "x" would
> ruin it.
> But something like:
> x = 10
> def foo
> scope.x
> end
> would not be as fragile, assuming |scope| is a new builtin method that
> does what you'd expect it do.
But then you've missed out on the advantage of lexical local variables.
What you propose takes the "lexical" out of "lexical scope". It is just
nested variables which are visible from other scopes.
No, what I am proposing is a mechanism for lexical scope. This is what
I mean with that |scope.x| - treat x as if it were from an enclosing
scope.
>> class Klass
>> GLOBALS.x
>> def bar
>> GLOBALS.x
>> end
>> end
>> This makes your intention explicit. If you know python, you've probably
>> heard the phrase, "Explicit is better than implicit."
> Except I do NOT want x to be globally accessible. I just want to to be
> accessible be child scopes. If I wanted it to be globally accessible,
> then I would just use global variables.
So don't make it global, as in the Top example above.
But they are not local variables. Local vars for a function are
created each time the function is called. Having access to those local
vars outside of the function makes no sense at all.
···
On Oct 31, 5:19 pm, Stefan Lang <perfectly.normal.hac...@gmail.com> wrote:
2008/10/31 Yuh-Ruey Chen <maian...@gmail.com>:
> On Oct 31, 3:09 pm, Stefan Lang <perfectly.normal.hac...@gmail.com> > > wrote:
On Oct 31, 5:43 pm, Mike Gold <mike.gold.4...@gmail.com> wrote:
On Nov 1, 12:40 am, "ara.t.howard" <ara.t.how...@gmail.com> wrote:
On Oct 31, 2008, at 3:08 PM, Yuh-Ruey Chen wrote:
> But something like:
> x = 10
> def foo
> scope.x
> end
> would not be as fragile, assuming |scope| is a new builtin method that
> does what you'd expect it do.
you can write it yourself now
cfp:~ > cat a.rb
class C
include(
Module.new do
y = 42
def x() y end
define_method :method_missing do |_|
if((_ = local_variables.index(_.to_s)))
eval local_variables[_]
else
super
end
end
end
)
end
p C.new.x
cfp:~ > ruby a.rb
42
That's, um, interesting. Less efficient than I hoped, but then again
Ruby is not known for its efficiency. Though that method_missing does
give me an idea...