Specifying local and external block parameters (that old chestnut)

:= assigns to local block scope,

:= assign to a variable which is always local to the block, even if a
variable with the same name exist in an outer block. For example

b = 12
1.times { b := 2 }

b := 2' will create a new block variable which shadow the previous variable b’

matz said previously that in
(0…10).each { |x| … }
the values would be assigned to x with ‘:=’, that is,
x = …
inside the block would use the local. Put otherwise, this is the same as
the “make them all local” solution w.r.t. block parameters!

= assigns to outside the local block scope.

= has the same meaning than actually, if a previous variable exist ruby
use this variable otherwise it create a variable local to the block

Isn’t this much stranger than what we have now?

i = 0
x = ‘some value’
(0…10).each do |i|
x := ‘surprise!’ if i == 2
x = i # uses local after the := is run
end

x => 1

Having ‘x = …’ meaning completely different things depending on the
“execution context” makes me feel unsecure.

···

On Mon, Oct 07, 2002 at 12:01:41AM +0900, ts wrote:

What happens with nested scopes.

same


Mauricio Julio Fernandez Pradier

Hello Yukihiro,

Monday, October 07, 2002, 9:16:08 AM, you wrote:

Hi,

i personally think that this usage will be very strange nad
untraditional. for me, it is better to use ‘=’ for constant assignment
and ‘:=’ for variable assignment, as done in algol-68 and in some
modern FP languages

Could you describe “constant assignment” and “variable assignment” in
algol-68 bit more in depth?

int a=1; – declaring a with type ‘int’ and value 1
int b:=2; – declaring b with type ‘pointer to int’ and value of
pointing to cell of type int, whose INITIAL VALUE will be 2

b:=3; – correct. b will point to the same cell which value is
however changed

well, a whole algol-68 is STRONG language (in two or more senses :wink:

common idea is that after ‘=’ we can’t change value, but after ‘:=’ we
can. btw, even subroutines declared in algol-68 with ‘=’ to closures

···

In message “Re: Specifying local and external block parameters (that old chestnut)” > on 02/10/07, “Bulat Ziganshin” bulatz@integ.ru writes:
a:=4; – INCORRECT. we can’t change value of a


Best regards,
Bulat mailto:bulatz@integ.ru

b = 12
1.times { b := 2 }

`b := 2' will create a new block variable which shadow the previous
variable `b'

matz said previously that in
  (0...10).each { |x| ... }
the values would be assigned to x with ':=', that is,
  x = ...
inside the block would use the local. Put otherwise, this is the same as
the "make them all local" solution w.r.t. block parameters!

I know this, but you don't have || in my example.

i = 0
x = 'some value'
(0...10).each do |i|
x := 'surprise!' if i == 2
x = i # uses local after the := is run
end

x => 1

I don't see where is the problem

pigeon% cat b.rb
#!./ruby
i = 0
x = 'some value'
(0...10).each do |i|
   x := 'surprise!' if i == 2
   x = i # uses local after the := is run
   p x
end
p x
pigeon%

pigeon% b.rb
./b.rb:4: warning: shadowing variable `i'
./b.rb:5: warning: shadowing variable `x'
0
1
2
3
4
5
6
7
8
9
"some value"
pigeon%

Having 'x = ...' meaning completely different things depending on the
"execution context" makes me feel unsecure.

Don't forget that I know "my" and its undocumented "features" :slight_smile: and I
can avoid them :-)))

To understand what it do (tLOCAL_ASGN is `:=')

[...]
    > lhs tLOCAL_ASGN command_call
        {
      node_local($1);
      $$ = node_assign($1, $3);
        }

[...]

static void
block_local(node)
    NODE *node;
{
    if (nd_type(node) == NODE_LASGN || nd_type(node) == NODE_DASGN) {
  rb_warn("shadowing variable `%s'", rb_id2name(node->nd_vid));
  rb_dvar_push(node->nd_vid, Qnil);
  nd_set_type(node, NODE_DASGN_CURR);
  node->nd_aid = 0;
    }
}

static void
node_local(node)
    NODE *node;
{
    if (!node) return;

    if (dyna_in_block()) {
  if (nd_type(node) == NODE_MASGN) {
      NODE *list = node->nd_head;
      while (list) {
    node_local(list->nd_head);
    list = list->nd_next;
      }
      if (node->nd_args && node->nd_args != (NODE *)-1) {
    block_local(node->nd_args);
      }
  }
  else {
      block_local(node);
  }
    }
    else {
  rb_warn("useless use of `:='");
    }
}

* at compile time, the lhs is modified (and a block local variable is
  created) *after* ruby has parsed the rhs

* at runtime, ruby first execute the rhs and then make the assignement
   (i.e. create a new block local variable)

This give something similar to a let*

pigeon% cat b.rb
#!./ruby
2.times do |i|
   b = i
   3.times do |i|
      b := b + i
      p "in #{b}"
   end
   p "out #{b}"
end

pigeon%

pigeon% b.rb
./b.rb:4: warning: shadowing variable `i'
./b.rb:5: warning: shadowing variable `b'
"in 0"
"in 1"
"in 2"
"out 0"
"in 1"
"in 2"
"in 3"
"out 1"
pigeon%

