News for hackers. Stuff that matters.
Re:Clojure vs. Scala by octo_t on Tuesday December 24, 2013 @08:42AM (#6959306)
So the Scala solution for this is: http://ideone.com/Vussjh

  object Cards {
    sealed trait Suit
    case object Spades extends Suit
    case object Clubs extends Suit
    case object Hearts extends Suit
    case object Diamonds extends Suit

    sealed trait Rank
    trait FaceCard extends Rank

    case object Jack  extends FaceCard
    case object Queen extends FaceCard
    case object King  extends FaceCard
    case object Ace   extends FaceCard

    case class ValueCard(n: Int) extends Rank

    case class Card(rank: Rank, suit: Suit)

    type Deck = IndexedSeq[Card]

    def numberToRank(n: Int): Rank = n match {
      case 1 => Ace
      case x if x <= 10 => ValueCard(x)
      case 11 => Jack
      case 12 => Queen
      case 13 => King
      case 14 => Ace
      case _ => throw new IllegalArgumentException
    }

    def numberToSuit(n: Int): Suit = n match {
      case 0 => Spades
      case 1 => Clubs
      case 2 => Hearts
      case 3 => Diamonds
    }

    def apply(): Deck = for(rank <- 1 to 13; suit <- 0 to 3) yield Card(numberToRank(rank), numberToSuit(suit))
  }
Now I have: normal operations bound to Deck (head, take, drop etc) and the ability to pattern match on cards. Also strongly typed. This took about 5 minutes top to write.

edit: I'd say the 'numberToRank' parts are probably code smells, but given that its Christmas Eve, I really can't be bothered to think of a better solution right now. Implementing ordering etc can be done on the traits very easily too, but that is game specific (for example are aces high or low, is a King ranked higher than a Jack etc).

Re:Clojure vs. Scala by brudgers on Tuesday December 24, 2013 @08:57AM (#6959346)
Some things are strongly typed and playing cards are among them. It is just that playing cards are strongly typed as playing cards, not integers or pairs of integers.

In blackjack:

    case 10 => Jack or Queen or King or 10
and

    case Ace => 1 or 11
and poker with "Dr Pepper"

    case 10 => ace or 2 or 3 or 4 or 5 or 6 or 7 or 8 or 9 or 10 or jack or queen or king
    case 2 => ace or 2 or 3 or 4 or 5 or 6 or 7 or 8 or 9 or 10 or jack or queen or king
    case 4 => ace or 2 or 3 or 4 or 5 or 6 or 7 or 8 or 9 or 10 or jack or queen or king
It is sometimes better if the data type provides abstractions over the messy details of the world rather than adding another one to it and planning for the possibility of a Joker in the deck might make sense.
Re:Clojure vs. Scala by octo_t on Tuesday December 24, 2013 @09:00AM (#6959357)
Heh, same time as my edit. Those methods should be private (i.e. they just exist for building the deck, its the consumers responsibility to shuffle / split into multiple decks etc, as well as assigning value to each card).
Re:Clojure vs. Scala by brudgers on Tuesday December 24, 2013 @10:33AM (#6959706)
So what then does 13=king get me over king=king? And does forgetting to privatise implementation details suggest that the necessary language idioms make the data structure complex in a way that is orthogonal to the real world complexity of the objects it represents, and wasn't the opportunity to avoid that complexity the advantage suggested by the author. To put it another way, private and sealed and trait don't reflect characteristics of a deck of playing cards. They are overhead from the language. It is a case where a static type system, because it is biased toward it's and strings and objects, makes it more difficult to reason about our code - leaving jokers aside, how much of the Scala code makes sense if I want to play Pinnocle versus the data approach advanced by the author? Now I'll admit that Lisp has shaped the way I see the two approaches to representing cards. and this may be why I see implementation of jokers and pinnocle as easy extensions of lists and rather more complex under an object system with static type checking. But I will point out that this model got me to thinking about card games rather than card data types pretty quickly, and card games are probably the reason we're draining the swamp.
Re:Clojure vs. Scala by drewhk on Tuesday December 24, 2013 @09:13AM (#6959385)
Yep, valuation can be simply a function, but wrapping in a typeclass might work as well.
Re:Clojure vs. Scala by necrobrit on Tuesday December 24, 2013 @09:19AM (#6959408)
Does that 'or' method actually exist in a library somewhere or was it just for illustration?
Re:Clojure vs. Scala by brudgers on Tuesday December 24, 2013 @09:58AM (#6959556)
Just for illustration. But to the author of the article's point that programming languages structure our thinking, the idea that "or" must be either in the core language or part of some library illustrates the constraints imposed on expressing our ideas absent the ability to introduce new syntax via a lisp-style macro facility. In a sense, Clojure's light weight data structures can be seen as extending up into the language.
Re:Clojure vs. Scala by dragonwriter on Tuesday December 24, 2013 @03:11PM (#6960950)
> I'd say the 'numberToRank' parts are probably code smells, but given that its Christmas Eve, I really can't be bothered to think of a better solution right now.

  object Cards {
    sealed trait Suit
    case object Spades extends Suit
    case object Clubs extends Suit
    case object Hearts extends Suit
    case object Diamonds extends Suit

    sealed trait Rank
    trait FaceCard extends Rank

    case object Jack  extends FaceCard
    case object Queen extends FaceCard
    case object King  extends FaceCard
    case object Ace   extends FaceCard

    case class ValueCard(n: Int) extends Rank

    case class Card(rank: Rank, suit: Suit)

    type Deck = IndexedSeq[Card]
    
    val faceCardRanks = IndexedSeq(Jack,Queen,King,Ace)
    val valueCardRanks = for (rank <- 2 to 10) yield ValueCard(rank)
    val ranks = IndexedSeq.concat(valueCardRanks,faceCardRanks)
    val suits = IndexedSeq(Spades,Clubs,Diamonds,Hearts)
    
    def apply(): Deck = for(rank <- ranks; suit <- suits) yield Card(rank, suit)
  }