为什么变量=变量+ 1有效?

时间:2013-07-25 00:20:40

标签: ruby

这是一个Ruby Monk练习,我无法绕过一个特定的概念。

例如,"soup bowl" = "soup bowl" + 1无效,那么为什么@dishes_needed[a] = (@dishes_needed[a] || 0) + 1可以在下面的代码中使用?是因为它们是变量而不是对象吗?如果是这样,为什么我最初设置a = (a||0)+1时代码a = "Soup"无效:

class Dish
end

class Soup < Dish
end
class IceCream < Dish
end
class ChineseGreenBeans < Dish
end

class DeliveryTray
  DISH_BOWL_MAPPING = { 
    Soup => "soup bowl",
    IceCream => "ice cream bowl",
    ChineseGreenBeans => "serving plate"
  }

  def initialize
    @dishes_needed = {}
  end

  def add(dish)
    a = DISH_BOWL_MAPPING[dish.class]
     @dishes_needed[a] = (@dishes_needed[a] || 0) + 1
  end

  def dishes_needed
      return "None." if @dishes_needed.empty?

      @dishes_needed.map { |dish, count| "#{count} #{dish}"}.join(", ")
  end
end  

d = DeliveryTray.new
d.add Soup.new; d.add Soup.new
d.add IceCream.new

puts d.dishes_needed # should be "2 soup bowl, 1 ice cream bowl"

3 个答案:

答案 0 :(得分:3)

让我们简化@dishes_needed部分,以便您了解核心概念。 @dishes_needed是一个哈希值,@dishes_needed[a] = (@dishes_needed[a] || 0) + 1为哈希值添加一个键值对。

这是查看代码的更简单方法。这是DISH_BOWL_MAPPING哈希:

  DISH_BOWL_MAPPING = { 
    Soup => "soup bowl",
    IceCream => "ice cream bowl",
    ChineseGreenBeans => "serving plate"
  }

DISH_BOWL_MAPPING哈希中获取某个元素:

>> DISH_BOWL_MAPPING[Soup]
=> "soup bowl"

@dishes_needed是一个空哈希:

>> @dishes_needed = {}
=> {}

如果a = Soup,那么这就是所讨论的代码行的运作方式:

>> a = Soup
=> Soup
>> @dishes_needed[a] = (@dishes_needed[a] || 0) + 1
=> 1
>> @dishes_needed
=> {Soup=>1}

让我们分解混淆等式的右边:

>> (@dishes_needed[a] || 0) + 1
>> (@dishes_needed[Soup] || 0) + 1
# @dishes_needed[Soup] is nil because Soup hasn't been added to the hash yet
>> (nil || 0) + 1
# nil || 0 evaluates to 0 because nil and false are falsey in Ruby
>> (0) + 1
>> 1

后来调用@dishes_needed[Soup]评估为1,现在哈希已更新:

>> @dishes_needed[Soup]
=> 1

这表示密钥(Soup)等于值加1(在这种情况下,该值尚未建立,因此导致1)。

如果a = "Soup",则a = (a||0)+1评估为a = "Soup" + 1,并且您无法在Ruby中添加整数和字符串。如果将1转换为字符串,则表达式将正确计算。

a = (a||0)+1.to_s

答案 1 :(得分:2)

我们不能将事物划分为ruby中的变量和对象。这里的一切都是一个对象。

关于你的代码唯一需要理解的是+方法(是的,它是一个方法)不会像你在两种情况下尝试的那样使用字符串对象。它适用于那种情况,因为如果对象是NILL,你用Fixnum对象初始化它0和+方法与Fixnum一起正常工作。

希望我能回答你。如果需要更多说明,请询问。

答案 2 :(得分:1)

在此代码中:

a = DISH_BOWL_MAPPING[dish.class]
@dishes_needed[a] = (@dishes_needed[a] || 0) + 1

a要么是来自DISH_BOWL_MAPPING哈希值中的一个值的字符串,要么是nil,如果密钥不在那里。如果是nil,则@dishes_needed[a]也将为零,这会使(@dishes_needed[a] || 0)评估为0,然后您将1添加到Hash#[]。这里的关键概念是nil如果找不到密钥则返回@dishes_needed[a](除非你将默认设置为其他东西,你没有在这里)。显然,这里的净效果是如果它已经存在则递增1,或者如果它不存在则将其设置为a = "Soup" a = (a||0)+1

与之对比:

a

此处,"Soup"始终以(a||0)开头,因此"Soup"始终为1,您无法将{{1}}添加到。{/ p>