1

I am a beginner at Ruby and have been having some trouble figuring out why I can't modify an initialized variable placed outside a block. For example, I want to do the following (but without a for loop because I heard using it in Ruby can cause some nasty bugs):

sentence = "short longest"

def longest_word(sentence)
  max_length = 0
  for word in sentence.split(" ")
    if word.length > max_length
      max_length = word.length
      max_word = word
    end
  end
  return max_word
end

What I tried:

def longest_word(sentence)
    max_length = 0
    sentence.split(" ").each do |word|
        if word.length > max_length
            max_length = word.length
            max_word = word
        end
    end
    return max_word
end

I understand that you can use something like this:

def longest_word(sentence)

     return sentence.split(" ").each.map {|word| [word.length, word]}.max[1]
end

as well but just wanted to figure out why I can't do the .each method in the same way I can do the for loop method. Any help would be appreciated!

1
  • "I can't modify an initialized variable placed outside a block" - Huh? You can and you successfully do. With the max_length variable, that is. You just forgot to initialize max_word outside as well. Commented Jan 24, 2018 at 12:49

1 Answer 1

5

First of all, note that the easiest way to do this would be:

sentence.split(" ").max_by(&:length)

Your method, which can be slightly simplified to:

sentence.split(" ").map {|word| [word.length, word]}.max[1]

also works, but in a more confusing way.

Array comparison works in an “element-wise” manner. So for example, [2, "foo"] > [1, "bar"] because 2 > 1. This is why max works in this scenario: Because you're actually, indirectly, comparing the first element of each array.

Why can't I do the .each method in the same way I can do the for loop method?

Because a variable defined within a block is only accessible within that block.

This is a very common programming principle across virtually all languages, known as the scope of the variable.

def longest_word(sentence)
  max_length = 0
  sentence.split(" ").each do |word|
    if word.length > max_length
      max_length = word.length
      max_word = word  # <--- The variable is defined IN A BLOCK (scope) here
    end
  end
  return max_word      # <--- So the variable does not exist out here
end

A simple workaround (but as I mentioned above, this is not the actual solution I'd recommend!) is to initialise the variable outside the block:

def longest_word(sentence)
  max_length = 0
  max_word = nil   # <--- The variable is defined OUTSIDE THE BLOCK (scope) here
  sentence.split(" ").each do |word|
    if word.length > max_length
      max_length = word.length
      max_word = word
    end
  end
  return max_word  # <--- So the variable exists here
end
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.