Local variable in a block

ruby -v
<1> ruby 2.7.4p191 (2021-07-07 revision a21a3b7d23)
[x86_64-linux-gnu]

code from Steve Litt website (link now broken)

[code]
#!/usr/bin/ruby
i = -99
puts "Before: " + i.to_s(1..10).each{|i| puts i}
puts "After : " + i.to_s
[/code]

When I run the code, I get:

`to_s': no implicit conversion of Range into Integer (TypeError)

I need figuring out what's wrong with the code. TIA ..

···

--
Duke
** Text only please. Bottom post is best. **

I think the code is supposed to include a line break:

i = -99
puts "Before: " + i.to_s
(1..10).each{|i| puts i}
puts "After : " + i.to_s

It is explaining that the `i` variable at the top level is not
reassigned to the value 10 after the loop even though they are both
named `i`. It stays -99.

ruby -v
<1> ruby 2.7.4p191 (2021-07-07 revision a21a3b7d23)
[x86_64-linux-gnu]

code from Steve Litt website (link now broken)

[code]
#!/usr/bin/ruby
i = -99
puts "Before: " + i.to_s(1..10).each{|i| puts i}
puts "After : " + i.to_s
[/code]

#!/usr/bin/ruby
i = -99
puts "Before: " + i.to_s
(1..10).each{|i| puts i}
puts "After : " + i.to_s

You have two lines joined together improperly.

-Rob

···

On 17 Dec 2021, at 15:59, Duke Normandin <dukeofpurl@gmx.com> wrote:

When I run the code, I get:

`to_s': no implicit conversion of Range into Integer (TypeError)

I need figuring out what's wrong with the code. TIA ..
--
Duke
** Text only please. Bottom post is best. **

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk&gt;

Jeepers! You gotta know that I'm a Ruby noob! LOL
The code was squashed in a table with no padding or margins. It all
seemed to run together. I blew it on the deciphering!

Thanks for your help!

···

On Fri, 17 Dec 2021 16:30:35 -0500 Rob Biedenharn <rob.biedenharn@gmail.com> wrote:

> On 17 Dec 2021, at 15:59, Duke Normandin <dukeofpurl@gmx.com> > > wrote:
>
> ruby -v
> <1> ruby 2.7.4p191 (2021-07-07 revision a21a3b7d23)
> [x86_64-linux-gnu]
>
> code from Steve Litt website (link now broken)
>
> [code]
> #!/usr/bin/ruby
> i = -99
> puts "Before: " + i.to_s(1..10).each{|i| puts i}
> puts "After : " + i.to_s
> [/code]

#!/usr/bin/ruby
i = -99
puts "Before: " + i.to_s
(1..10).each{|i| puts i}
puts "After : " + i.to_s

You have two lines joined together improperly.

--
Duke
** Text only please. Bottom post is best. **

Now that I have the code working thanks to Rob B., I need to grok
the point of:

[quote]
Speaking of performance, if you declare the block argument outside
the block (in other words, make it a local variable), performance
improves because Ruby needn't recreate a variable every iteration.

HOWEVER, the loop messes with the value of the variable, so it's
best to use a specific variable for that purpose, and do not use it
for other purposes within the subroutine.

Here's an example of using a local variable as a block argument:
[/quote]

So - we have i declared outside the { ..block.. }

Then we use it (a global variable I suppose) inside a block.

So what's the point? Don't use globals as in iterator? Should have
used j for example, inside the block?

···

On Fri, 17 Dec 2021 13:59:50 -0700 Duke Normandin <dukeofpurl@gmx.com> wrote:

--
Duke
** Text only please. Bottom post is best. **

Now that I have the code working thanks to Rob B., I need to grok
the point of:

[quote]
Speaking of performance, if you declare the block argument outside
the block (in other words, make it a local variable), performance
improves because Ruby needn't recreate a variable every iteration.

This isn’t likely to be a performance issue. If it *is*, then you probably need to be using a compiled language!

HOWEVER, the loop messes with the value of the variable, so it's
best to use a specific variable for that purpose, and do not use it
for other purposes within the subroutine.

Here's an example of using a local variable as a block argument:
[/quote]

So - we have i declared outside the { ..block.. }

Then we use it (a global variable I suppose) inside a block.

Not a global variable (those are different and *very rare* in Ruby), but a normal "local" variable.

So what's the point? Don't use globals as in iterator? Should have
used j for example, inside the block?

Typically, the reason to do this is not for the block variable, but to have a variable that can be manipulated within the block, but still be accessible after the block.

If you look at your output, you’ll see that the i which is the block argument does not affect the i from outside the block. It "shadows" the i outside the block and is completely separate from it.

Depending on how old this site/code that you’e following is, the rules might have been a bit different. I *know* that the current behavior of block arguments has not always been this way.

-Rob B.

···

On 17 Dec 2021, at 16:50, Duke Normandin <dukeofpurl@gmx.com> wrote:
On Fri, 17 Dec 2021 13:59:50 -0700 > Duke Normandin <dukeofpurl@gmx.com> wrote:

--
Duke
** Text only please. Bottom post is best. **

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk&gt;

{snip]

If you look at your output, you’ll see that the i which is the
block argument does not affect the i from outside the block. It
"shadows" the i outside the block and is completely separate from
it.

Depending on how old this site/code that you’e following is, the
rules might have been a bit different. I *know* that the current
behavior of block arguments has not always been this way.

Got it!

Variables declared in a block are local to a block and
cannot be accessed from outside the block.

Variables _outside_ the block are available to the block so beware
of the variable names used?

···

