Forum: Ruby ruby1.9 block scope

Posted by Daniel DeLorme (Guest)
on 2008-09-29 13:22
(Received via mailing list)
I could have sworn that one of the firm changes in ruby 1.9 was that
variables defined inside a block would also exist outside the block. But
  when I try it:

 >> 1.times{ x=2 }
=> 1
 >> x
NameError: undefined local variable or method `x' for main:Object

Did I dream all that? If it wasn't a dream, when and why was that change
reversed?

Daniel
Posted by James Coglan (Guest)
on 2008-09-29 13:41
(Received via mailing list)
>
> I could have sworn that one of the firm changes in ruby 1.9 was that
> variables defined inside a block would also exist outside the block


No, it's the reverse. Take this:

x = 5
1.upto(10) { |i| x = i }
puts x

ruby1.8 prints "10", ruby1.9 should print "5".
Posted by Daniel DeLorme (Guest)
on 2008-09-29 13:43
(Received via mailing list)
James Coglan wrote:
> ruby1.8 prints "10", ruby1.9 should print "5".
Actually you are confusing things a litte. In this case ruby1.9 prints
"10". Only the block *parameters* are local to the block:
   >> i = "a"
   => "a"
   >> 2.times{ |i| puts i }
   0
   1
   => 2
   >> puts i
   a

Which is nice, but not nearly as nice as having the variables assigned
inside the block available outside of it. These slides are quite old but
this was the original plan:
http://www.rubyist.net/~matz/slides/rc2003/mgp00012.html

And I seem to remember I experienced that behavior in 1.9 a few months
ago only. But not any more :-(
Posted by Yukihiro Matsumoto (Guest)
on 2008-09-29 14:07
(Received via mailing list)
Hi,

In message "Re: ruby1.9 block scope"
    on Mon, 29 Sep 2008 19:54:43 +0900, Daniel DeLorme 
<dan-ml@dan42.com> writes:

|I could have sworn that one of the firm changes in ruby 1.9 was that 
|variables defined inside a block would also exist outside the block. But 
|  when I try it:
|
| >> 1.times{ x=2 }
|=> 1
| >> x
|NameError: undefined local variable or method `x' for main:Object
|
|Did I dream all that? If it wasn't a dream, when and why was that change 
|reversed?

I have once presented a plan to make it work so, but have never
implemented.  So it's not "changed reversed".  Just the idea
abandoned.

              matz.
Posted by Daniel DeLorme (Guest)
on 2008-09-29 14:26
(Received via mailing list)
Yukihiro Matsumoto wrote:
> |
> |Did I dream all that? If it wasn't a dream, when and why was that change 
> |reversed?
> 
> I have once presented a plan to make it work so, but have never
> implemented.  So it's not "changed reversed".  Just the idea
> abandoned.

Ah, ok, then I guess I *did* dream the whole thing. For the record, I
think it's a great idea and deserves to be implemented... in ruby 2.0
maybe ;-)
Posted by Yukihiro Matsumoto (Guest)
on 2008-09-29 14:43
(Received via mailing list)
Hi,

In message "Re: ruby1.9 block scope"
    on Mon, 29 Sep 2008 21:24:02 +0900, Daniel DeLorme 
<dan-ml@dan42.com> writes:

