Lexical scope and closures

nobu.nokada@softhome.net schrieb im Newsbeitrag
news:200302141518.h1EFI0804442@sharui.nakada.kanuma.tochigi.jp…

Hi,

I’d choose something between

arr.each {|i|
local{|a,b|
c = …

}
}
(snip)
in either case, a, b are local, c is method-wise variable.

I vote for the second variant, possibly replacing ‘let’ with
‘local’. The
drawback of the first variant is IMHO that it is too easily
recognized as
an ordinary block.

Because it is an ordinary block.

? Why would you then need a ‘local’ keyword at all?

def local; yield; end

Err, sorry, I don’t get what you mean. Could you please write another
explaining sentence? Thanks a lot!

Regards

robert
···

At Fri, 14 Feb 2003 22:32:11 +0900, > Robert Klemme wrote:

Hi –

···

On Sat, 15 Feb 2003, Tom Sawyer wrote:

On Friday 14 February 2003 08:18 am, nobu.nokada@softhome.net wrote:

? Why would you then need a ‘local’ keyword at all?

def local; yield; end

all it does local a and b. ugly, if you ask me.

Isn’t that the goal though?

David


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Still dreaming of your super-closures? :slight_smile:
The other notation was more elegant…

FWIW, I find local at the same time

  1. ugly, cause it involves another indentation level and lots of key-presses
  2. beautiful, cause it’s defined in the language itself and not by modifying
    the parser

At the end of the day, (1) is the most important since I won’t be admiring
(2) when I have to type it for the 1000th time.

···

On Sat, Feb 15, 2003 at 04:41:52AM +0900, Tom Sawyer wrote:

On Friday 14 February 2003 08:18 am, nobu.nokada@softhome.net wrote:

? Why would you then need a ‘local’ keyword at all?

def local; yield; end

all it does local a and b. ugly, if you ask me.

hey, i thought of another ugly possibility yesterday! :slight_smile:

arr.each { |i|
c = “is local”
@c = “is c in outer scope”
@@c = “is @c in outerscope”
@@@c = “is @@c in outerscope”
}

yep, and then you can layers and layers of blocks and eventually end up with:

@@@@@@@@@@@@@@@c = “foo bar”

fun fun :wink:


_ _

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

I’ve no idea when Linus is going to release 2.0.24, but if he takes
too long Im going to release a 2.0.24unoff and he can sound off all
he likes.
– Alan Cox

self.c = 1

would conflict with:

def c
 1
end

With a warning?

well, a warning might be good. the later definition would override the former
in such a case. at least that’s my initial thought on such an occurance. the
interesting thing though is that the distinction between the two cases above
becomes blured and could actually be represented in exactly the same manner
within the interpreter.

so
puts c
is
puts self.c # instance variable, not method

correct

Anyway, accessors are broken inside the class’ instance methods (and
sometimes we want them, when they do non-trivial things).

yes, this aspect would change the language a good bit, as instance variables
would not require accessors, and rather there visibility would be controlled
by public, private, and protected. just like methods. defining not simple
accessors would require name differentiation:

def complex_c
	c ** -1
    end

Ummm, now I realize that your idea corresponds exactly to defining
automagically accessors for each i.v. .

you got me :slight_smile: indeed it is quite close. in fact, i am really headed in a
direction where the distinction between methods and variables becomes mute.

Plus I think locals are more used than i.v. so it makes more sense to
prefix the latter…

the above is the reason why instance varaibles would loose the prefix.

I see, but this doesn’t change the fact that I’d have to prefix locals,
which are far more common.

that’s true. well, nothing’s perfect :wink:

···

On Saturday 15 February 2003 02:21 am, Mauricio Fernández wrote:


tom sawyer, aka transami
transami@transami.net

Hi –

···

On Sun, 16 Feb 2003, ts wrote:

