6

I'm learning Ruby and practicing by writing a Caesar cipher. Here's my code so far:

print "Enter rotation: "
rotation = gets.chomp
print "Enter string to encrypt: "
string = gets.chomp

def encrypt
    keys = (' '..'z').to_a
    values = (' '..'z').to_a.rotate(rotation)
    hash = Hash[keys.zip(values)]
    chars = string.split('')
    encrypted_chars = chars.collect { |char| hash[char] }
    encryptd_string = encrypted_chars.join
end

puts "Encrypted string: " + encrypt

It's saying that I don't have access to the rotation variable inside of the encrypt method. NameError: undefined local variable or method 'rotation' for main:Object.

From what I understand, rotation is a local variable with outer scope, and should be accessible inside of the encrypt method. Obviously something is wrong with that reasoning, so could someone explain what's wrong?

Adam Zerner
  • 17,797
  • 15
  • 90
  • 156
  • Possible duplicate of [Ruby accessing outer variables in nested function](https://stackoverflow.com/questions/1016408/ruby-accessing-outer-variables-in-nested-function) – ggorlen Jul 28 '18 at 03:34

2 Answers2

5

This is a duplicate of Ruby accessing outer variables in nested function.

You could make it an instance variable on the containing object by calling it @rotation, but why not just pass string and rotation into the encrypt method?

Buck Doyle
  • 6,333
  • 1
  • 22
  • 35
2

The reason for this behaviour is that Local variables exist in a local scope and defining a method creates a new local scope for that method. Local varables are only visible in the current scope.

I was confused by this and found that relating the OP's question to one of nested methods only added confusion. But I've done a bit more research and discovered this succinct question and, in particular, this answer that explains it clearly as well as demonstrating a way to define a method without creating a new scope.

(I'm just adding this answer for the benefit of others because my search for an answer led me to this question.)

Community
  • 1
  • 1
starfry
  • 9,273
  • 7
  • 66
  • 96