【问题标题】:Ruby explicit & implicit return confusionsRuby 显式和隐式返回混淆
【发布时间】:2015-09-17 22:58:20
【问题描述】:

我正在玩构建一个小的地址簿程序。我有三门课; AddressBookContactAddress。在Address 类中编写的to_s 方法定义了地址的输出格式,我在Contact 类中编写了一个print_addresses 方法,该方法等待传入的参数是long 还是short应该输出 to_s 方法中定义的两种输出格式之一。在 AddressBook 类的 Contact 实例上调用 print_addresses('long') 时,它只会输出 short 方法中定义的 short 格式。

这没有按我的预期工作,我很确定这是我对方法和变量范围或显式和隐式返回的理解有问题,但我无法辨别我哪里出错了。我写的代码如下,谁能帮助我更好地理解这一点?谢谢。

地址类

class Address
  attr_accessor :kind, :street_1, :street_2, :city, :state, :postal_code 


  def to_s(format = 'short')
    address = ''
    case format
    when 'long'
      address += street_1 + "\n"
      address += street_2 + "\n" if !street_2.nil? 
      address += "#{city}, #{state} #{postal_code}"
    when 'short'
      address += "#{kind}: "
      address += street_1
      if street_2 
        address += " " + street_2 
      end
      address += ", #{city}, #{state}, #{postal_code}"
    end
    address
   end
  end

联系班级

require './phone_number'
require './address'

class Contact
  attr_writer :first_name, :middle_name, :last_name
  attr_reader :phone_numbers, :addresses

  def initialize
    @phone_numbers = []
    @addresses = []
  end

def add_address(kind, street_1, street_2, city, state, postal_code)
    address = Address.new
    address.kind = kind
    address.street_1 = street_1
    address.street_2 = street_2
    address.city = city
    address.state = state
    address.postal_code = postal_code
    addresses.push(address)
end

def print_addresses(format = 'short')
    puts "Addresses:"
    case format
    when 'short' 
      addresses.each do |address|
        address.to_s('short')
      end
    when 'long'
      addresses.each do |address|
        address.to_s('long')
      end
    end
  end
end

通讯录类

require './contact'

class AddressBook
  attr_reader :contacts

  def initialize
    @contacts = []
  end

  def find_by_name(name)
    results = []
    search = name.downcase
    @contacts.each do |contact|
      if contact.first_name.downcase.include?(search)
        results.push(contact)
      end
    end
    puts "Name search results (#{search})"
    results.each do |contact|
      puts contact.to_s('full_name')
      puts contact.print_addresses('long')
      puts contact.print_phone_numbers

    end
  end
end

address_book = AddressBook.new

james = Contact.new
james.first_name = "James"
james.middle_name = "jim"
james.last_name = "jimbo"
james.add_address('home', '1', '2', '3', '4', '5')



address_book.contacts.push(james)
puts "-" * 35
puts james.print_addresses('long')
puts '=' * 35

ruby address_book.rb - 输出

------------------------------
Addresses:
home: 1, 2, 3, 4, 5
===================================

期待并努力实现:

------------------------------
Addresses:
1,
2,
3, 4, 5
===================================

【问题讨论】:

  • 缺少enddef add_address
  • Contact.add_phone_number 从未定义。
  • 很好,感谢 Aetherus,粘贴错误。未解决引用的问题。
  • 感谢 Schwern,尝试取出不相关的方法但错误留下了一些痕迹,现在已删除痕迹!
  • 你期待什么结果?

标签: ruby methods scope return


【解决方案1】:

它同时提供长版和短版。您可以通过在 to_s 函数中添加 puts "long"puts "short" 来查看这一点。

问题不在于范围,而在于您对 print_addresses 中最后一个评估表达式的隐式返回的依赖。 print_addresses 不打印任何内容,也没有明确返回任何内容。它尽职尽责地调用address.to_s('long'),抛出结果,并返回最后一个计算表达式的结果...addressaddress 然后通过 puts 运行,这导致它被转换为具有默认短格式的字符串。你可以注释掉对address.to_s的调用,你会得到同样的结果。

address 是最后一个求值的表达式,这可能看起来很奇怪,这就是为什么您应该始终执行显式返回。它使代码更易于阅读,并为每个人省去了很多麻烦。这也指出你的函数应该返回不止一件事,这是你不能轻易隐式做的事情。

  def print_addresses(format = 'short')
    puts "Addresses:"

    formatted_addresses = []

    case format
    when 'short' 
      addresses.each do |address|
        formatted_addresses << address.to_s('short')
      end
    when 'long'
      addresses.each do |address|
        formatted_addresses << address.to_s('long')
      end
    end

    return formatted_addresses
  end

附带说明,由于print_addresses 不打印,因此应将其称为format_addresses。它还应该摆脱那个多余的 case 语句。额外的格式(“地址”标头)进入包装器方法以使 format_addresses 灵活。

  def display_addresses(format)
    return ["Addresses: "] + format_addresses(format)
  end

  def format_addresses(format = 'short')    
    formatted_addresses = []

    addresses.each do |address|
      formatted_addresses << address.to_s(format)
    end

    return formatted_addresses
  end

【讨论】:

  • 向你鞠躬@Schwern,真的谢谢你。我已经盯着这个难题看了好几个小时,试图弄清楚它,你已经正式向我展示了光明。非常感谢。
  • 我自己摸索了一会儿,大概花了半个小时调试 puts 并在调试器中弄明白了。
  • 谢谢 Schwerm,非常有帮助。我想知道您在何时显式返回以及何时回复隐式返回方面是否遵守规则?想我会重新命名这个问题,以便有退货问题的人更容易找到它!
  • @jbk 我有一个规则。 始终使用显式返回。一个额外的词将为您或其他人节省数小时的调试时间。空返回明确表明该函数不返回任何内容,并且可以避免人们以后使用意外的返回值。例外情况是非常小的内联函数,例如 array.map { |x| x*2 }
  • 很好,感谢@Schwern 的提示。从函数中显式返回“中断”不是吗,所以也许人们必须小心使用它,例如,您可能想要继续循环的循环?
猜你喜欢
  • 2016-12-03
  • 1970-01-01
  • 2010-10-20
  • 1970-01-01
  • 2023-03-08
  • 2013-12-14
  • 2010-11-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多