2

I'm trying to understand how to use a conditional expression in a Ruby case/when statement. This code seems like it should work, but it only prints 1 through 100 inclusive, and never prints "Fizz", "Buzz" or "FizzBuzz".

#!/usr/bin/env ruby

(1..100).each do |n|
  case n
  when n % 3 == 0 && n % 5 == 0
    puts "FizzBuzz"
  when n % 3 == 0
    puts "Fizz"
  when n % 5 == 0
    puts "Buzz"
  else
    puts n
  end
end

I'm fairly sure I'm missing something obvious and stupid, but the documentation seems to indicate that this should work. Its very similar example was:

a = 2

case
when a == 1, a == 2
  puts "a is one or two"
when a == 3
  puts "a is three"
else
  puts "I don't know what a is"
end

My Ruby version is:

ruby 2.1.6p336 (2015-04-13 revision 50298) [x86_64-linux]

And for completeness, the output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
Community
  • 1
  • 1
Michael Hampton
  • 9,737
  • 4
  • 55
  • 96

2 Answers2

4

If you're going to put arbitrary conditions in the when, then you need to leave the expression off the case:

(1..100).each do |n|
  case
  when n % 3 == 0 && n % 5 == 0
    puts "FizzBuzz"
  when n % 3 == 0
    puts "Fizz"
  when n % 5 == 0
    puts "Buzz"
  else
    puts n
  end
end

When you do case n ... whenboolean, that will only trigger when n itself is equal to the boolean result - that is, true or false, not a number. When you do case...when without the n, that's what will cause a true when to be triggered.

Mark Reed
  • 91,912
  • 16
  • 138
  • 175
  • 1
    Yep, this was it. I did manage to figure it out, but by that point people had already answered and it was too late to hide my stupidity. – Michael Hampton May 18 '15 at 22:14
  • I think you'll find that you learn a lot faster if you stop being concerned about hiding your "stupidity" - which is really just easily-cured ignorance, anyway. – Mark Reed May 18 '15 at 22:17
  • 3
    Yes, I know. That was meant to be humorous. Obviously I need to work on that, too. – Michael Hampton May 18 '15 at 22:19
2

Your problem is because you have case n, instead of just case. If you take that out, it'll work.

(1..100).each do |n|
  case
  when n % 3 == 0 && n % 5 == 0
    puts "FizzBuzz"
  when n % 3 == 0
    puts "Fizz"
  when n % 5 == 0
    puts "Buzz"
  else
    puts n
  end
end

Putting a variable after case causes it to check against the conditions you put in when. The link you provided actually deals with this specific situation, the line before the code you posted specifically says this:

The other way to use a case expression is like an if-elsif expression

Waynn Lue
  • 11,344
  • 8
  • 51
  • 76