|> | >> 1.times{ x=2 }
|> |=> 1
|> | >> x
|> |NameError: undefined local variable or method `x' for main:Object

|> I have once presented a plan to make it work so, but have never
|> implemented.  So it's not "changed reversed".  Just the idea
|> abandoned.
|
|Ah, ok, then I guess I *did* dream the whole thing. For the record, I 
|think it's a great idea and deserves to be implemented... in ruby 2.0 
|maybe ;-)

My vague idea for the issue is that when you see the reference to a
local variable inside of the block, the scope of the variable would be
upgraded to the level of the reference.

              matz.
Posted by Daniel DeLorme (Guest)
on 2008-09-29 18:06
(Received via mailing list)
Yukihiro Matsumoto wrote:
> upgraded to the level of the reference.
Do you mean upgrade the scope of the variable dynamically? Is that even
possible? I thought that all local vars had their scope pretty much set
in stone at the lexical level. But if you could upgrade their scoping
level dynamically... that would be nifty indeed!
Posted by geo ssscripting (vhaerun)
on 2008-09-29 19:03
Daniel DeLorme wrote:
> Yukihiro Matsumoto wrote:
>> upgraded to the level of the reference.
> Do you mean upgrade the scope of the variable dynamically? Is that even
> possible? I thought that all local vars had their scope pretty much set
> in stone at the lexical level. But if you could upgrade their scoping
> level dynamically... that would be nifty indeed!

If he did that , we wouldn't have locals anymore .
Posted by Nobuyoshi Nakada (nobu)
on 2008-09-29 21:07
(Received via mailing list)
Hi,

At Tue, 30 Sep 2008 00:23:17 +0900,
Daniel DeLorme wrote in [ruby-talk:316347]:
> > My vague idea for the issue is that when you see the reference to a
> > local variable inside of the block, the scope of the variable would be
> > upgraded to the level of the reference.
> 
> Do you mean upgrade the scope of the variable dynamically? Is that even 
> possible? I thought that all local vars had their scope pretty much set 
> in stone at the lexical level. But if you could upgrade their scoping 
> level dynamically... that would be nifty indeed!

I guess the parser would do it at the compile time.
Posted by namekuseijin (Guest)
on 2008-09-29 22:02
(Received via mailing list)
On Sep 29, 12:23 pm, Daniel DeLorme <dan...@dan42.com> wrote:
> > local variable inside of the block, the scope of the variable would be
> > upgraded to the level of the reference.
>
> Do you mean upgrade the scope of the variable dynamically? Is that even
> possible? I thought that all local vars had their scope pretty much set
> in stone at the lexical level. But if you could upgrade their scoping
> level dynamically... that would be nifty indeed!

Yeah, that would be so... 1970's!

Even javascript seems to finally have abandoned dynamic scoping in
favor of friggin' *ALGOL*'s lexical scoping... I wonder why would ruby
insist on sloppy programming by opening this old can of worms...
Posted by Daniel DeLorme (Guest)
on 2008-09-30 02:12
(Received via mailing list)
Nobuyoshi Nakada wrote:
> 
> I guess the parser would do it at the compile time.

That was also my guess; it least it's an easy concept to imagine. But it
does bring the question of what to do when you *don't* want variables to
"escape" into the enclosing scope? e.g.

class Foo
   defined_method :bar do
     x = 1  #I don't want x to be defined in the Foo scope
   end
   defined_method :baz do
     x = 2  #because it would wind up shared with this method
   end
end

The best I could think of was that a variable shouldn't be upgraded if
the enclosing scope is a "class" or "module" section. That can be
detected at parse time so it would work with lexical binding.

But it would be very interesting indeed if you could bind a block's
variables to the enclosing scope dynamically. You could say:
   block.call_using_enclosing_scope #e.g. define_method
   block.call_using_own_scope #e.g. each

To me that feels very very powerful. And more power to the programmer is
good, right? ;-)
Posted by Daniel DeLorme (Guest)
on 2008-09-30 02:15
(Received via mailing list)
namekuseijin wrote:
> Yeah, that would be so... 1970's!
> 
> Even javascript seems to finally have abandoned dynamic scoping in
> favor of friggin' *ALGOL*'s lexical scoping... I wonder why would ruby
> insist on sloppy programming by opening this old can of worms...

Hehe, you have somewhat of a point. Local variables and proper isolation
  of scope are pretty important to structured programming. But we
weren't talking about a free-for-all opening of all scopes, just about
the scope of local variables within *blocks*. I wouldn't much like my
method-local variables to creep into the global scope just because I
forgot to define them with "var", no thank you.
Posted by Nobuyoshi Nakada (nobu)
on 2008-09-30 02:46
(Received via mailing list)
Hi,

At Tue, 30 Sep 2008 09:10:39 +0900,
Daniel DeLorme wrote in [ruby-talk:316386]:
> class Foo
     define_method :bar do |;x|
>      x = 1  #I don't want x to be defined in the Foo scope
>    end
     define_method :baz do |;x|
Posted by Yukihiro Matsumoto (Guest)
on 2008-09-30 06:15
(Received via mailing list)
Hi,

In message "Re: ruby1.9 block scope"
    on Tue, 30 Sep 2008 09:10:39 +0900, Daniel DeLorme 
<dan-ml@dan42.com> writes:

|That was also my guess; it least it's an easy concept to imagine. But it 
|does bring the question of what to do when you *don't* want variables to 
|"escape" into the enclosing scope? e.g.
|
|class Foo
|   defined_method :bar do
|     x = 1  #I don't want x to be defined in the Foo scope
|   end
|   defined_method :baz do
|     x = 2  #because it would wind up shared with this method
|   end
|end

As Nobu stated, you can explicitly declare block local variables,
using ';'.  Besides that above code would not share variable x, since
the variable is not used upper level.   They are two distinct
variables at the same level, with a same name.  See the following
code, that makes a variables shared among blocks:

class Foo
   defined_method :bar do
     x = 1
   end
   defined_method :baz do
     x = 2
   end
   x = 45  # this assignment would make x shared with foo and bar under 
the new rule.
end

The reason I haven't introduced it yet in Ruby is that single
assignment after the blocks can change the scope of a variable
afterward.  Same thing happens assignments _before_ the blocks
already.  But I hesitated to enhance that far.

              matz.
Posted by Mike Gold (mikegold)
on 2008-09-30 09:50
Yukihiro Matsumoto wrote:
> 
> As Nobu stated, you can explicitly declare block local variables,
> using ';'.  Besides that above code would not share variable x, since
> the variable is not used upper level.   They are two distinct
> variables at the same level, with a same name.  See the following
> code, that makes a variables shared among blocks:
> 
> class Foo
>    defined_method :bar do
>      x = 1
>    end
>    defined_method :baz do
>      x = 2
>    end
>    x = 45  # this assignment would make x shared with foo and bar under 
> the new rule.
> end
> 
> The reason I haven't introduced it yet in Ruby is that single
> assignment after the blocks can change the scope of a variable
> afterward.  Same thing happens assignments _before_ the blocks
> already.  But I hesitated to enhance that far.
> 
>               matz.

Making the scope of x contingent upon what comes later would result, I 
believe, in extreme confusion.

Let's say Foo is a large class.  Joe Schmo, who did not write Foo, comes 
along and adds some code to the bottom, such as the 'x = 45' in your 
example.  Suddenly there is a bug in Foo.  It seems impossible to Joe, 
but there it is.  He wonders if it is caused by the recent sunspots.  He 
wraps his computer in tin foil, but to no avail.  The tests for bar and 
baz still fail as a result of his (obviously, to him) unrelated change.

This was the 'tall' case, but there is also the 'wide' case of deeply 
nested scopes.  An equal helping of confusion applies here too.

One might argue that when 'x = 45' appears before bar and baz, this 
_already_ changes the meaning of bar and baz.  But the situation here is 
entirely different, in my mind.  Don't most of us read code from top to 
bottom?
Posted by Yukihiro Matsumoto (Guest)
on 2008-09-30 10:09
(Received via mailing list)
Hi,

In message "Re: ruby1.9 block scope"
    on Tue, 30 Sep 2008 16:49:19 +0900, Mike Gold 
<mike.gold.4433@gmail.com> writes:

|Making the scope of x contingent upon what comes later would result, I 
|believe, in extreme confusion.

|One might argue that when 'x = 45' appears before bar and baz, this 
|_already_ changes the meaning of bar and baz.  But the situation here is 
|entirely different, in my mind.  Don't most of us read code from top to 
|bottom?

Understandable.  That's the very reason the current Ruby does not work
like this.

              matz.
Posted by Mike Gold (mikegold)
on 2008-09-30 10:25
Yukihiro Matsumoto wrote:
> Hi,
> 
> In message "Re: ruby1.9 block scope"
>     on Tue, 30 Sep 2008 16:49:19 +0900, Mike Gold 
> <mike.gold.4433@gmail.com> writes:
> 
> |Making the scope of x contingent upon what comes later would result, I 
> |believe, in extreme confusion.
> 
> |One might argue that when 'x = 45' appears before bar and baz, this 
> |_already_ changes the meaning of bar and baz.  But the situation here is 
> |entirely different, in my mind.  Don't most of us read code from top to 
> |bottom?
> 
> Understandable.  That's the very reason the current Ruby does not work
> like this.
> 
>               matz.

The current ruby doesn't, but a future one might?  The reason I posted 
was because the phrase "I haven't introduced it yet" might imply that it 
could happen.
Posted by Yukihiro Matsumoto (Guest)
on 2008-09-30 10:32
(Received via mailing list)
Hi,

In message "Re: ruby1.9 block scope"
    on Tue, 30 Sep 2008 17:24:03 +0900, Mike Gold 
<mike.gold.4433@gmail.com> writes:

|The current ruby doesn't, but a future one might?  The reason I posted 
|was because the phrase "I haven't introduced it yet" might imply that it 
|could happen.

Yes, it could happen, but not for sure.  This idea revisit me
everytime I see "undefined local variable or method" error.

              matz.
Posted by Daniel DeLorme (Guest)
on 2008-09-30 10:59
(Received via mailing list)
Mike Gold wrote:
> This was the 'tall' case, but there is also the 'wide' case of deeply 
> nested scopes.  An equal helping of confusion applies here too.
> 
> One might argue that when 'x = 45' appears before bar and baz, this 
> _already_ changes the meaning of bar and baz.  But the situation here is 
> entirely different, in my mind.  Don't most of us read code from top to 
> bottom?

Yes, I would argue that, and I believe most of us don't *add* new code
always at the bottom of the file. If the bar and baz methods are defined
at the bottom and Joe Schmo adds x = 45 at the top, he has the same
problem. I really don't see how it's any different; it's symmetric. Bugs
happen, and it's possible to come up with "problems cases" for
absolutely every feature in ruby, but that doesn't mean they turn out to
be problems in reality.

I must ask: is this confusing to *you* or are you trying to "protect" a
hypothetical Joe Schmo? I'll take the hypothetically confused Joe Schmo
over the very *real* confusion of every ruby newbie who wonders why his
local var has disappeared after the loop.
Posted by David A. Black (Guest)
on 2008-09-30 11:42
(Received via mailing list)
Hi --

On Tue, 30 Sep 2008, Yukihiro Matsumoto wrote:

> |   defined_method :bar do
> variables at the same level, with a same name.  See the following
> end
>
> The reason I haven't introduced it yet in Ruby is that single
> assignment after the blocks can change the scope of a variable
> afterward.  Same thing happens assignments _before_ the blocks
> already.  But I hesitated to enhance that far.

Please continue to hesitate :-) That would be very hard to deal with.
As a reader of the code, you'd have to do a two-pass visual scan
before you could begin to understand any of it. And you would have to
do that for *every* block, just in case, even if only 1% of them had a
variable defined later.


David
Posted by Daniel DeLorme (Guest)
on 2008-09-30 16:48
(Received via mailing list)
David A. Black wrote:
> before you could begin to understand any of it. And you would have to
> do that for *every* block, just in case, even if only 1% of them had a
> variable defined later.

You dont need a two-pass visual scan; it just allows you to assume that
a variable defined a line L of a method will be available for reference
at line L+n, no matter if it was defined inside a block or not. It
should be common sense, really.
Posted by Mike Gold (mikegold)
on 2008-09-30 16:52
Daniel DeLorme wrote:
> Mike Gold wrote:
>> This was the 'tall' case, but there is also the 'wide' case of deeply 
>> nested scopes.  An equal helping of confusion applies here too.
>> 
>> One might argue that when 'x = 45' appears before bar and baz, this 
>> _already_ changes the meaning of bar and baz.  But the situation here is 
>> entirely different, in my mind.  Don't most of us read code from top to 
>> bottom?
> 
> Yes, I would argue that, and I believe most of us don't *add* new code
> always at the bottom of the file. If the bar and baz methods are defined
> at the bottom and Joe Schmo adds x = 45 at the top, he has the same
> problem. I really don't see how it's any different; it's symmetric. Bugs
> happen, and it's possible to come up with "problems cases" for
> absolutely every feature in ruby, but that doesn't mean they turn out to
> be problems in reality.
> 
> I must ask: is this confusing to *you* or are you trying to "protect" a
> hypothetical Joe Schmo? I'll take the hypothetically confused Joe Schmo
> over the very *real* confusion of every ruby newbie who wonders why his
> local var has disappeared after the loop.

Joe Schmo is all of us.  Like D. Black says, all of us would need to 
read the code twice before understanding it.  In practice it is probably 
more common to read with backtracking, which is even slower.

On the other hand, a ruby newbie who first encounters the rules for 
local variable bindings (in the form of an error) should in no manner be 
shielded from understanding them.  That error is an important learning 
experience.

For old-timers like me who, coming from lisp, often use closures to 
preserve state in conjunction with define_method on anonymous classes, 
the impact of the proposed change is significant (or unmanageable, 
depending on your point of view).  It transforms code complexity from 
O(n)--n nested blocks--to O(n^2)--n nested blocks (which can't even be 
called "nested" anymore) with backtracking.
Posted by Mike Gold (mikegold)
on 2008-09-30 17:03
Daniel DeLorme wrote:
> David A. Black wrote:
>> before you could begin to understand any of it. And you would have to
>> do that for *every* block, just in case, even if only 1% of them had a
>> variable defined later.
> 
> You dont need a two-pass visual scan; it just allows you to assume that
> a variable defined a line L of a method will be available for reference
> at line L+n, no matter if it was defined inside a block or not. It
> should be common sense, really.

You have described exactly what D. Black and I mean by a two-pass scan. 
Line L is dependent on code arbitrarily far ahead at L+n.

When you encounter the variable at line L+n, you should backtrack to 
line L to determine whether or not the block scopes are aligned in such 
a way to change the meaning of line L.
Posted by Mike Gold (mikegold)
on 2008-09-30 19:07
I hope I'm not belaboring the point, but --

a = Class.new {
  define_method(:f) {
    x
  }

  define_method(:x) {
    33
  }
}.new

x = 44

b = Class.new {
  define_method(:f) {
    x
  }

  define_method(:x) {
    55
  }
}.new

p a.f # => 33
p b.f # => 44

You want a.f == 44.  I do not.

If you think this is a contrived example then you haven't been exposed
to the elegant solution this gives for certain cases.  At run-time we
are creating additional layers of abstraction which translate the
current context into pieces which are passed to lower levels.
Posted by Yukihiro Matsumoto (Guest)
on 2008-09-30 19:44
(Received via mailing list)
Hi,

In message "Re: ruby1.9 block scope"
    on Wed, 1 Oct 2008 02:06:38 +0900, Mike Gold 
<mike.gold.4433@gmail.com> writes:

|I hope I'm not belaboring the point, but --

<snip>

Yes, but

 * Class.new and define_method is a rather rare examples, of which
   non-block counterpart introduce new scopes.
 * In 1.9, you can have explicit block local variables if you expect
   any confusion.

              matz.
Posted by Mike Gold (mikegold)
on 2008-09-30 20:41
Yukihiro Matsumoto wrote:
> 
> Yes, but
> 
>  * Class.new and define_method is a rather rare examples, of which
>    non-block counterpart introduce new scopes.

But it's not a rare example for me.  It's a great solution to an 
otherwise tangled problem.  When I have more time I can post some code 
if my example is not convincing.

The whole point is that I don't want to introduce a new scope.  As I 
briefly mentioned, I am writing adapters which put a "new face" on the 
current binding so that other levels can understand it.

By contrast, it would be convoluted to create all new scopes each with 
instance variables pointing back to the places I just came from.  The 
code would be Java-like: reams of scaffolding which serve no end except 
to compensate for a missing language feature.

>  * In 1.9, you can have explicit block local variables if you expect
>    any confusion.

I would use the block local syntax every time, because I would always 
expect confusion.  The ruby "good feeling" would be gone, for me. 
Effectively it would be Lisp "let" constructs, which is fine I guess, 
but it's Lisp.

I have always thought of ruby as a (non-defmacro) Lisp "optimized" to 
make programmers more happy.  In this case I feel the proposed 
"optimization" goes too far, producing unexpected behavior like in the 
example I gave.  But I realize POLS refers to your surprise, not my 
surprise.
Posted by Yukihiro Matsumoto (Guest)
on 2008-09-30 20:54
(Received via mailing list)
Hi,

In message "Re: ruby1.9 block scope"
    on Wed, 1 Oct 2008 03:40:08 +0900, Mike Gold 
<mike.gold.4433@gmail.com> writes:

|>  * Class.new and define_method is a rather rare examples, of which
|>    non-block counterpart introduce new scopes.
|
|But it's not a rare example for me.  It's a great solution to an 
|otherwise tangled problem.  When I have more time I can post some code 
|if my example is not convincing.

<snip rest>

Thank you for your valuable input.  And don't worry I have not decided
to put this in the language, even after 2.0.

              matz.
Posted by Nobuyoshi Nakada (nobu)
on 2008-10-01 05:59
(Received via mailing list)
Hi,

At Wed, 1 Oct 2008 03:53:26 +0900,
Yukihiro Matsumoto wrote in [ruby-talk:316501]:
> Thank you for your valuable input.  And don't worry I have not decided
> to put this in the language, even after 2.0.

How about making all local variables other than block arguments
method/class/toplevel?
Posted by Daniel DeLorme (Guest)
on 2008-10-01 07:21
(Received via mailing list)
Mike Gold wrote:
> Yukihiro Matsumoto wrote:
>> Yes, but
>>
>>  * Class.new and define_method is a rather rare examples, of which
>>    non-block counterpart introduce new scopes.
> 
> But it's not a rare example for me.  It's a great solution to an 
> otherwise tangled problem.  When I have more time I can post some code 
> if my example is not convincing.

Yes, I would love to see some non-contrived example code. I don't use
define_method very often and I have hardly ever used Class.new,
certainly not with several levels of nested blocks. The common case for
which I *would* like to use this suggested featured is something like 
this:

1   collection.each do |element|
2     changed = true if element.change
3   end
4   do_something if changed

Are you really saying that upon reading line 4 you have to backtrack to
line 2 in order to understand this code?

Far from a monster of O(n^2) complexity, this is the kind of code that
most programmers would expect to work. Except it doesn't, and if I have
to hazard a guess I would say that 90% of ruby newbies have run into
that gotcha.

Of course we all learn to work around it and even exploit it, but it
doesn't mean it was right to begin with. While "intuitive" and "POLS"
are loaded terms, if 90% of newbies bump into a gotcha, IMHO it's the
sign of a design flaw, and matz was right to notice it.
Posted by Brian Candler (candlerb)
on 2008-10-01 10:20
Nobuyoshi Nakada wrote:
> How about making all local variables other than block arguments
> method/class/toplevel?

On the plus side:

  def my_find(a)
    # res=nil not needed!
    a.each { |e| res = e if e =~ /foo/ }
    res
  end

On the minus side:

  m = lambda { |x,y| tmp = x*2; tmp + y }

Here tmp becomes a "static" variable (in C-speak) by default, unless you 
write

  m = lambda { |x,y;tmp| ... }

I think this could cause hard-to-find bugs if the lambda is invoked from 
multiple threads, and a lot of confusion for people expecting functions 
written in this form to be side-effect free.

I guess it could become another difference between lambda and 
Proc/block. I'm not sure if that would make things less confusing or 
more.

I still think the current rule ("tmp is part of the closure if it is 
assigned to earlier in the method") is much more sane than the suggested 
alternative ("tmp is part of the closure if it is assigned to earlier 
*or later* in the method")
Posted by Brian Candler (candlerb)
on 2008-10-01 10:34
Daniel DeLorme wrote:
> 1   collection.each do |element|
> 2     changed = true if element.change
> 3   end
> 4   do_something if changed
> 
> Are you really saying that upon reading line 4 you have to backtrack to
> line 2 in order to understand this code?

I think the point is more this:

class Foo
  attr_reader :changed

  def update
    collection.each do |element|
      element << "\n" if changed      # <<<<
    end
    ...
    ...
    ...
    collection.each do |element|
      changed = true if element.change
    end
  end
end

At the marked line, you can't tell whether 'changed' is a local variable 
or a method call on this object until you have read forward to the end 
of the method. For me, this is horrid.

Perhaps more importantly though, as far as I can see it makes irb pretty 
useless, since it can't predict the future. What's supposed to happen 
when you type this, one line at a time?

def tmp; "hello"; end
m = lambda { |x| tmp + x }
m[" world"]
tmp = "goodbye"
m[" world"]

This particular example may be somewhat contrived, but if code behaves 
differently in irb than when read from a source file, that would be 
horrid (and difficult to explain) too.

Regards,

Brian.
Posted by Jim McKerchar (Guest)
on 2008-10-01 12:45
Attachment: jim_mckerchar.vcf (178 Bytes)
(Received via mailing list)
Hello to all.

I wonder if someone is able to help me out. I'm using the RSCM gem to
help us with our deployment and am running into some difficulties when
using RSCM::Subversion.diff to get the changes made since a "base"
revision.

When i call RSCM::Subversion.diff i get the following error:
*/
scm.diff("branches/optimization/Rakefile", 1533, 1665)/*

/svn: Can't write to stream: The pipe is being closed.
c:/ruby/lib/ruby/gems/1.8/gems/rscm-0.5.1/lib/rscm/command_line.rb:111:in
`verify_exit_code':  (RSCM::CommandLine::ExecutionError)
dir : C:/Documents and Settings/Jim/My Documents/Work/OffroadDeployR
command : svn diff --revision 1533:1665
"svn://svn.******/Ruby/****/branches/optimization/Rakefile"
executed command : svn diff --revision 1533:1665
"svn://svn.******/Ruby/****/branches/optimization/Rakefile"
exitstatus: 1
STDERR TAIL START
 doesn't exist
