Parameter in a block is not local?

I thought a iterator with a block is like an nameless function call...
so if it is a function call, the parameter is local.
but for the following, the output is surprising:

a = 1
p a

1.upto(10) {|a| p a}

p a

···

--------------

E:\>ruby test_iterator.rb
1
1
2
3
4
5
6
7
8
9
10
10

a is changed!

but is it true that the "a" is not global to begin with....
but then, isn't the "a" inside the block more local than the "a"
outside?

like in Pascal, i think there can be nested functions and therefore,
there will be local and then "local that is more local" than the outer
local.
--
Posted via http://www.ruby-forum.com/.

SpringFlowers AutumnMoon wrote:

I thought a iterator with a block is like an nameless function call...
so if it is a function call, the parameter is local.
but for the following, the output is surprising:

Reread pickaxe2, p.51, second paragraph.

···

--
Posted via http://www.ruby-forum.com/\.

SpringFlowers AutumnMoon wrote:

I thought a iterator with a block is like an nameless function call...
so if it is a function call, the parameter is local.
but for the following, the output is surprising:

Also, I think I recall reading a post by Matz somewhere where he
shouldered the blame for that "feature" and said it was a design
mistake.

···

--
Posted via http://www.ruby-forum.com/\.

Hi --

I thought a iterator with a block is like an nameless function call...
so if it is a function call, the parameter is local.
but for the following, the output is surprising:

a = 1
p a

1.upto(10) {|a| p a}

p a

--------------

E:\>ruby test_iterator.rb
1
2
3
4
5
6
7
8
9
10

a is changed!

but is it true that the "a" is not global to begin with....
but then, isn't the "a" inside the block more local than the "a"
outside?

a is local, not global. The semantics of block parameters is
assignment semantics:

   >a>

basically means "a = ...", in the same scope as the scope in which the
block is created. Blocks are different in that respect from methods,
and the || notation (instead of (), as in methods) is a good reminder
that they're not the same. (Not that || specifically implies
assignment semantics, but it's a reminder that there's a difference.)

David

···

On Sun, 14 Oct 2007, SpringFlowers AutumnMoon wrote:

--
Upcoming training from Ruby Power and Light, LLC:
   * Intro to Ruby on Rails, Edison, NJ, October 23-26
   * Advancing with Rails, Edison, NJ, November 6-9
Both taught by David A. Black.
See http://www.rubypal.com for more info!

one way to think about it (not entirely correct) is this

  - if the parameter exists *already* it is reused
  - if not a block local var is created

this

  1.upto(10){|a| p a}

  p a

will throw an error - as you probably know. it's a fine line between having function call semantics and closure ones. we all want this to work

  message = 'hello world'
  42.times{ p message }