Guy Decoux

Hi,

i = 0
x = ‘some value’
(0…10).each do |i|
x := ‘surprise!’ if i == 2
x = i # uses local after the := is run
end

x => 1

Having ‘x = …’ meaning completely different things depending on the
“execution context” makes me feel unsecure.

They are not “completely different”. Think about the following C
code:

int foo() {
int a
a = 42;
printf(“a=%d\n”, a);
{
int a;
a = 55
printf(“a=%d\n”, a);
}
printf(“a=%d again\n”, a);
}

This is somewhat confusing but completely valid code in C. Besides,
in (future) Ruby, you will be warned for a bad style.

						matz.
···

In message “Re: Specifying local and external block parameters (that old chestnut)” on 02/10/08, Mauricio Fernández batsman.geo@yahoo.com writes:

Hi,

i = 0
x = ‘some value’
(0…10).each do |i|
x := ‘surprise!’ if i == 2
x = i # uses local after the := is run
end

x => 1

Having ‘x = …’ meaning completely different things depending on the
“execution context” makes me feel unsecure.

They are not “completely different”. Think about the following C
code:

int foo() {
int a
a = 42;
printf(“a=%d\n”, a);
{
int a;
a = 55
printf(“a=%d\n”, a);
}
printf(“a=%d again\n”, a);
}

My concern is about the code meaning different things in each iteration;
I’d expect the code in a for loop to always behave the same.

···

On Tue, Oct 08, 2002 at 06:38:53PM +0900, Yukihiro Matsumoto wrote:

In message “Re: Specifying local and external block parameters (that old chestnut)” > on 02/10/08, Mauricio Fernández batsman.geo@yahoo.com writes:

This is somewhat confusing but completely valid code in C. Besides,
in (future) Ruby, you will be warned for a bad style.

  					matz.


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

[…] or some clown changed the chips on a board and not its name.
(Don’t laugh! Look at the SMC etherpower for that.)
– from /usr/src/linux/MAINTAINERS

b = 12
1.times { b := 2 }

b := 2' will create a new block variable which shadow the previous variable b’

matz said previously that in
(0…10).each { |x| … }
the values would be assigned to x with ‘:=’, that is,
x = …
inside the block would use the local. Put otherwise, this is the same as
the “make them all local” solution w.r.t. block parameters!

I know this, but you don’t have || in my example.

i = 0
x = ‘some value’
(0…10).each do |i|
x := ‘surprise!’ if i == 2
x = i # uses local after the := is run
end

x => 1

I don’t see where is the problem

pigeon% cat b.rb
#!./ruby
i = 0
x = ‘some value’
(0…10).each do |i|
x := ‘surprise!’ if i == 2
x = i # uses local after the := is run
p x
end
p x
pigeon%

pigeon% b.rb
./b.rb:4: warning: shadowing variable i' ./b.rb:5: warning: shadowing variable x’
0
1
2
3
4
5
6
7
8
9
“some value”
pigeon%

Now I get it… it depends on whether Ruby sees ‘:=’ in the parsing
phase. I thought Ruby would begin to consider variables local after
executing the ‘:=’ statement. So I thought we’d get

i = 0
x = ‘some value’
(0…10).each do |i|
x := ‘surprise!’ if i == 2
x = i # uses local after the := is run
p x
end
p x

pigeon% b.rb
./b.rb:4: warning: shadowing variable i' ./b.rb:5: warning: shadowing variable x’
0
1
2
3
4
5
6
7
8
9
1

because after i == 2 only the local ‘x’ would be assigned to, not the
outer one. Of course this would be absolutely insane, but going the
syntactic way seems so much better :slight_smile:

···

On Tue, Oct 08, 2002 at 06:31:03PM +0900, ts wrote:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

We come to bury DOS, not to praise it.
– Paul Vojta, vojta@math.berkeley.edu

At first sight, this looks great!

···

On Tue, Oct 08, 2002 at 06:31:03PM +0900, ts wrote:

  • at compile time, the lhs is modified (and a block local variable is
    created) after ruby has parsed the rhs

  • at runtime, ruby first execute the rhs and then make the assignement
    (i.e. create a new block local variable)

This give something similar to a let*

pigeon% cat b.rb
#!./ruby
2.times do |i|
b = i
3.times do |i|
b := b + i
p “in #{b}”
end
p “out #{b}”
end

pigeon%

pigeon% b.rb
./b.rb:4: warning: shadowing variable i' ./b.rb:5: warning: shadowing variable b’
“in 0”
“in 1”
“in 2”
“out 0”
“in 1”
“in 2”
“in 3”
“out 1”
pigeon%


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Q: What’s the big deal about rm, I have been deleting stuff for years? And
never lost anything… oops!
A: …
– From the Frequently Unasked Questions

My concern is about the code meaning different things in _each iteration_;
I'd expect the code in a for loop to always behave the same.

See [ruby-talk:52719]

Guy Decoux

Hi,

···

In message “Re: Specifying local and external block parameters (that old chestnut)” on 02/10/08, Mauricio Fernández batsman.geo@yahoo.com writes:

My concern is about the code meaning different things in each iteration;
I’d expect the code in a for loop to always behave the same.

No need to concern. It is determined compile-time.

						matz.