def meth
a = 1
[1,2,3].each {|x| # explicitly import existing a into block}
end

I don’t understand sorry, with this example

a = 1
1.times do |x|
a = 2 # shadowing ???
end
a # ===> 1

a = 1
1.times do |x|
# explicitly import existing a into block
a = 2
end
a # ===> 2

this ?

Yes, but now that I see the word “shadowing” I realize it won’t happen
:slight_smile: I’m just trying to find something to suggest instead of “local” or
“let”, without much success.

David


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Hi,

I think the most common case will be … code that looks exactly like it
does today. I think the need for local will be rare, the thread
examples being the one instance that I know of where local is definitely
needed.

Thank you for expressing my thought. I wish I could describe my ideas
as good as you did. Well, that’s life.

Matz will do what he thinks best. And his track record is proven. I
have no fears about the changes he finally decides upon.

Don’t trust me too much. I failed once in this area. But at least I
will take plenty of time before making final decision.

						matz.
···

In message “Re: Lexical scope and closures” on 03/02/17, Jim Weirich jweirich@one.net writes:

That mechanism can be implemented in Ruby itself, ie. it doesn’t need
the parser to be modified. Almost all the other possibilities involve
new keywords or syntax.

def local; yield; end

local do |islocal,istoo|
islocal = true
istoo = bla
end

both islocal and istoo undefined here.

···

On Mon, Feb 17, 2003 at 06:04:30PM +0900, Robert Klemme wrote:

I vote for the second variant, possibly replacing ‘let’ with
‘local’. The
drawback of the first variant is IMHO that it is too easily
recognized as
an ordinary block.

Because it is an ordinary block.

? Why would you then need a ‘local’ keyword at all?

def local; yield; end

Err, sorry, I don’t get what you mean. Could you please write another
explaining sentence? Thanks a lot!


_ _

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

need help: my first packet to my provider gets lost :frowning:
sel: dont send the first one, start with #2

  • netgod is kidding

Yes, but now that I see the word "shadowing" I realize it won't happen
:slight_smile: I'm just trying to find something to suggest instead of "local" or
"let", without much success.

use "export" rather than "import", i.e.

   1.times do |x|
      a = 2
   end
   a # undefined local variable `a'

   1.times do |x|
      # explicitly export a
      a = 2
   end
   a # ===> 2

but you don't solve the problem : all persons seems to see |x| as a
declaration when it's just an assignement.

Guy Decoux

I see. Thanks!

robert

“Mauricio Fernández” batsman.geo@yahoo.com schrieb im Newsbeitrag
news:20030217094102.GA13990@student.ei.uni-stuttgart.de

···

On Mon, Feb 17, 2003 at 06:04:30PM +0900, Robert Klemme wrote:

I vote for the second variant, possibly replacing ‘let’ with
‘local’. The
drawback of the first variant is IMHO that it is too easily
recognized as
an ordinary block.

Because it is an ordinary block.

? Why would you then need a ‘local’ keyword at all?

def local; yield; end

Err, sorry, I don’t get what you mean. Could you please write another
explaining sentence? Thanks a lot!

That mechanism can be implemented in Ruby itself, ie. it doesn’t need
the parser to be modified. Almost all the other possibilities involve
new keywords or syntax.

def local; yield; end

local do |islocal,istoo|
islocal = true
istoo = bla
end

both islocal and istoo undefined here.


_ _

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

need help: my first packet to my provider gets lost :frowning:
sel: dont send the first one, start with #2

  • netgod is kidding

Personally I am genuinely confused. I like the scoping rules as they
are, and I have never had any problem with them (including in
multi-threaded code). I’ve always known that the |x| notation was an
assignment (although I’d missed the trick about using it with an
assignment type method call - Cool :slight_smile:

Could somebody please explain why anyone would write code like

a=1
[1…3].each {|a| #do something }

and then be surprised about side effects. It just seems like asking
for trouble to me.

Honestly, I’m not trolling or trying to dis anyone. I just don’t
understand!

best regards,
treefrog.

That's not entirely the problem. It's also when your '#do something'
includes an assignment to 'b'. The behaviour then depends on whether 'b' was
assigned to outside the block or not. This is a bit of a battle for
newcomers, to discover that what is the simplest concept in most other
languages (variables) is actually one of the most complicated in Ruby.

I generated quite a lot of noise on this list while trying to understand
which, for which I apologise!

There is a Wiki on this topic now at

and please feel free to contribute ideas there. There have been postings in
the past arguing to keep things unchanged, and those opinions aren't really
represented there yet.

Regards,

Brian.

···

On Mon, Feb 17, 2003 at 08:24:48PM +0900, Steve Hill wrote:

Could somebody please explain why anyone would write code like

a=1
[1..3].each {|a| #do something }

and then be surprised about side effects. It just seems like asking
for trouble to me.

Honestly, I'm not trolling or trying to dis anyone. I just *don't*
understand!

Brian Candler B.Candler@pobox.com wrote in message

That’s not entirely the problem. It’s also when your ‘#do something’
includes an assignment to ‘b’. The behaviour then depends on whether ‘b’ was
assigned to outside the block or not. This is a bit of a battle for
newcomers, to discover that what is the simplest concept in most other
languages (variables) is actually one of the most complicated in Ruby.

I understand the problem now - its just that I have never found it to
be a problem. When I first encountered Ruby a few years back, the
thing that I had most trouble with was the assignment by reference. A
couple of bad experiences in the early days persuaded me to be very
careful about when I duplicated objects. And ensuring the
block-locality of variables was one of those places. Personally, I
tend to use a Struct to hold all the variables that I want to be block
local (unless a Class is really needed).

So what is the problem with something along the lines of

Block_local=Struct.new(“Block_local”, :a, :b)

a=1
b=2

[1,2,3].each do |x|
local=Block_local.new(a,b)
local.a*=x
local.b+=x
p local
end

p a,b

./local.rb
#<Struct::Block_local a=1, b=3>
#<Struct::Block_local a=2, b=4>
#<Struct::Block_local a=3, b=5>
1
2

Or am I still missing the point somewhere?

Best regards,
Steve

You've only displaced the problem: 'local' now must be a block-local
variable, instead of 'a' and 'b'

If you declared 'local' in an outer scope, then under the current rules this
'local' will be bound to it, and things will break even worse than normal
:slight_smile:

Regards,

Brian.

···

On Tue, Feb 18, 2003 at 07:27:53PM +0900, Steve Hill wrote:

Block_local=Struct.new("Block_local", :a, :b)

a=1
b=2

[1,2,3].each do |x|
  local=Block_local.new(a,b)
  local.a*=x
  local.b+=x
  p local
end