of course. so it's rather tricky. you can search the archives but i *think* the new rule is that introducing a var like so

  method{ |some_var| ...

will introduce a block local var (as you are expecting above), while this

  method{ p some_var

will not. i could be confused on this though, it really gets confusing to not violate POLS (referring to mine here) in all cases

   http://eigenclass.org/hiki.rb?Changes+in+Ruby+1.9#l7
   http://www.davidflanagan.com/blog/2007_08.html#000137

and, of course, search the archives - matz has spelled out the changes several times.

kind regards.

a @ http://codeforpeople.com/

···

On Oct 14, 2007, at 8:42 AM, SpringFlowers AutumnMoon wrote:

I thought a iterator with a block is like an nameless function call...
so if it is a function call, the parameter is local.
but for the following, the output is surprising:

a = 1
p a

1.upto(10) {|a| p a}

p a

--
it is not enough to be compassionate. you must act.
h.h. the 14th dalai lama

This seems to me along the same lines as

a = 1
if true
  a = 10
end
p a # => 10

Which certainly is not surprising or unwelcome.

Pat

···

On 10/14/07, SpringFlowers AutumnMoon <summercoolness@gmail.com> wrote:

I thought a iterator with a block is like an nameless function call...
so if it is a function call, the parameter is local.
but for the following, the output is surprising:

a = 1
p a

1.upto(10) {|a| p a}

p a

--------------

E:\>ruby test_iterator.rb
1
1
2
3
4
5
6
7
8
9
10
10

a is changed!

but is it true that the "a" is not global to begin with....
but then, isn't the "a" inside the block more local than the "a"
outside?

like in Pascal, i think there can be nested functions and therefore,
there will be local and then "local that is more local" than the outer
local.
--
Posted via http://www.ruby-forum.com/\.

SpringFlowers AutumnMoon wrote:

a = 1
p a

1.upto(10) {|a| p a}

p a

--------------

E:\>ruby test_iterator.rb
1
1
2
3
4
5
6
7
8
9
10
10

a is changed!

!Remark only!

There will be a change for soon upcoming Ruby 1.9.1:

irb(main):001:0> a = 1
=> 1
irb(main):002:0> p a
1
=> nil
irb(main):003:0> 1.upto(10) {|a| p a}
1
2
3
4
5
6
7
8
9
10
=> 1
irb(main):004:0> p a
1
=> nil

Wolfgang Nádasi-Donner

···

--
Posted via http://www.ruby-forum.com/\.

I thought a iterator with a block is like an nameless function call...

Similar, but not the same. Blocks are closures, so for example:

a = 1
1.times {p a}

will print 1 since a in the block refers to a in the outer scope.

so if it is a function call, the parameter is local.
but for the following, the output is surprising:

a = 1
p a

1.upto(10) {|a| p a}

p a

--------------

E:\>ruby test_iterator.rb
1
1
2
3
4
5
6
7
8
9
10
10

a is changed!

but is it true that the "a" is not global to begin with....
but then, isn't the "a" inside the block more local than the "a"
outside?

In Ruby 1.8 a block argument acts like a local in the containing scope.

This is changing in 1.9

http://eigenclass.org/hiki/Changes+in+Ruby+1.9#l8

···

On 10/14/07, SpringFlowers AutumnMoon <summercoolness@gmail.com> wrote:

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

SpringFlowers AutumnMoon wrote:

I thought a iterator with a block is like an nameless function call...

Here's another example(a modification of the example found in pickaxe2,
p 106):

if false
  data = "hello"
end

(1..3).each {data = "goodbye"}

puts data

--output:--
goodbye

That is equivalent to Java's call by value--but using references and C++
reference semantics, and the flat scope is converted to spheric scope
with assignment semantics applying throughout any call by value passing.
:slight_smile:

···

--
Posted via http://www.ruby-forum.com/\.

I should amend that by noting that it's a "one-way valve": if the
variable exists before the block is created, the scope is flat,
whereas if the variable doesn't exist yet, it also doesn't exist when
the block exits.

In other words, the local scope enters the block, from the left, so to
speak, bringing all its bindings with it; and it exits from the right
with only those bindings, which may or may not have been altered
during their time in the block.

David

···

On Mon, 15 Oct 2007, David A. Black wrote:

a is local, not global. The semantics of block parameters is
assignment semantics:

>a>

basically means "a = ...", in the same scope as the scope in which the
block is created.

--
Upcoming training from Ruby Power and Light, LLC:
   * Intro to Ruby on Rails, Edison, NJ, October 23-26
   * Advancing with Rails, Edison, NJ, November 6-9
Both taught by David A. Black.
See http://www.rubypal.com for more info!

Pat Maddox wrote:

This seems to me along the same lines as

a = 1
if true
  a = 10
end
p a # => 10

Which certainly is not surprising or unwelcome.

when compared to the following it is surprising:

a = 1
p a

def foo(a)
  p a
end

for i in 1..10
  foo(i)
end

p a

···

------------------

E:\>ruby test_iterator2.rb
1
1
2
3
4
5
6
7
8
9
10
1

--
Posted via http://www.ruby-forum.com/\.

Rick Denatale wrote:

This is changing in 1.9

http://eigenclass.org/hiki/Changes+in+Ruby+1.9#l8

I don't know what software install Ruby 1.9 on my computer

  C:\Users\Mike\ruby-1.9.0-20060415-i386-mswin32

and then if I run ruby 1.9, it gives me the same result:

C:\Users\Mike\ruby-1.9.0-20060415-i386-mswin32\bin>ruby test_iterator.rb
1
1
2
3
4
5
6
7
8
9
10
10
"=========="
"1.9.0"

···

---------------------------
Code

a = 1
p a

1.upto(10) {|a| p a}

p a

p "=" * 10

p RUBY_VERSION

--
Posted via http://www.ruby-forum.com/\.

No it's not. no matter what 'spheric scope' means.

Blocks are closures, they are NOT functions/methods.

In the example the variable 'data' in the block is the same variable
as 'data' in data = 'hello'

In that sense this is no different than

if false; data = 'hello';end
data = 'goodbye'

The variable definition is lexical, so it doesn't matter that the
data='hello' statement didn't get executed, it's the fact that the
parser saw it which caused it to be defined.

And note that if you JUST had

1.times {a = "goodbye"}

with no prior definition of a in the scope, you'd get a NameError when
you ran it because a is undefined, and Ruby 1.8 doesn't allow new
locals to be defined within a block.

Ruby 1.9 has a feature marked EXPERIMENTAL which allows block locals
to be defined by listing them in the |'s preceded by a ; after any
block arguments. This might or might not survive.

···

On 10/15/07, 7stud -- <bbxx789_05ss@yahoo.com> wrote:

SpringFlowers AutumnMoon wrote:
>
> I thought a iterator with a block is like an nameless function call...
>

Here's another example(a modification of the example found in pickaxe2,
p 106):

