1

これは 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"
4

3 に答える 3

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

これは、キー (スープ) が値に 1 を加えた値に等しいことを示しています (この場合、値はまだ確立されていないため、結果は 1 になります)。

If a = "Soup"thena = (a||0)+1が評価されa = "Soup" + 1、Ruby で整数と文字列を追加することはできません。1 を文字列に変換すると、式は正しく評価されます。

a = (a||0)+1.to_s
于 2013-07-25T00:27:05.793 に答える
2

ruby では変数とオブジェクトに分けられない。ここにあるものはすべてオブジェクトです。

あなたのコードについて理解すべき唯一のことは、両方のケースで試しているように、 + メソッド(そう、そのメソッド)は文字列オブジェクトでは機能しないということです。オブジェクトが NILL の場合、Fixnum オブジェクト 0 で初期化しているため、その場合に機能し、+ メソッドは Fixnum で正常に機能します。

私があなたに答えたことを願っています。さらに説明が必要な場合は、お問い合わせください。

于 2013-07-25T04:47:13.603 に答える
1

このコードでは:

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

aDISH_BOWL_MAPPINGハッシュ内の値の 1 つからの文字列になるnilか、キーが存在しない場合のいずれかになります。の場合は nil にもなり、 に評価され、nilその後に追加されます。ここでの重要な概念は、キーが見つからない場合に返されることです (デフォルトをここにない別のものに設定していない限り)。明らかに、ここでの最終的な効果は、既に存在する場合はインクリメントし、まだ存在しない場合はに設定することです。@dishes_needed[a](@dishes_needed[a] || 0)01Hash#[]nil@dishes_needed[a]1

それを次のように対比してください。

a = "Soup"
a = (a||0)+1

ここでは、常にaとして開始する"Soup"ため、追加することはできません。(a||0)"Soup"1

于 2013-07-25T00:30:05.923 に答える