Yukihiro Matsumoto wrote:
> 
> ...
> But in reallity,
> you may want some variables update, and rest of them remain isolated
> from outer namespace, at the same time.  So I feel <> paremeters are
> better, since we can explicitly choose.  But I hate the fact that the
> user has to examine out scope to tell the scope of a variable.  I
> really want to fix this.
> 

For some reason, I keep spending a lot of time on this issue.

Considering the following... [ruby-talk:5531]
      >>
      In addition, there should be way to distinguish local variables
      local to the closure and local variables shared with outer
      scope.  For most languages, declarations do the job, but I have
      no idea what is good for Ruby yet.
      <<

One approach is to introduce declarative 'import' and 'export' as 
either keywords or special method calls for non-parameter locals.

IMPORT
------
foo {|x|
	import a
	if ...
		import :b,:c
	else
		import *
	end
}

'import a' would mean to create a block-local variable
initialized to the same value of local-variable 'a'
if it exists, else set it to nil.

We would still need a way to control the parameters, though.

Some have mentioned _x, (x), :x, ::x, etc.  
I now re-introduce x~  ;-)  [ruby-talk:5548] 
(Maybe it doesn't look so ugly anymore?)

PARAMETER BACKUP ~
------------------
In this case, the tilde is a marker that indicates the variable
is block-local, but should be initialized to the associate var's
value. (IOW, it is a back-up variable - just like how '~' is appended 
to filenames that are backups)

x = 5
foo { | x~ |	# also make back-up of x 
	x += 3
	puts x	# 8
}			# restore x from back-up 
puts x		# 5

This solves case (1) by making a block-local duplicate of a parameter
appearing beforehand.
>   (1) a block parameter variable names appeared BEFORE the lambda.
>       Since parameters in most languages are scope local, some (or
>       even most) expect them local to the block, even if they already
>       appear in the enclosing scope.
[ruby-talk:5552]

EXPORT
------
The 'export' feature would address the case where Ruby
by default made a block-local variable due to the non-
existence of that variable in the enclosing scope.

foo {|x|
	export :q	# create and/or use 'q' in enclosing scope
	q=5
	:
}

This addresses case (3) without initializing the variable
prior to the block.
>   (3) a local variable names appeared AFTER the lambda.
>       Since it's easy to forget about block scope rules, some (or even
>       most) expect the values of block local variables preserved after
>       the block.  When he meets the `undefined local variable' error,
>       he should go back before the block and initialize the variable.

and
>  ary.each do |x|
>    if cond?(x)
>      break
>    end
>  end
>  found = x  # error; x is not defined here.

becomes

ary.each do |x| export :x
	if cond?(x)
	  break
	end
end
found = x  # no error

It is also related to Dave's idea [ruby-talk:5543]
>>
... then introduce some kind of operator which
says "scope this variable outside the block" so that closures would
work. This has the benefit of making scope-sharing explicit, ...
<<

Except he was going with the idea of making everything block-local by default.
By using the declarative 'import', no code needs to be broken.



NATIVE
------
Another useful feature would address the problem in which
a value is prevented from interacting with the enclosing scope. 
I'll call it 'native'.

foo {|a,b,c|	
	native :r,:q	# optional, but ensures local to block
	10.times do
		import :c	# localize changes
		q = []; r = Math.sqrt(b**2-4*a*c)
		q << (-b + r)/2*a
		q << (-b - r)/2*a
		c += 5
	end  # c reverts
	x = q
	export :x	# optional, but ensures it is passed on
}  # r,q revert

The 'native' feature should also ensure the variable is initialized.

This feature would solve case (2) by not having to know the variable 
was not previously used simply to know whether it will be block-local.
>   (2) a local variable names appeared IN the block.
>       When you are trying to use a variable local to the block, you
>       have to assure the name of a variable is not used outside of the
>       block.  You have to know all local variable names.  Although
>       it's good to know all local variable names in the method, a
>       programmer should be allowed to be lazy enough to avoid
>       searching variable names.


I think these four approaches would provide the necessary
optional control to allow the programmer to evade ambiguous
mind benders...

However, it make ruby look somewhat declarative.
Yet think about private, public, attr, and the like.
Plus, think about the certainty it would afford, and
the time saved.

Still, how could these be reduced?

Well, I like the idea of a block having automatic access 
to everything in its surrounding scope.

So we could probably eliminate 'native' and just use
'import var' with a 'var=0' type of follow-up.

Furthermore, both import and export could possibly be
combined into the <a,b|x,y> approach as follows:

foo {|q,r~|<a,b|x,y>
	....
}  # q is as usual; x and y get passed on; r,a,b revert


summarizing this one,

foo {|(1),(2~)| <(3)|(4)>
	....
}

(1) *[regular params with tricky scope]
(2) *[backed-up params with block-local scope]
(3) *[import as block-local copies]
(4) *[export to locals on scope exit]

I hope these ideas made some sense...

Conceptually,
{|params, shadows~| <imports|exports> .... }

iterators work, closures work; optional extra control...

Although implementation might not be considered right now,
I do think it is important to an extent.
Shadows might be done as a flagged dynavar, import in would
be simply creating a block local with an initial value, and
export out would simply be binding to a local (possibly
creating the local) in the enclosing scope.


Guy N. Hurst


-- 
HurstLinks Web Development    http://www.hurstlinks.com/
Norfolk, VA  23510            (757)623-9688 FAX 623-0433
PHP/MySQL - Ruby/Perl - HTML/Javascript