Question

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?

Was it helpful?

Solution

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?

OTHER TIPS

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.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top