Variable local to block (was: one liner perl in ruby)

1 view
Skip to first unread message

Robert Citek

unread,
Dec 14, 2009, 5:45:29 PM12/14/09
to stl...@googlegroups.com
On Thu, Dec 10, 2009 at 9:36 AM, Robert Citek <robert...@gmail.com> wrote:
> On Wed, Dec 9, 2009 at 11:39 PM, Ed Howland <ed.ho...@gmail.com> wrote:
>>  I assum you wat to line number a file?
>
> I was more interested in how to initialize a variable from within the
> the loop created by using the -n command-line option.  Numbering lines
> was the simplest example I could think of.

And I thought I understood what ruby was doing. This works, except
that it creates a variable c external to the block:

$ ruby -e 'c=0 ; (1..3).each {|x| c+=1 ; puts c } ; puts c'
1
2
3
3

Although c is now local to the block, the variable c is not incremented:

$ ruby -e '(1..3).each {|x| c=(c||0)+1 ; puts c } ; puts c'
1
1
1
-e:1: undefined local variable or method `c' for main:Object (NameError)

How can one create a variable that is local to a block?

Regards,
- Robert

Amos King

unread,
Dec 14, 2009, 6:21:55 PM12/14/09
to stl...@googlegroups.com
$ ruby -e '(1..3).inject(0) {|c, x| c=(c)+1; puts c; c } ; puts c'



--

You received this message because you are subscribed to the Google Groups "Saint Louis Ruby Users Group" group.
To post to this group, send email to stl...@googlegroups.com.
To unsubscribe from this group, send email to stlruby+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/stlruby?hl=en.





--
Amos King
http://dirtyInformation.com
http://github.com/Adkron
--
Looking for something to do? Visit http://ImThere.com

Robert Citek

unread,
Dec 14, 2009, 6:53:42 PM12/14/09
to stl...@googlegroups.com
On Mon, Dec 14, 2009 at 6:21 PM, Amos King <amos....@gmail.com> wrote:
> $ ruby -e '(1..3).inject(0) {|c, x| c=(c)+1; puts c; c } ; puts c'

That works in this particular case. But doesn't work in others. For
example, changing from this:

count=0
db.execute(sql) do |resultset|
count+=1
...
end

to this, does not work:

db.execute(sql).inject(0) do |resultset, count|
count+=1
...
end

I get this:

./foo.rb:66:in `+': can't convert Fixnum into Array (TypeError)

From reading p105 in the pickaxe book, variable scoping within blocks
seems to be an unresolved issue.

Regards,
- Robert

Christopher M

unread,
Dec 15, 2009, 8:41:44 AM12/15/09
to stl...@googlegroups.com
On Mon, Dec 14, 2009 at 5:53 PM, Robert Citek <robert...@gmail.com> wrote:

From reading p105 in the pickaxe book, variable scoping within blocks
seems to be an unresolved issue.


It's not really unresolved. In the first example, you're creating a closure out of the block and it's capturing the local variables for use in the block. That's why the 'puts c' after the block returns the final value the variable was assigned. In the second example, you're reinitializing 'c' for every iteration in your block because there's nothing to close over so there's no "state" and the variable's scope at that point is local to the block only.

If you want the variable to persist over iterations of your block, you have to use the closure style definition.

Ed Howland

unread,
Dec 15, 2009, 4:40:49 PM12/15/09
to stl...@googlegroups.com
It also varies in 1.9.1:

http://ruby.about.com/od/newinruby191/a/blockvariscope.htm

The code is similr to what Robert wrote.

Ed
> --
>
> You received this message because you are subscribed to the Google Groups
> "Saint Louis Ruby Users Group" group.
> To post to this group, send email to stl...@googlegroups.com.
> To unsubscribe from this group, send email to
> stlruby+u...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/stlruby?hl=en.
>



--
Ed Howland
http://greenprogrammer.wordpress.com
http://twitter.com/ed_howland

Christopher MacGown

unread,
Dec 15, 2009, 7:19:47 PM12/15/09
to stl...@googlegroups.com
That's correct, I'd intended to mention that you have to explicitly
enclose local variables in 1.9 (in some cases) but forgot.

- chris
Reply all
Reply to author
Forward
0 new messages