STDERR TAIL END
    from
c:/ruby/lib/ruby/gems/1.8/gems/rscm-0.5.1/lib/rscm/command_line.rb:140:in
`e'
    from
c:/ruby/lib/ruby/gems/1.8/gems/rscm-0.5.1/lib/rscm/command_line.rb:70:in
`execute'
    from
c:/ruby/lib/ruby/gems/1.8/gems/rscm-0.5.1/lib/rscm/base.rb:281:in 
`execute'
    from
c:/ruby/lib/ruby/gems/1.8/gems/rscm-0.5.1/lib/rscm/scm/subversion.rb:82:in
`diff'
    from svn_wrapper.rb:30
    from svn_wrapper.rb:29:in `each'
    from svn_wrapper.rb:29
    from svn_wrapper.rb:28:in `each_pair'
    from svn_wrapper.rb:28
    from
c:/ruby/lib/ruby/gems/1.8/gems/rscm-0.5.1/lib/rscm/revisions.rb:64:in 
`each'
    from
c:/ruby/lib/ruby/gems/1.8/gems/rscm-0.5.1/lib/rscm/revisions.rb:64:in 
`each'
    from svn_wrapper.rb:7

/However if i copy the svn diff cmd from the error codeand run it from a
command line, I get a diff of the files as expected.:

