[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Why is my var undefined?

Tim

2/3/2008 12:08:00 AM

I'm new to ruby and I have the following code:

index=0
unsorted_array.each do |value|
if index==0
smallest=value
smallest_index=0
elsif value<smallest
smallest=value
smallest_index=index
end
index=index+1
end

When it gets to index 1, it crashes and says that smallest is
undefined (on the elsif line). Why is that, when it gets defined in
the first pass (index = 0) ?

Thanks for helping a newbie out.

Tim
8 Answers

Ilan Berci

2/3/2008 12:27:00 AM

0

Tim wrote:
> I'm new to ruby and I have the following code:
>
> index=0
> unsorted_array.each do |value|
> if index==0
> smallest=value
> smallest_index=0
> elsif value<smallest
> smallest=value
> smallest_index=index
> end
> index=index+1
> end
>
> When it gets to index 1, it crashes and says that smallest is
> undefined (on the elsif line). Why is that, when it gets defined in
> the first pass (index = 0) ?
>
> Thanks for helping a newbie out.
>
> Tim

It's only defined for the scope that it's in.. which is the "if" block..
Once it leaves that block and your code returns to the
"unsorted_array.each" scope, "smallest" is out of scope and therefore no
longer defined.

Dave Thomas has a free online version of Ruby 1.6 referred as the Pick
Axe book which discusses scope and I think you will find it very useful

hth

ilan

--
Posted via http://www.ruby-....

Todd Benson

2/3/2008 5:05:00 AM

0

On Feb 2, 2008 6:09 PM, Tim <TimWelsh5@gmail.com> wrote:
> I'm new to ruby and I have the following code:
>
> index=0

you could insert "smallest = nil" here

> unsorted_array.each do |value|
> if index==0
> smallest=value
> smallest_index=0
> elsif value<smallest
> smallest=value
> smallest_index=index
> end
> index=index+1
> end
>
> When it gets to index 1, it crashes and says that smallest is
> undefined (on the elsif line). Why is that, when it gets defined in
> the first pass (index = 0) ?

Not sure what you are trying to do, but if your data is not unique...

a = 5,1,4,7,2,1,9,2,1
smallest = a.min
s_indexes = []
a.each_with_index {|v, i| s_indexes << i if v == a.min}

If you don't want to do it that way, then...

a = 5,1,4,7,2,1,9,2,1
smallest, s_indexes = a.first, []
a.inject(a.first) {|m, e| e < m ? e : m}
a.each_with_index {|v, i| s_indexes << i if v == a.min}

Todd

Todd Benson

2/3/2008 5:14:00 AM

0

On Feb 2, 2008 11:05 PM, Todd Benson <caduceass@gmail.com> wrote:
> a.inject(a.first) {|m, e| e < m ? e : m}
> a.each_with_index {|v, i| s_indexes << i if v == a.min}


Sorry, these lines are supposed to be...

smallest = a.inject(a.first) {|m, e| e < m ? e : m}
a.each_with_index {|v, i| s_indexes << i if v <= smallest}

Todd

Isidor Isa

2/3/2008 9:03:00 AM

0

Todd Benson wrote:
> On Feb 2, 2008 11:05 PM, Todd Benson <caduceass@gmail.com> wrote:
>> a.inject(a.first) {|m, e| e < m ? e : m}
>> a.each_with_index {|v, i| s_indexes << i if v == a.min}
>
>
> Sorry, these lines are supposed to be...
>
> smallest = a.inject(a.first) {|m, e| e < m ? e : m}
> a.each_with_index {|v, i| s_indexes << i if v <= smallest}
>
> Todd

In Ruby 1.9, finding indexes of all elements which have minimal value
is easily done using a new iterator chaining feature:



a = 5, 1, 4, 7, 2, 1, 9, 2, 1

min_value = a.min



a.each_with_index.inject([]){|accum, (elem, index)|

elem == min_value ? accum << index : accum

}

Output:

=> [1, 5, 8]


Best regards
Isidor Nikolic
--
Posted via http://www.ruby-....

Eivind Eklund

2/3/2008 10:51:00 AM

0

On Feb 3, 2008 1:09 AM, Tim <TimWelsh5@gmail.com> wrote:
> I'm new to ruby and I have the following code:
>

Add
smallest = nil
smallest_index = 0
here, and your code will work.


> index=0
> unsorted_array.each do |value|
> if index==0
> smallest=value
> smallest_index=0
> elsif value<smallest
> smallest=value
> smallest_index=index
> end
> index=index+1
> end
>
> When it gets to index 1, it crashes and says that smallest is
> undefined (on the elsif line). Why is that, when it gets defined in
> the first pass (index = 0) ?

The variable is not "pass"-based - it is "scope" based, ie, it only
exists inside a particular *lexical* - that is, textual - part of your
program (in this case, your if statement, NOT the loop). In other
words, you get a new variable for each pass through the loop.

By adding the initialization, you get th same variable all loop iterations.

Here is another variant of your code that uses essensially the same
algorithm and simplifies the code a bit:

smallest_index = 0
smallest_value = nil
unsorted_array.each_with_index do |value, index|
if !smallest_value || value<smallest
smallest=value
smallest_index=index
end
end


Eivind.

Sebastian Hungerecker

2/3/2008 11:33:00 AM

0

Ilan Berci wrote:
> It's only defined for the scope that it's in.. which is the "if" block

It's not local to the if-block. It's local to each execution of the each-
block.

HTH,
Sebastian
--
NP: Shape of Despair - Angels of Distress
Jabber: sepp2k@jabber.org
ICQ: 205544826

Eivind Eklund

2/3/2008 12:01:00 PM

0

On Feb 3, 2008 11:50 AM, Eivind Eklund <eeklund@gmail.com> wrote:
> The variable is not "pass"-based - it is "scope" based, ie, it only
> exists inside a particular *lexical* - that is, textual - part of your
> program (in this case, your if statement, NOT the loop).

This was slightly clumsily written; the variable leak through to the
end of the block, but isn't present for the entire loop. Sebastians
description is correct.

Eivind.

Tim

2/3/2008 5:28:00 PM

0

Thanks to all for the help. I take it from the comments here that any
variables which are defined in an iteration block (or a Proc)are local
to each iteration. Thinking about it, that makes sense because each
iteration requires its own call from each (or each_with_index,
etc.)...with the variables being treated somewhat like method
variables.