Require bug confirmation: possible 'times' method error

Hi all,

First time posting here. I'm a Ruby newbie, so apologies if this question
sounds dumb.

I've found something I'm unable to explain. It's either a 'bug' or a
confusing feature. See code below (taken from rubylearning.com):

···

---
"# p019mtdarry.rb

# if you give return multiple parameters,
# the method returns them in an array
# The times method of the Integer class iterates block num times,
# passing in values from zero to num-1

def mtdarry
  10.times do |num|
  square = num * num
  return num, square if num > 5
  end
end

# using parallel assignment to collect the return value
num, square = mtdarry

puts num
puts square"
---
The output is meant to be as follows:
---
">ruby p019mtdarry.rb
6
36

Exit code: 0"

---
This is the output for the code above. However, if I change 10.times to
6.times, the 'puts num' output is 6, and the square output is blank.

The reason this is odd is, if the values for num go from 0 to 5, then the
output of puts num should be 5. However, as the output of puts num is 6,
then the puts square output should be 36, but instead it is blank.

I've tested this on both Ruby 1.9.2 and 1.9.3 (p0). My question is, should
I raise this as a bug or have I missed something in my program analysis?

Thanks,
Tom

I think you're seeing expected behavior here.

A Ruby method will return the value of the last expression in the method,
unless there is an earlier return statement.

In the interest of "teaching you to fish", I'll just ask a couple of
leading questions:

What happens if you use 5.times?

What happens if you use 7.times?

Does that help?

Randy

···

On Wed, Feb 8, 2012 at 8:56 AM, Tom Clarke <tarclarke@gmail.com> wrote:

Hi all,

First time posting here. I'm a Ruby newbie, so apologies if this question
sounds dumb.

I've found something I'm unable to explain. It's either a 'bug' or a
confusing feature. See code below (taken from rubylearning.com):
---
"# p019mtdarry.rb

# if you give return multiple parameters,
# the method returns them in an array
# The times method of the Integer class iterates block num times,
# passing in values from zero to num-1

def mtdarry
10.times do |num|
square = num * num
return num, square if num > 5
end
end

# using parallel assignment to collect the return value
num, square = mtdarry

puts num
puts square"
---
The output is meant to be as follows:
---
">ruby p019mtdarry.rb
6
36
>Exit code: 0"
---
This is the output for the code above. However, if I change 10.times to
6.times, the 'puts num' output is 6, and the square output is blank.

The reason this is odd is, if the values for num go from 0 to 5, then the
output of puts num should be 5. However, as the output of puts num is 6,
then the puts square output should be 36, but instead it is blank.

I've tested this on both Ruby 1.9.2 and 1.9.3 (p0). My question is, should
I raise this as a bug or have I missed something in my program analysis?

Thanks,
Tom

--
Randy Coulman
rcoulman@gmail.com
Twitter: @randycoulman

Hi Randy,

Thank you for your reply.

I have already tried 7.times, which fixes the issue, but that is not
relevant to the issue I raised.

Let's remind ourselves of the most pertinent section of the code in
question:
return num, square if num > 5

At the last time when this code is encountered, num is equal to 6 (as is
displayed by the later 'puts num' statement output). The value for square
is to be outputted if num is greater than 5. As 6 is greater than 5 then
the value for square should be returned (which will be 36 when num is 6).

So it doesn't matter whether it's fixed with 7.times, what matters is what
happens when 6.times is used. What I'm trying to establish is whether there
is a bug in the current Ruby implementation, and workarounds to edge cases
like this will not help bugs to be fixed.

So, with this in mind, why does a value for square not get returned when
num = 6?

Thanks in advance for your advice,
Tom

···

On 8 February 2012 17:43, Randy Coulman <rcoulman@gmail.com> wrote:

I think you're seeing expected behavior here.

A Ruby method will return the value of the last expression in the method,
unless there is an earlier return statement.

In the interest of "teaching you to fish", I'll just ask a couple of
leading questions:

What happens if you use 5.times?

What happens if you use 7.times?

Does that help?

Randy

On Wed, Feb 8, 2012 at 8:56 AM, Tom Clarke <tarclarke@gmail.com> wrote:

> Hi all,
>
> First time posting here. I'm a Ruby newbie, so apologies if this question
> sounds dumb.
>
> I've found something I'm unable to explain. It's either a 'bug' or a
> confusing feature. See code below (taken from rubylearning.com):
> ---
> "# p019mtdarry.rb
>
> # if you give return multiple parameters,
> # the method returns them in an array
> # The times method of the Integer class iterates block num times,
> # passing in values from zero to num-1
>
> def mtdarry
> 10.times do |num|
> square = num * num
> return num, square if num > 5
> end
> end
>
>
> # using parallel assignment to collect the return value
> num, square = mtdarry
>
> puts num
> puts square"
> ---
> The output is meant to be as follows:
> ---
> ">ruby p019mtdarry.rb
> 6
> 36
> >Exit code: 0"
> ---
> This is the output for the code above. However, if I change 10.times to
> 6.times, the 'puts num' output is 6, and the square output is blank.
>
> The reason this is odd is, if the values for num go from 0 to 5, then the
> output of puts num should be 5. However, as the output of puts num is 6,
> then the puts square output should be 36, but instead it is blank.
>
> I've tested this on both Ruby 1.9.2 and 1.9.3 (p0). My question is,
should
> I raise this as a bug or have I missed something in my program analysis?
>
> Thanks,
> Tom
>

--
Randy Coulman
rcoulman@gmail.com
Twitter: @randycoulman

You never hit your return statement (num is never > 5), so the method just
returns the last thing it evaluated.