On Fri, 17 Dec 2021 17:17:11 -0500 Rob Biedenharn <rob.biedenharn@gmail.com> wrote:
--
Duke
** Text only please. Bottom post is best. **

That's right, and further: a block only encloses local variables in
the scope where the block is _defined_, not where it's _called_. That
really comes to light when you're passing around a Proc or Lambda.

~~~ruby
def generator_func
  x = 41 # x is local to this function

  proc do |y| # y is a parameter
    z = x + y # z is local to the block
    {x: x, y: y, z: z}
  end

  # can't access `y` or `z` here
end

def consumer_func
  the_proc = generator_func

  # these variables are all local to this function
  x = 9
  y = 1
  z = ':)'

  # call the block, passing in `x`
  hsh = the_proc
  p hsh # => {x: 41, y: 9, z: 50}

  # local variables aren't modified by the block
  p x # => 9
  p y # => 1
  p z # => ':)'
end

···

On Sat, Dec 18, 2021 at 8:30 AM Duke Normandin <dukeofpurl@gmx.com> wrote:

Got it!

Variables declared in a block are local to a block and
cannot be accessed from outside the block.

Variables _outside_ the block are available to the block so beware
of the variable names used?
--
Duke

~~~

--
  Matthew Kerwin
  https://matthew.kerwin.net.au/

Jeepers! That's a "full meal deal". It'll take me a few stouts to
digest that lot. :smiley:
Thanks a bunch for your trouble!

···

On Sat, 18 Dec 2021 08:47:58 +1000 Matthew Kerwin <matthew@kerwin.net.au> wrote:

On Sat, Dec 18, 2021 at 8:30 AM Duke Normandin > <dukeofpurl@gmx.com> wrote:
>
> Got it!
>
> Variables declared in a block are local to a block and
> cannot be accessed from outside the block.
>
> Variables _outside_ the block are available to the block so
> beware of the variable names used?

That's right, and further: a block only encloses local variables
in the scope where the block is _defined_, not where it's
_called_. That really comes to light when you're passing around a
Proc or Lambda.

~~~ruby
def generator_func
  x = 41 # x is local to this function

  proc do |y| # y is a parameter
    z = x + y # z is local to the block
    {x: x, y: y, z: z}
  end

  # can't access `y` or `z` here
end

def consumer_func
  the_proc = generator_func

  # these variables are all local to this function
  x = 9
  y = 1
  z = ':)'

  # call the block, passing in `x`
  hsh = the_proc
  p hsh # => {x: 41, y: 9, z: 50}

  # local variables aren't modified by the block
  p x # => 9
  p y # => 1
  p z # => ':)'
end
~~~

--
Duke
** Text only please. Bottom post is best. **

Kind of offtopic: It's possible to shadow the outer non-input variable and it's a little known about feature of Ruby :smiley:

Consider this pry session:

[3] pry(main)> i = 7
=> 7
[4] pry(main)> a = proc do |;i| i = 10; p i; end
=> #<Proc:0x0000564971a5b6d8 (pry):4>
[5] pry(main)> a.call(i)
10
=> 10
[6] pry(main)> i
=> 7
[7] pry(main)>

···

On 12/17/21 21:59, Duke Normandin wrote:

  ruby -v
<1> ruby 2.7.4p191 (2021-07-07 revision a21a3b7d23)
[x86_64-linux-gnu]

code from Steve Litt website (link now broken)

[code]
#!/usr/bin/ruby
i = -99
puts "Before: " + i.to_s(1..10).each{|i| puts i}
puts "After : " + i.to_s
[/code]

When I run the code, I get:

`to_s': no implicit conversion of Range into Integer (TypeError)

I need figuring out what's wrong with the code. TIA ..
--
Duke
** Text only please. Bottom post is best. **

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk&gt;

I'll leave that good stuff until I'm past the noob stage, otherwise
I'll start choking and be forced to take a slug of Python and chase
it with a good pull of Guinness stout. LOL

···

On Sat, 18 Dec 2021 00:12:38 +0100 hmdne <hmdne@airmail.cc> wrote:

Kind of offtopic: It's possible to shadow the outer non-input
variable and it's a little known about feature of Ruby :smiley:

Consider this pry session:

[3] pry(main)> i = 7
=> 7
[4] pry(main)> a = proc do |;i| i = 10; p i; end
=> #<Proc:0x0000564971a5b6d8 (pry):4>
[5] pry(main)> a.call(i)
10
=> 10
[6] pry(main)> i
=> 7
[7] pry(main)>

--
Duke
** Text only please. Bottom post is best. **

It's mostly useless I must admit and I would say less than 0.1% of Ruby programmers know about this feature... But I'm leaving it here for the more advanced users :slight_smile:

···

On 12/18/21 00:19, Duke Normandin wrote:

I'll leave that good stuff until I'm past the noob stage, otherwise
I'll start choking and be forced to take a slug of Python and chase
it with a good pull of Guinness stout. LOL

Right on! Who knows! There may be some poor Ruby hacker choking on
a wedge of pizza in some obscure corner of this planet - that
_needs_ that very solution! :slight_smile:

···

On Sat, 18 Dec 2021 00:40:28 +0100 hmdne <hmdne@airmail.cc> wrote:

On 12/18/21 00:19, Duke Normandin wrote:
> I'll leave that good stuff until I'm past the noob stage,
> otherwise I'll start choking and be forced to take a slug of
> Python and chase it with a good pull of Guinness stout. LOL
>
It's mostly useless I must admit and I would say less than 0.1%
of Ruby programmers know about this feature... But I'm leaving it
here for the more advanced users :slight_smile:

--
Duke
** Text only please. Bottom post is best. **