if false
  data = "hello"
end

(1..3).each {data = "goodbye"}

puts data

--output:--
goodbye

That is equivalent to Java's call by value--but using references and C++
reference semantics, and the flat scope is converted to spheric scope
with assignment semantics applying throughout any call by value passing.

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

SpringFlowers AutumnMoon wrote:

I don't know what software install Ruby 1.9 on my computer

  C:\Users\Mike\ruby-1.9.0-20060415-i386-mswin32

This is a very old version of Ruby 1.9. Please don't forget that Ruby
1.9(.0) is still an experimental version, that will move towards the
final Ruby 1.9.1 in December 2007 (I hope "December 2007" is the correct
date).

There are newer precompiled versions
(ruby-1.9.0-20070709-x64-mswin64_80.zip on
http://dl.ambiweb.de/mirrors/ftp.ruby-lang.org/binaries/mswin32/\) or
snapshots which can be compiled (snapshot.tar.gz on
ftp://ftp.ruby-lang.org/pub/ruby/).

Wolfgang Nádasi-Donner

···

--
Posted via http://www.ruby-forum.com/\.

Well, that's kind of the point of blocks, isn't it? They close over
any vars that are currently in scope. Methods on the other hand have
their own scope. I guess it could be confusing if you thought methods
and blocks were the same thing...but, um, they're not.

Pat

···

On 10/14/07, SpringFlowers AutumnMoon <summercoolness@gmail.com> wrote:

Pat Maddox wrote:
> This seems to me along the same lines as
>
> a = 1
> if true
> a = 10
> end
> p a # => 10
>
> Which certainly is not surprising or unwelcome.

when compared to the following it is surprising:

a = 1
p a

def foo(a)
  p a
end

for i in 1..10
  foo(i)
end

p a

------------------

E:\>ruby test_iterator2.rb
1
1
2
3
4
5
6
7
8
9
10
1

Hi --

···

On Mon, 15 Oct 2007, SpringFlowers AutumnMoon wrote:

Pat Maddox wrote:

This seems to me along the same lines as

a = 1
if true
  a = 10
end
p a # => 10

Which certainly is not surprising or unwelcome.

when compared to the following it is surprising:

a = 1
p a

def foo(a)
p a
end

for i in 1..10
foo(i)
end

p a

------------------

E:\>ruby test_iterator2.rb
1
2
3
4
5
6
7
8
9
10
1

There's no relation or connection between the two. The def keyword
always starts a new local scope; the if keyword doesn't. There's no
reason to expect them to behave the same way as each other, as they
serve entirely different purposes.

David

--
Upcoming training from Ruby Power and Light, LLC:
   * Intro to Ruby on Rails, Edison, NJ, October 23-26
   * Advancing with Rails, Edison, NJ, November 6-9
Both taught by David A. Black.
See http://www.rubypal.com for more info!

SpringFlowers AutumnMoon wrote:

Pat Maddox wrote:

This seems to me along the same lines as

a = 1
if true
  a = 10
end
p a # => 10

Which certainly is not surprising or unwelcome.

when compared to the following it is surprising:

a = 1
p a

def foo(a)
  p a
end

for i in 1..10
  foo(i)
end

p a

------------------

E:\>ruby test_iterator2.rb
1
1
2
3
4
5
6
7
8
9
10
1

Yes, the def syntax specifically doesn't take the caller binding, AFAIK.
If you intend having methods access variables local to where they are
defined, just use define_method, which takes a block, with all of its
peculiarities, like taking the caller binding along with its local
variables.

mortee

David A. Black wrote:

Hi --

foo(i)
3
4
5
6
7
8
9
10
1

There's no relation or connection between the two. The def keyword
always starts a new local scope; the if keyword doesn't. There's no
reason to expect them to behave the same way as each other, as they
serve entirely different purposes.

So in a way, think of a code block like a "if" statement? (no new local
scope)

Come to think about it, since

[1,2,3,4,5].each {|a| p a}

is equivalent to

for a in [1,2,3,4,5]
  p a
end

so the "for" version clearly doesn't have a new scope for "a".

But in the newest Ruby 1.9, they are not equivalent any more?

···

On Mon, 15 Oct 2007, SpringFlowers AutumnMoon wrote:

--
Posted via http://www.ruby-forum.com/\.

SpringFlowers AutumnMoon wrote:

So in a way, think of a code block like a "if" statement? (no new local
scope)

Come to think about it, since

[1,2,3,4,5].each {|a| p a}

is equivalent to

for a in [1,2,3,4,5]
  p a
end

so the "for" version clearly doesn't have a new scope for "a".

But in the newest Ruby 1.9, they are not equivalent any more?

No, they aren't the same even in Ruby 1.8.x either. With the do...end or
{...} syntax, any variables assigned in the block, but inexisting at the
point of the definition of the block, are actually local to the block.

AFAIK, in 1.9, the formal parameters of the block, specified between

's, are considered unconditionally block-local *too*. In 1.8.x, those

are treated like any other local variables in the block: they refer to
the same as the enclosing block if pre-existing, and refer to
block-local variables otherwise.

mortee

Hi --

David A. Black wrote:

Hi --

foo(i)
3
4
5
6
7
8
9
10
1

There's no relation or connection between the two. The def keyword
always starts a new local scope; the if keyword doesn't. There's no
reason to expect them to behave the same way as each other, as they
serve entirely different purposes.

So in a way, think of a code block like a "if" statement? (no new local
scope)

I think the best thing is to learn about blocks as blocks, and don't
worry too much about how much they are or aren't similar to other
things. A block has the variables from the local scope in which it was
created, and can also create its own variables, but the ones it
creates exist only inside the block. An if statement is truly flat
with regard to its local scope.

David

···

On Mon, 15 Oct 2007, SpringFlowers AutumnMoon wrote:

On Mon, 15 Oct 2007, SpringFlowers AutumnMoon wrote:

--
Upcoming training from Ruby Power and Light, LLC:
   * Intro to Ruby on Rails, Edison, NJ, October 23-26
   * Advancing with Rails, Edison, NJ, November 6-9
Both taught by David A. Black.
See http://www.rubypal.com for more info!