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