redeagle47
redeagle47

Reputation: 1367

Why can't I update this mutable Map's value for this key in Scala?

I have a function that I need to update a mutable Map by decrementing the value associated with a key passed into the function. It looks like this:

def selectProduct(product: String, insertedAmount: Float): (String,String) = {
    val price = products(product)
    val returnedProduct = if (insertedAmount >= price) product else ""
    if (returnedProduct != "") {
      inventory.update(product, inventory(product) - 1)
    }
    val message = display.displayMessage(product, returnedProduct)
    (returnedProduct, message)
}

where inventory is defined like this:

def inventory = mutable.Map[String, Int](
  product1 -> 3,
  product2 -> 3,
  product3 -> 3
)

I have tests set up to check that after the item is selected in selectProduct, the inventory should have one fewer of that item. This test fails. I have verified the item is selected correctly. I have tried declaring the inventory value with both def and val. I have tried doing this in the REPL, and what I am trying to do works just fine. Why won't this value update?

Update: Test Code

class VendingMachineSpec extends UnitSpec {

def vendingMachine = new VendingMachine()

it should "remove a purchased item from the inventory" in {
  val sixtyFiveCents = vendingMachine.coinOp.insertCoin(QUARTER, vendingMachine.coinOp.insertCoin(QUARTER, vendingMachine.coinOp.insertCoin(NICKEL, vendingMachine.coinOp.insertCoin(DIME, Coins.coins(PENNY)))))
  assert(sixtyFiveCents == SIXTY_FIVE_CENTS)

  val results = vendingMachine.selectProduct(product1, sixtyFiveCents)
  val product = results._1
  val message = results._2
  assert(product == product1)
  assert(message == "Thank you!")

  assert(vendingMachine.inventory(product1) == 2)
}
}

Upvotes: 0

Views: 81

Answers (1)

irundaia
irundaia

Reputation: 1730

The problem lies with the definition of the inventory. You've defined the inventory as:

def inventory = mutable.Map[String, Int](???)

By defining it as a def, you've made sure that the inventory is reevealuated whenever it's used. So suppose you have:

val x = inventory
val y = inventory

both x and y would be pointing to different objects.

For your code to work, you'd have to replace the definition of inventory with either

val inventory = mutable.Map[String, Int](???)

or

lazy val inventory = mutable.Map[String, Int](???)

Upvotes: 3

Related Questions