Monday 7 May 2012

Y is 6 afraid_of 7

A few days ago I read a post by Dirk Detering. Apart from good laughs it gave me, it trapped my attention to a useless task of rewriting the code to remove the parentheses. Why? Because it's in Scala, and we need no stinkin' parens, right?

OK, so here is the original code from the Dirk's post:

type Reason = () => String

class ReasonedState(val state:Boolean, val reason:Reason)

case class True(why:Reason)  extends ReasonedState(true, why) {
   override def toString() = "yes"
}
case class False(why:Reason) extends ReasonedState(false, why) {
   override def toString() = "no"
}

class Fears(value:Int) {
   def afraidOf(other:Int) = (value,other) match {
      case (6,7) => True (() => (7 to 9).toList.map(_.toString).reduce(_+" "+_))
      case _     => False(() => "nothing to fear")
   }
}

implicit def numbersFears(nu:Int) = new Fears(nu)

def is(rs:ReasonedState) = rs
def y (rs:ReasonedState) = rs match {
    case rs:True => "because "+rs.reason()
    case _       => "wrong question"
}
To generate the pun you have to save the code to a file (e.g. fears.scala), open the Scala REPL console and type:
scala> :load fears.scala
...
scala> y ( is (6 afraidOf 7))
Funny eh? But it's not in English, so let's try to say it more natively. Ideally it should be able to compile the question:
scala> Y is 6 afraid of 7

The solution

Let's remove the parentheses between Y and is, first. It is possible with an infix method, so we need Y to be an object and is to be its infix method. Then we have another infix operator afraid that on the left side has an object of some class (let's borrow the name Fears) and on the right side there should be an object returned by a call to a function of.

The last part is most difficult to me, as I couldn't find a way to avoid the last parentheses. So my code makes it possible to ask the question in two ways:


scala> Y is 6 afraid of(7)
...
scala> Y is 6 afraid_of 7
And of course here it is the code:
case class Fears(value:Int) {
  var s: String = "... Wait! %d has no fears!".format(value)
  def afraid(f: Fears) = {
    if (value == 6)
      f.s = s + f.s
    else
      f.s = s
    f
  }
  def of(n: Int = value) = n match {
      case 7 => " " + (7 to 9).toList.map(_.toString).reduce(_+" "+_)
      case _ => "... Wait! There's nothing to fear!"
  }
  def afraid_of(f: Fears) = {
    f.s = of(f.value)
    afraid(f)
  }
  override def toString() = s
}

def of(f: Fears) = {
  f.s = f.of()
  f
}

implicit def numbersFears(n: Int) = new Fears(n)

object Y {
  def is(f: Fears) = {
    f.s = f.value match {
      case 6 => "because"
      case _ => "wrong question"
    }
    f
  }
}
The code is also available on GitHub. Just save it to another file and load to REPL. And remember -- to get the joke -- read it aloud in English.

If by accident a Scala wizard reads this post I would be glad to see the solution of the 'last mile problem', i.e. how to make it work with the ideal form of the question.

And at the very last -- the task of writing the program above wasn't really useless, because it was a good exercise for a Scala rookie like me.

Posted from a bus suffering a heavy traffic delay, but happily equipped with free wi-fi hot-spot. Technorati claim token: AQMTKWCBK5BZ

No comments:

Post a Comment