On Tue, 13 Mar 2001, Yukihiro Matsumoto wrote:

> The one is allowing explicit declaration of block local variables.
> <a,b|c,d> is one choice of notations.

One problem I can see with this is that it will make code harder to
modify. If I change the contents of a block, I will have to remember
to "declare" my usage in the <>'s. I kinda liked not having to define
my variables before using them.

> The other notation candidates may be special block form({{}}),

I already find the difference between do..end and {} to be confusingly
similar. One block type would be nicer, especially if it could remove
the difference between Proc objects and Method objects.

> and special declarative assignment.

This could be handled with a naming convention, and fits in with the
current design of Ruby...

  :name  is global in scope
  $name  is global in scope
  @@name is class in scope
  @name  is instance in scope
  _name  is block in scope

However, I'm not so sure this is the way to go either.

> The other idea is implicit propagation of variable scope, that is

In other words, a flattening of scope. I like this idea as it aligns
with not having nested methods. Eg, you can't do this:

  def method1
    def method1a
    end
    def method1b
    end
  end
  def method2
  end

I used nested procedures all the time when I was programming in Pascal
and found it very useful at the time. However, it has its problems and I
think things are better without them.

The same argument applies to nested variables in that they're useful, but
things are probably better without them.



*** start of loony tunes proposal ***

I would like to suggest that scoping rules be removed from do..end blocks
and stricter scoping rules be introduced for {} blocks.

Let's look at do..end first. Variables are accessible inside, and new
variables are available outside. This can be slightly extended so that
the parameters are shadowed, as follows:

  i = 123
  j = 10
  (1..10).each do |i|   # i becomes shadowed within the block
    j = i * 5
    k = i * 10
  end
  p [i, j, k]                  -> [123, 50, 100]

The "i" is protected because it's defined in the |i| parameter list. This
is a nice way of just using a name for the loop without trashing anything
else. All other variables are just there and used, like BASIC. :)

This also makes the following possible:

  i = 1000
  (101..103).each do |i|
    (1..3).each do |i|
      p i
    end
    p i
  end
  p i

  1 2 3 101 1 2 3 102 1 2 3 103 1000

So if someone really cares, they could list a few more variables in the
||'s (which would be empty since there's not enough parameters passed)
and achieve their local variables that way. Kludge? Yep! :)

{}'s are redefined to be the same as method definitions. They have their
own scope with no pre-existing variables accessible and no new variables
being accessible either. They both return a value.

Eg:

  i = 123
  j = 10
  (1..10).each {|i|
    # accessing j at this point would be an error
    j = i * 5
    k = i * 10
  }
  p [i, j, k]                  -> [123, 10, error]

Eg, no local variables are accessible inside of a {} block, and any
variables defined inside are not subsequently accessible, just as if
the code had been refactored into a separate method.

Now for one final tweak which will clean up another bit of Ruby as well.

Now that {}'s are the same as methods, it would be good to be able to do
the following:

  def jack(x) p x end  # as per normal

  jill = {|x| p x }    # storing code into a variable

  jack(10)          -> prints 10  # as per normal
  jill(20)          -> prints 20  # behaves exactly the same

  {|x| p x}(30)     -> prints 30  # orthogonality is great

thus making {}'s and "def method" exactly the same. The problem currently
in the way of this happening is that giving the name alone only returns the
Object handle when performing a call is more desirable.

The brute force way is to define a default method to be called when the
name is used. However, looking at what Ruby does...

  p a    # will silently call a.inspect
  puts a # will silently call a.to_s
  1 + a  # will silently call a.coerce

it makes much more sense to define the interpreter perform a call when
interpreting the code... in other words

  a      # will silently call a.exec

All of a sudden my classes become just as good as the built-in classes.

  class Fred
    attr_accessor :var
    def exec
      @var
    end
  end

  a = Fred.new.var 10       -> 10
  b = a + 20                -> 30
  c = 30 + a                -> 40

  a = Fred.new.var "12345"  -> "12345"
  b = a + "hello"           -> "12345hello"
  c = "world" + a           -> "world12345"

because the interpreter reads in the source, finds "a" by itself, and calls
the "exec" method automatically. I can hook in and define how I want this
variable to behave - in this case, acting exactly like @val.

This is something I can't do in Ruby at the moment, therefore my classes
will never be able to do as much as the built-in's.

In summary:

  do..end is the same as Proc objects, and has no scoping rules.

  {} is the same as Method, and has its own scope.

  The interpreter calls the "exec" method when the name alone is used.

On the downside, these changes are not backwards compatible. There's two
ways to go on this aspect...

  1) Introduce new syntax while phasing out old syntax.

  2) Introduce a version number that tells the interpreter how to handle
     the code, while giving warnings on old constructs.

I like the second option better, but can imagine it would be a headache
to program the interpreter to handle this.

Now from the big picture viewpoint, these changes make code easier to
refactor and modify. To add new code, I can use {}'s to make sure it
doesn't disturb any existing code. To move code out, I can enclose it
it in {}'s, treat it like a method, then move it out. The syntax stays
simple and things are conceptually more distinct.

What do you think? I like it. :)

-- 
  spwhite / chariot.net.au