*/svn diff --revision 1533:1665
"svn://svn.******/Ruby/****/branches/optimization/Rakefile"/*
/
/I'm running Ruby 1.8.6 on Windows XP with the RSCM v0.5.1 (oh and
Subversion 1.5.1). If i've missed anything let me know. Would really
appreciate help if anyone can.

Cheers
Jim
Posted by Joe Wölfel (Guest)
on 2008-10-01 16:01
(Received via mailing list)
On 1 oct. 08, at 04:18, Brian Candler wrote:

>   end
res =  a.find { |e| e =~ /foo/ }
Posted by Brian Candler (candlerb)
on 2008-10-01 17:27
Joe Wölfel wrote:
> On 1 oct. 08, at 04:18, Brian Candler wrote:
> 
>>   end
> res =  a.find { |e| e =~ /foo/ }

Yes I know. That's why I called it "myfind". I made a simple concrete 
example of a pattern: iterate doing each, assign something during the 
iteration, use the assigned value outside of the iteration.

Enumerable#find by itself is not sufficient for all programming needs.
Posted by Joe Wölfel (Guest)
on 2008-10-01 17:33
(Received via mailing list)
Agreed.  But it would be a stronger example if it were something
that couldn't be done easily without a new language feature.
Posted by Mike Gold (mikegold)
on 2008-10-01 20:45
Daniel DeLorme wrote:
> Mike Gold wrote:
>> Yukihiro Matsumoto wrote:
>>> Yes, but
>>>
>>>  * Class.new and define_method is a rather rare examples, of which
>>>    non-block counterpart introduce new scopes.
>> 
>> But it's not a rare example for me.  It's a great solution to an 
>> otherwise tangled problem.  When I have more time I can post some code 
>> if my example is not convincing.
> 
> Yes, I would love to see some non-contrived example code. I don't use
> define_method very often and I have hardly ever used Class.new,
> certainly not with several levels of nested blocks. The common case for
> which I *would* like to use this suggested featured is something like 
> this:

Because you've hardly ever used Class.new, and therefore are probably 
not familiar with run-time generated classes which present a given 
binding as different views to external onlookers, then you won't 
appreciate what I have to say.  To you everything is blub, and you 
wonder why non-blub things are necessary.  It's a paradox, that you need 
to understand before you can understand.  See 
http://www.paulgraham.com/avg.html

The strategy I've described comes from Lisp.  And it's awesome.

In fact I think my example does suffice.  You just need to imagine it 
being using on a slightly larger scale.  As I said previously in this 
thread, "it would be convoluted to create all new scopes each with 
instance variables pointing back to the places I just came from.  The 
code would be Java-like: reams of scaffolding which serve no end except 
to compensate for a missing language feature."  Do you have a response 
to that?  Please don't repeat your argument yet again; instead, try to 
understand what I've said.

> 1   collection.each do |element|
> 2     changed = true if element.change
> 3   end
> 4   do_something if changed
> 
> Are you really saying that upon reading line 4 you have to backtrack to
> line 2 in order to understand this code?

Yes, I backtracked just now, before I read your last sentence above.  I 
checked to be sure that 'changed' means a local variable.   I have to do 
this with every variable in arbitrarily long scopes.  You are thinking 
in terms of small examples, but I am thinking about large ones.

> Far from a monster of O(n^2) complexity, 

It is O(n^2) complex because it requires a backtrack for each case.  I 
like to be certain what code does.  I will always backtrack in order to 
be certain.

> this is the kind of code that
> most programmers would expect to work. Except it doesn't, and if I have
> to hazard a guess I would say that 90% of ruby newbies have run into
> that gotcha.

You did not address my counterpoint to your argument here.  You just 
repeated your argument.
Posted by Pit Capitain (Guest)
on 2008-10-01 21:41
(Received via mailing list)
2008/10/1 Mike Gold <mike.gold.4433@gmail.com>:
> appreciate what I have to say.
So Mike, please show us a real non-contrived example to enlighten us.
I've often used Class.new but still don't see your problem.

> In fact I think my example does suffice.

No it doesn't. In your example there's no obvious need to use
Class.new and define_method.

>> Far from a monster of O(n^2) complexity,
>
> It is O(n^2) complex because it requires a backtrack for each case.  I
> like to be certain what code does.  I will always backtrack in order to
> be certain.

You have to do that in current Ruby, too, because you have to check
for local variables that have been assigned to before the code blocks.
Expanding the checks to the end of the scope doesn't change the O
complexity.

Regards,
Pit
Posted by Suraj Kurapati (snk)
on 2008-10-01 22:30
Brian Candler wrote:
>   def my_find(a)
>     # res=nil not needed!
>     a.each { |e| res = e if e =~ /foo/ }
>     res
>   end

IMHO, the res=nil is necessary to preserve the semantics of a closure:

A lambda/closure should *enclose* the variables around it into a neat 
package.  It should *not* emit new variables into its surroundings! 
Otherwise, it would be something like an "opener" instead of a 
"closure".

> I still think the current rule ("tmp is part of the closure if it is 
> assigned to earlier in the method") is much more sane than the suggested 
> alternative ("tmp is part of the closure if it is assigned to earlier 
> *or later* in the method")

I agree wholeheartedly and I hope Ruby does not change in this regard.
Posted by Mike Gold (mikegold)
on 2008-10-01 22:56
Pit Capitain wrote:
> So Mike, please show us a real non-contrived example to enlighten us.
> I've often used Class.new but still don't see your problem.

Do you understand my previous paragraph:

By contrast, it would be convoluted to create all new scopes each with
instance variables pointing back to the places I just came from.  The
code would be Java-like: reams of scaffolding which serve no end except
to compensate for a missing language feature.

I ask because I've seen no indication that others have gotten it besides 
matz.  A larger example would be just what I've written already, only 
larger.  But if we aren't first on the same page with respect to the 
above, the larger example will not help either.  There is nothing I'm 
holding back.  If it's not obvious then ask a question.

I would suggest to actively seek what is meant by the above, rather than 
to passively demand code which will infuse you with enlightenment.  It 
won't.

Rather, treat it as a homework problem: construct a case where a set of 
dynamically generated _unique_ classes bound to the current context 
results in better code compared to a set of named classes defined in a 
different scopes containing instance variables to that current context. 
Go.

I don't mean to lecture, but after the necessary tools have been laid on 
the table, I do resent students who demand to be shown.  It is only the 
curious who really learn.  Questions are welcome.  Demands are not.

> You have to do that in current Ruby, too, because you have to check
> for local variables that have been assigned to before the code blocks.

But you don't have to check for locals that have been assigned after. 
See my example.
Posted by Daniel DeLorme (Guest)
on 2008-10-02 06:42
(Received via mailing list)
Joe Wölfel wrote:
> 
> On 1 oct. 08, at 04:18, Brian Candler wrote:
>>
>>   def my_find(a)
>>     # res=nil not needed!
>>     a.each { |e| res = e if e =~ /foo/ }
>>     res
>>   end
> 
> res =  a.find { |e| e =~ /foo/ }

Actually that has a slightly different effect.
Brian's my_find finds the *last* matching expression. ;-)
Posted by Daniel DeLorme (Guest)
on 2008-10-02 07:47
(Received via mailing list)
Mike Gold wrote:
> Because you've hardly ever used Class.new, and therefore are probably 
> not familiar with run-time generated classes which present a given 
> binding as different views to external onlookers, then you won't 
> appreciate what I have to say.  To you everything is blub, and you 
> wonder why non-blub things are necessary.  It's a paradox, that you need 
> to understand before you can understand.  See 
> http://www.paulgraham.com/avg.html
> 
> The strategy I've described comes from Lisp.  And it's awesome.

Just because I've hardly ever *had* to use Class.new doesn't mean that I
don't understand how it works or that I'm some kind of idiot. It's true
that I don't appreciate what you have to say. And I imagine 99.9% of
ruby coders won't either. The problem you describe is, by your own
admission, rooted in using ruby as an alternative lisp. It's great that
ruby is so flexible that you can do that, but ultimately ruby is ruby,
not lisp. I wouldn't hold back the language just so that it can stay
more like another language.

> In fact I think my example does suffice.  You just need to imagine it 
> being using on a slightly larger scale.  As I said previously in this 
> thread, "it would be convoluted to create all new scopes each with 
> instance variables pointing back to the places I just came from.  The 
> code would be Java-like: reams of scaffolding which serve no end except 
> to compensate for a missing language feature."  Do you have a response 
> to that?  Please don't repeat your argument yet again; instead, try to 
> understand what I've said.

I apologize for repeating myself. In my defense, your argument is
gibberish to me so there's not much I can reply to. If you're talking
about added complexity in the interpreter, I fail to see how that should
affect the language's design. And if you're talking about added
complexity in the ruby code, I fail to see how the proposal has anything
to do with instance variables or would require additional "scaffolding".
At most you'd need to avoid re-using variable names in a given scope,
and that good programming practice anyway.

> Yes, I backtracked just now, before I read your last sentence above.  I 
> checked to be sure that 'changed' means a local variable.   I have to do 
> this with every variable in arbitrarily long scopes.  You are thinking 
> in terms of small examples, but I am thinking about large ones.
> It is O(n^2) complex because it requires a backtrack for each case.  I 
> like to be certain what code does.  I will always backtrack in order to 
> be certain.

Ok, I now see that it is indeed O(n^2) complex. But you *already* have
to do that for large scopes; you have to consider every variable that
previously appeared in the scope, and that's O(n^2). The new rule would
make it 2*O(n^2) [which, in math speak, is still O(n^2)]. But this is
only a problem if n is very large; if you really have a scope that long
then I dare say that you already have a problem and some refactoring is
in order. Whatever happened to "no more than 10-20 lines per method" ?
Posted by Daniel DeLorme (Guest)
on 2008-10-02 07:49
(Received via mailing list)
Daniel DeLorme wrote:
> Ok, I now see that it is indeed O(n^2) complex. But you *already* have 
> to do that for large scopes; you have to consider every variable that 
> previously appeared in the scope, and that's O(n^2). The new rule would 
> make it 2*O(n^2) [which, in math speak, is still O(n^2)]. But this is 
> only a problem if n is very large; if you really have a scope that long 
> then I dare say that you already have a problem and some refactoring is 
> in order. Whatever happened to "no more than 10-20 lines per method" ?

Sorry, I didn't think this through enough.

The new rule would not change the current rule that variables defined at
L are not considered as variables at all at lines L-n. So under the new
rule, code would have mathematically the *same* complexity but
practically it might be more tricky:

   define_method :foo do
     #say, 20 lines of code
   end
   foobar

under new rules, you'd have to backtrack until the top of the scope to
see if "foobar" is a variable or not.

under old rules, you'd have to backtrack until the top of the scope to
see if "foobar" is a variable or not, while taking into account that
variables defined in a sub-scope are self-contained, which means that
you can skip large sections of indented code.

I hope I got it right this time.
Posted by Daniel DeLorme (Guest)
on 2008-10-02 08:05
(Received via mailing list)
Suraj Kurapati wrote:
> package.  It should *not* emit new variables into its surroundings! 
> Otherwise, it would be something like an "opener" instead of a 
> "closure".

If you're thinking in terms of lambdas and anonymous functions then I
can see how you would think that. But I think of blocks more in terms of
control structures. Variables defined inside a "if" or "while" statement
continue existing outside of the if/while, and so should variables
defined inside a block.

I don't deny that that lambdas are useful, but I do think we have a
conflict here: blocks are used both as control structures and as
lambdas, and those two would benefit from having different scoping 
rules.
Posted by Pit Capitain (Guest)
on 2008-10-02 08:17
(Received via mailing list)
2008/10/1 Mike Gold <mike.gold.4433@gmail.com>:
> Rather, treat it as a homework problem: construct a case where a set of
> dynamically generated _unique_ classes bound to the current context
> results in better code compared to a set of named classes defined in a
> different scopes containing instance variables to that current context.

Why should I do that? You said that changing Ruby to automatically
expand the scope of local variables would make some code harder to
visually inspect and showed an example using Class.new and
define_method. But your example could be changed easily to use normal
class and method definitions without altering its behaviour.

My question is why you need the current context. This is the very part
which you don't explain in your example. I'm not asking "how" but
"why". By writing code I can only learn about the "how" part. I'm
always interested to learn something new, but if you don't want to
answer the question, that's fine for me, too.

>> You have to do that in current Ruby, too, because you have to check
>> for local variables that have been assigned to before the code blocks.
>
> But you don't have to check for locals that have been assigned after.

Oh really? I think I didn't get this, yet :-) But how does this change
the asymptotic complexity? This is what I wrote about.

Regards,
Pit
Posted by Joe Wölfel (Guest)
on 2008-10-02 15:08
(Received via mailing list)
Yes.  You are right.  In that case might be good to not perform a
regular expression match on every element.
res = a.reverse.find { |e| e =~ /foo/ }
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.