Tell me more ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I'm currently in the process of learning scala, and I'm looking for some best practices/proper idioms for the use of pattern matching with BigInts. I'm writing some algorithmic code (for Project Euler) as a way to learn the language.

The problem I am running into is what is the best idiomatic way to match a BigInt, since there's a type conversion problem if I try to write case 1 => and BigInt isn't a case class. Is there a canonical way to do this, or should I just give up and use if statements?

The following is one possible pattern:

def pollardRho(n: BigInt): BigInt = {
  val one = BigInt(1)

  n match {
    case `one` => n
    //additional cases here
  }
}

This one just feels wrong: A hack to get around the fact that I can't match it directly, especially with the backticks in there to keep scala from trying to assign the resulting value to one or when I have to do it for more than a single value or in a single case.

Another possibility:

def pollardRho(n: BigInt): BigInt = {

  n match {
    case _ if n == 1 => n
    //additional cases here
  }
}

This sort of pattern appeals to the Erlang programmer in me, but I have some concerns:

  1. Given the warnings I've read not to treat Scala like any other language, I am not sure that my instinct here is not an anti-pattern (or at least considered less readable) in the scala world.
  2. It feels like there might be cleaner way to use a custom PartialFunction instead of n match if what I am fundamentally going to do is just a series of tests around n. I am not sure, however, exactly what that would look like (most of the examples of PartialFunctions I've seen don't look quite like this application).

My question is, out of the array of possibilities in scala, which one is the best/most readable/most idiomatic?

share|improve this question

1 Answer

Write your own extractor:

object Big {
  def unapply(n:BigInt) = Some(n.toInt)
}

//usage
def f(b:BigInt) = b match {
   case Big(0) => "none"
   case Big(1) => "one"
   case _ => "many"
}

Obviously, this isn't the fastest solution, but I think, it's quite idiomatic...

share|improve this answer
This also doesn't produce the desired output, since it assumes that I am working with something that can convert to Int without overflow, e.g., BigInt("4294967297") will match Big(1). – dclements Aug 11 '12 at 20:18
The logic in this one might not be 100% correct but extract is definitely the way to go if you want to be able to use match. – ericacm Aug 11 '12 at 21:01

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.