case/when question

C

cremes.devlist

I was intrigued by the post that _why put up a few days/weeks ago
about using case/when for testing arrays [1]. I thought I'd give it a
try but I can't make it work. What am I doing wrong?

irb(main):001:0> r1 = (0..12).to_a
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
irb(main):002:0> r2 = (20..32).to_a
=> [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]
irb(main):003:0> def foo range
irb(main):004:1> case range
irb(main):005:2> when *r1
irb(main):006:2> puts "#{range} in r1"
irb(main):007:2> when *r2
irb(main):008:2> puts "#{range} in r2"
irb(main):009:2> else
irb(main):010:2* puts "#{range} NOT in any range"
irb(main):011:2> end
irb(main):012:1> end
=> nil
irb(main):013:0> foo 3
NameError: undefined local variable or method `r1' for main:Object
from (irb):5:in `foo'
from (irb):13

This is under OSX:
ruby 1.8.4 (2005-12-24) [powerpc-darwin8.4.0]

[1] http://redhanded.hobix.com/bits/wonderOfTheWhenBeFlat.html
 
J

James Edward Gray II

I was intrigued by the post that _why put up a few days/weeks ago
about using case/when for testing arrays [1]. I thought I'd give it
a try but I can't make it work. What am I doing wrong?

irb(main):001:0> r1 = (0..12).to_a
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
irb(main):002:0> r2 = (20..32).to_a
=> [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]
irb(main):003:0> def foo range
irb(main):004:1> case range
irb(main):005:2> when *r1
irb(main):006:2> puts "#{range} in r1"
irb(main):007:2> when *r2
irb(main):008:2> puts "#{range} in r2"
irb(main):009:2> else
irb(main):010:2* puts "#{range} NOT in any range"
irb(main):011:2> end
irb(main):012:1> end
=> nil
irb(main):013:0> foo 3
NameError: undefined local variable or method `r1' for main:Object
from (irb):5:in `foo'
from (irb):13

Method definitions, unlike blocks, are not closures and do not have
access to local variables from the scope where they are defined.
Move the vars inside the method, or switch them to instance (or
global) vars and it will work.

Hope that helps.

James Edward Gray II
 
C

cremes.devlist

I was intrigued by the post that _why put up a few days/weeks ago
about using case/when for testing arrays [1]. I thought I'd give it
a try but I can't make it work. What am I doing wrong?

irb(main):001:0> r1 = (0..12).to_a
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
irb(main):002:0> r2 = (20..32).to_a
=> [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]
irb(main):003:0> def foo range
irb(main):004:1> case range
irb(main):005:2> when *r1
irb(main):006:2> puts "#{range} in r1"
irb(main):007:2> when *r2
irb(main):008:2> puts "#{range} in r2"
irb(main):009:2> else
irb(main):010:2* puts "#{range} NOT in any range"
irb(main):011:2> end
irb(main):012:1> end
=> nil
irb(main):013:0> foo 3
NameError: undefined local variable or method `r1' for main:Object
from (irb):5:in `foo'
from (irb):13

Responding to my own email...

I figured it out about 5 minutes after sending. This is purely a
scope mistake on my part. Variables r1 and r2 are NOT in scope inside
foo which is exactly what ruby told me.

The fix is to make r1 and r2 into class vars. Change r1 to @r1 and r2
to @r2 in that example and it works just fine.

Nuby making lots of mistakes!
 
D

dblack

Hi --

I was intrigued by the post that _why put up a few days/weeks ago about using
case/when for testing arrays [1]. I thought I'd give it a try but I can't
make it work. What am I doing wrong?

irb(main):001:0> r1 = (0..12).to_a
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
irb(main):002:0> r2 = (20..32).to_a
=> [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]
irb(main):003:0> def foo range
irb(main):004:1> case range
irb(main):005:2> when *r1
irb(main):006:2> puts "#{range} in r1"
irb(main):007:2> when *r2
irb(main):008:2> puts "#{range} in r2"
irb(main):009:2> else
irb(main):010:2* puts "#{range} NOT in any range"
irb(main):011:2> end
irb(main):012:1> end
=> nil
irb(main):013:0> foo 3
NameError: undefined local variable or method `r1' for main:Object
from (irb):5:in `foo'
from (irb):13

You've defined r1 and r2 outside of the scope of the method definition
block. You need:

def foo(range)
r1 = (0..12).to_a
r2 = .... etc

By the way you can also just use the ranges to test inclusion.



David

--
David A. Black ([email protected])
Ruby Power and Light (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! http://www.manning.com/books/black
 
D

dblack

Hi --

I was intrigued by the post that _why put up a few days/weeks ago about
using case/when for testing arrays [1]. I thought I'd give it a try but I
can't make it work. What am I doing wrong?

irb(main):001:0> r1 = (0..12).to_a
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
irb(main):002:0> r2 = (20..32).to_a
=> [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]
irb(main):003:0> def foo range
irb(main):004:1> case range
irb(main):005:2> when *r1
irb(main):006:2> puts "#{range} in r1"
irb(main):007:2> when *r2
irb(main):008:2> puts "#{range} in r2"
irb(main):009:2> else
irb(main):010:2* puts "#{range} NOT in any range"
irb(main):011:2> end
irb(main):012:1> end
=> nil
irb(main):013:0> foo 3
NameError: undefined local variable or method `r1' for main:Object
from (irb):5:in `foo'
from (irb):13

Responding to my own email...

I figured it out about 5 minutes after sending. This is purely a scope
mistake on my part. Variables r1 and r2 are NOT in scope inside foo which is
exactly what ruby told me.

The fix is to make r1 and r2 into class vars. Change r1 to @r1 and r2 to @r2
in that example and it works just fine.

Sort of :) Actually @r1 is an instance variable, not a class
variable. It's true that if you do:

@a = 1
def meth
puts @a
end
meth

you'll get "1", but only if you are writing code at the top level of
the program. If you do this:

class MyClass
@a = 1
def meth
puts @a
end
end

MyClass.new.meth

you won't because, the two @a's are different from each other.

Class variables (@@r1) will cross the method-definition divide, but
they're somewhat cumbersome.... The best thing is to create local
variables in the scope where you need them (the method definition).


David

--
David A. Black ([email protected])
Ruby Power and Light (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! http://www.manning.com/books/black
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top