定义了一个Ruby NameError,未定义的局部变量

时间:2017-01-04 15:07:23

标签: ruby scope

我做了一个简单的哈希提取应用程序,它根据用户输入的第一个字符检索邮政编码区域。但我一直收到这个错误

  

postal_code_lookup.rb:27:in lookup_code': undefined local variable or method postal_codes'for main:Object(NameError)你的意思是?   POSTAL_CODE

我很困惑,因为我已经声明了变量,它应该在我的循环中可用。

postal_codes = {
  V: "British Columbia",
  Y: "Yukon Territory",
  X: "Northwest Territory",
  T: "Alberta",
  S: "Saskatechewan",
  R: "Manitoba",
  P: "Northern Ontario",
  M: "Toronto",
  L: "Central Ontario",
  K: "Eastern Ontario",
  J: "Western & Northern Quebec",
  N: "Western Ontario",
  G: "Eastern Quebec",
  H: "Metroplitan Montreal",
  A: "Newfoundland & Labradour",
  C: "Prince Edward Island",
  E: "New Brunswick",
  B: "Nova Scotia"
}


def lookup_code(postal_code)
  territory = postal_codes.fetch(postal_code[0].upcase.to_sym)
  puts "Your address is in #{territory}"
end

loop do 
  puts "Do you want to lookup a postal code?(Y/n)"
  prompt = gets.chomp.downcase
  if prompt != "y"
    break
  end

print "Enter your postal code > "
postal_code = gets.chomp

lookup_code(postal_code)

end

我不了解这里的范围?

2 个答案:

答案 0 :(得分:3)

方法引入新范围。它们不是闭包:不应该期望来自父作用域的局部变量可以在嵌套作用域中访问。

解决方案1:使用常量

POSTAL_CODES = {
  V: "British Columbia",
  # SKIPPED
  B: "Nova Scotia"
}


def lookup_code(postal_code)
  territory = POSTAL_CODES.fetch(postal_code[0].upcase.to_sym)
  puts "Your address is in #{territory}"
end

解决方案2:使用实例变量

尽管您没有课程,但mainObject的特殊实例,始终定义:

@postal_codes = {
  V: "British Columbia",
  # SKIPPED
  B: "Nova Scotia"
}


def lookup_code(postal_code)
  territory = @postal_codes.fetch(postal_code[0].upcase.to_sym)
  puts "Your address is in #{territory}"
end

解决方案3:使用全局变量

$postal_codes = {
  V: "British Columbia",
  # SKIPPED
  B: "Nova Scotia"
}


def lookup_code(postal_code)
  territory = $postal_codes.fetch(postal_code[0].upcase.to_sym)
  puts "Your address is in #{territory}"
end

解决方案4:滥用OOP

有人可能(bah!)在这里创建一个类并使用它的实例:

class Lookup
  def postal_codes
    @postal_codes ||= {
      V: "British Columbia",
      # SKIPPED
      B: "Nova Scotia"
    }
  end

  def lookup_code(postal_code)
    territory = postal_codes.fetch(postal_code[0].upcase.to_sym)
    puts "Your address is in #{territory}"
  end
end

Lookup.new.lookup_code("01234")

解决方案5(归功于@ndn):内联哈希

def lookup_code(postal_code)
  territory = {
    V: "British Columbia",
    # SKIPPED
    B: "Nova Scotia"
  }.fetch(postal_code[0].upcase.to_sym)
  puts "Your address is in #{territory}"
end

答案 1 :(得分:1)

@postal_codes = {
  V: "British Columbia",
  Y: "Yukon Territory",
  X: "Northwest Territory",
  T: "Alberta",
  S: "Saskatechewan",
  R: "Manitoba",
  P: "Northern Ontario",
  M: "Toronto",
  L: "Central Ontario",
  K: "Eastern Ontario",
  J: "Western & Northern Quebec",
  N: "Western Ontario",
  G: "Eastern Quebec",
  H: "Metroplitan Montreal",
  A: "Newfoundland & Labradour",
  C: "Prince Edward Island",
  E: "New Brunswick",
  B: "Nova Scotia"
}

def lookup_code(postal_code)
  territory = @postal_codes.fetch(postal_code[0].upcase.to_sym)
  puts "Your address is in #{territory}"
end