On Fri, Jan 31, 2003 at 09:26:28PM +0900, Tom Sawyer wrote:
> On Thursday 30 January 2003 05:44 pm, ahoward wrote:
> > yes. i have confused scope with namespaces, but not entirely i think.
> 
> scope is a rather complex issue in Ruby, it seems. i was just thinking about 
> it myself in relation to the ambiguity between implied self method calls and 
> local variables (a pet subject of mine), which got me thinking: what would 
> the ramifications be if the scope at any point was always defined by self?
> 
> 	x = 1
> 	closure = lambda { x }
> 
> thus x in the closure would not be the same as the first x because self is 
> different in the two cases. i suppose this is essentially the same as the 
> poll option: make'em all local. so how do you get access to outer variables 
> from within closures in this scenario?...
> 
> first, let me come back to the ambiguity between local variables and implied 
> self-receiver method calls. i've had an interesting conception about this: 
> what does it mean to do this when #x= is not defined?
> 
> 	self.x = 1
> 
> no doubt, i would get an error saying #x= is undefined, correct? perhaps that 
> is an error in itself! ;-) why not have local variables themselves be a sort 
> of instantly instantiated "attr_accessor", albiet of a slighty different 
> nature than normal methods --in that ruby handles these "instant attributes" 
> as it currently does local variables. hmmm....ambiguity fading?

Would these instant attributes live between method calls?

class Bar
  def foo
    x = 1
  end
  def foo2
    puts x
  end
end

a = Bar.new
a.foo
a.foo2     # puts 1 ??

> now we come back to accessing outerscoped variables in our closure. our 
> problem is not yet solved, but can be with the realization thus: ruby has to 
> keep track of self at theses various descention/ascentions into blocks and 
> out again. correct? in essence this is a FIFO stack of what self is at any 
> given code point. so why not make self available for it what it really is: an 
> Array? self, stated by itself, would be the same as self[0], but 
> self[1]...ah...
> 
> 	x = 1
> 	closure = lambda { self[1].x }
> 
> would gives us the inter-related result: x in the outer scope is the same as 
> self[1].x in the inner scope.
> 
> some interesting possibilities start to trickle into mind.....

You possibly break GC, as blocks can access variables deeply down the
stack, so you're in fact capturing a substantial part of the environment
in each closure.

def foo
  x = "a" * 100000
  proc do |i|
     self[i].x    # Ouch, self.x can never be reclaimed for any self down
		  # the stack!
  end 
  # normally x could be reclaimed here unless explicitly used by the
  # closure 
end

def foo2
  x = "b" * 100000
  foo
  # normally x could be reclaimed here, but the closure might use it
end

foo.call(1) 
foo2.call(2)
foo.call(100)     # now, what was x 100 stack-frames ago?

I had better never use self[i].tmp inside one of these super-closures :)

Maybe I got it wrong, but I have the feeling this is too powerful.
I'll think more on this. 

Now, I sound like matz ;-)

These super-closures sure are very seductive :)
-- 
 _           _                             
| |__   __ _| |_ ___ _ __ ___   __ _ _ __  
| '_ \ / _` | __/ __| '_ ` _ \ / _` | '_ \ 
| |_) | (_| | |_\__ \ | | | | | (_| | | | |
|_.__/ \__,_|\__|___/_| |_| |_|\__,_|_| |_|
	Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Ok, I'm just uploading the new version of the kernel, v1.3.33, also
known as "the buggiest kernel ever".
	-- Linus Torvalds