Search code examples
rubystringuppercaselowercase

Why does this Ruby code using char.upcase! fail but char = char.upcase works?


I was solving a coding problem to do a funny case for each word, "LiKe ThIs". Here was my one liner solution. I know it's a little hacky, but oh well.

string.split(" ").map{|word| word.split("").map.with_index{|char,i|
  i.even? ? char.upcase! : char.downcase! }.join("")}.join(" ")

This was outputting HLO TEE TS for the input hello there test, making it look like only the even case was firing. But on throwing a print statement in there, I can see that yes, it's going through each index.

In my frustration, I changed it to:

 string.split(" ").map{|word| word.split("").map.with_index{|char,i|
   i.even? ? char = char.upcase : char = char.downcase }.join("")}.join(" ")

which I feel like should be equivalent - changing the char.upcase! to char = char.upcase...And magically, this worked.

What is going on here?


Solution

  • This is due to the definition of upcase! and downcase!. Here's upcase!

    Upcases the contents of str, returning nil if no changes were made. Note: case replacement is effective only in ASCII region.

    Notice that it returns nil if no changes were made. In this case, if the character you are iterating over is already in the correct case, it'll return nil and effectively remove the character from the string as part of your map function.

    In your specific example, you'll notice every other character is being removed because it's already in lower case and downcase! is returning nil.