1.9.3-p0 :003 > 6.times {|n| puts n}
0
1
2
3
4
5
=> 6 #returns 6

Your method returns only 6.

Also, give people who help you over the internet the benefit of the doubt.
I don't think anyone was trying to waste your time :slight_smile:

···

On 2/8/12 1:12 PM, "Tom Clarke" <tarclarke@gmail.com> wrote:

Hi Randy,

Thank you for your reply.

I have already tried 7.times, which fixes the issue, but that is not
relevant to the issue I raised.

Let's remind ourselves of the most pertinent section of the code in
question:
return num, square if num > 5

At the last time when this code is encountered, num is equal to 6 (as is
displayed by the later 'puts num' statement output). The value for square
is to be outputted if num is greater than 5. As 6 is greater than 5 then
the value for square should be returned (which will be 36 when num is 6).

So it doesn't matter whether it's fixed with 7.times, what matters is what
happens when 6.times is used. What I'm trying to establish is whether
there
is a bug in the current Ruby implementation, and workarounds to edge cases
like this will not help bugs to be fixed.

So, with this in mind, why does a value for square not get returned when
num = 6?

Thanks in advance for your advice,
Tom

On 8 February 2012 17:43, Randy Coulman <rcoulman@gmail.com> wrote:

I think you're seeing expected behavior here.

A Ruby method will return the value of the last expression in the
method,
unless there is an earlier return statement.

In the interest of "teaching you to fish", I'll just ask a couple of
leading questions:

What happens if you use 5.times?

What happens if you use 7.times?

Does that help?

Randy

On Wed, Feb 8, 2012 at 8:56 AM, Tom Clarke <tarclarke@gmail.com> wrote:

> Hi all,
>
> First time posting here. I'm a Ruby newbie, so apologies if this
question
> sounds dumb.
>
> I've found something I'm unable to explain. It's either a 'bug' or a
> confusing feature. See code below (taken from rubylearning.com):
> ---
> "# p019mtdarry.rb
>
> # if you give return multiple parameters,
> # the method returns them in an array
> # The times method of the Integer class iterates block num times,
> # passing in values from zero to num-1
>
> def mtdarry
> 10.times do |num|
> square = num * num
> return num, square if num > 5
> end
> end
>
>
> # using parallel assignment to collect the return value
> num, square = mtdarry
>
> puts num
> puts square"
> ---
> The output is meant to be as follows:
> ---
> ">ruby p019mtdarry.rb
> 6
> 36
> >Exit code: 0"
> ---
> This is the output for the code above. However, if I change 10.times
to
> 6.times, the 'puts num' output is 6, and the square output is blank.
>
> The reason this is odd is, if the values for num go from 0 to 5, then
the
> output of puts num should be 5. However, as the output of puts num is
6,
> then the puts square output should be 36, but instead it is blank.
>
> I've tested this on both Ruby 1.9.2 and 1.9.3 (p0). My question is,
should
> I raise this as a bug or have I missed something in my program
analysis?
>
> Thanks,
> Tom
>

--
Randy Coulman
rcoulman@gmail.com
Twitter: @randycoulman

Calling num.times{|i| ...} counts from 0 to num-1, *not* from 1 to num.

Therefore, using 6 here will never trigger the condition (since 5 is
not greater than 5), the explicit return will not be used, and the
method will return the value of last expression. This expression is
the #times block, and #times returns the receiver (ie., the number it
was called on) - in this case, 6. Then the multiple assignment will
assign 6 to first variable, and nil to the second one.

-- Matma Rex

Hi,

I realised what Randy was trying to say about 5 minutes after I stepped
away from my computer (I often think best away from it). Apologies for
being short with you Randy, I understand what you were trying to say now.,
thank you for your help

Thank you to Ian and Matma for your explanations also.

Cheers,
Tom

···

2012/2/8 Bartosz Dziewoński <matma.rex@gmail.com>

Calling num.times{|i| ...} counts from 0 to num-1, *not* from 1 to num.

Therefore, using 6 here will never trigger the condition (since 5 is
not greater than 5), the explicit return will not be used, and the
method will return the value of last expression. This expression is
the #times block, and #times returns the receiver (ie., the number it
was called on) - in this case, 6. Then the multiple assignment will
assign 6 to first variable, and nil to the second one.

-- Matma Rex

No problem. I wasn't trying to be cryptic, and maybe I've been helping my
kids with their homework too much lately, but I wanted to give you some
hints that would lead you to discover the answer for yourself. I find I
learn better if I have to figure some things out for myself, as long as I
don't get frustrated by being stuck on something for too long.

Randy

···

On Wed, Feb 8, 2012 at 10:50 AM, Tom Clarke <tarclarke@gmail.com> wrote:

Hi,

I realised what Randy was trying to say about 5 minutes after I stepped
away from my computer (I often think best away from it). Apologies for
being short with you Randy, I understand what you were trying to say now.,
thank you for your help

Thank you to Ian and Matma for your explanations also.

Cheers,
Tom

2012/2/8 Bartosz Dziewoński <matma.rex@gmail.com>

> Calling num.times{|i| ...} counts from 0 to num-1, *not* from 1 to num.
>
> Therefore, using 6 here will never trigger the condition (since 5 is
> not greater than 5), the explicit return will not be used, and the
> method will return the value of last expression. This expression is
> the #times block, and #times returns the receiver (ie., the number it
> was called on) - in this case, 6. Then the multiple assignment will
> assign 6 to first variable, and nil to the second one.
>
> -- Matma Rex
>
>

--
Randy Coulman
rcoulman@gmail.com
Twitter: @randycoulman