top | item 6959223

(no title)

JeanPierre | 12 years ago

Using val King = 13; val Queen = 12; in Scala is not equivalent with using Clojure keywords, as their printed variant will be 13 and 12, not :king and :queen. Reading debugging output or logs would force you to manually convert those values.

Ordering for free is valuable, I guess, but it sort of depends on the situation. Sometimes face cards are worth 10, other times they are worth 11, 12, 13. If you use val King = 10;, then it suddenly is impossible to distinguish between face cards and tens.

discuss

order

anonymoushn|12 years ago

Right, if you wanted to have an ordering around, you would use an enum. The enum's values would print as Ace, 2, 3, 4, ..., Jack, Queen, King, and then when you wanted to implement a particular game the game could define the mapping from rank -> set of possible values. You wouldn't want to map each rank to a single value, since in commonly played games aces are worth both 1 and 11 or both 1 and 14.

If you didn't want the ordering (or the compiler warning when your blackjack implementation omits queens), you could use Scala's symbols, which are more or less the same as Clojure's keywords:

  scala> 'king
  res0: Symbol = 'king

drewhk|12 years ago

Or use value classes and get the best of both worlds.

fhars|12 years ago

No, your first sentence is wrong. The following definition stores the ranks as unboxed integers, but prints them differently:

    case class Rank private (val rank : Int) extends AnyVal {
      override def toString() = {
        rank match {
          case 1 => "A" 
          case 11 => "J"
          case 12 => "Q"
          case 13 => "K"
          case _ => rank.toString()
        }
      }
    }   

    object Rank {
       val Ace = Rank(1)
       val Two = Rank(2)
       // ...
       val King = Rank(13)
    }

drewhk|12 years ago

And you can create a new string interpolation to make card instances, like:

    card"Heart:Ace"
or

    card"$suite:Ace" if you want to reference a variable.