Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Concise way to create day of week enumeration in Scala

Tags:

enums

scala

I'm new to Scala, so be nice please. You'll have to excuse me if I'm missing something obvious.

I'm trying to create an enum like structure to represent the days of the week in Scala. I want a method that accepts a string that can either be the numbers 1 through 7, the full name of the day, or a three letter abbreviation, with any capitalisation, and returns the correct day. Ideally I want to be able to retrieve the correct day simply by writing DayOfWeek(_), which as far as I understand things means this method needs to be apply. The individual values also have to be subclasses (or mix in) a trait called CalendarField, which at the moment defines no methods or members.

This is my current attempt:

object DayOfWeek extends Enumeration with CalendarField {

    val Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday = Value

    def apply(v:String) = {
        v.toUpperCase match {
            case Int(x) => x match {
                case 1 => Sunday
                case 2 => Monday
                case 3 => Tuesday
                case 4 => Wednesday
                case 5 => Thursday                  
                case 6 => Friday
                case 7 => Saturday
                case _ => throw new IllegalArgumentException("Invalid value for day of week: " + v)
            }
            case "SUN" | "SUNDAY" => Sunday
            case "MON" | "MONDAY" => Monday
            case "TUE" | "TUEDAY" => Tuesday
            case "WED" | "WEDNESDAY" => Wednesday
            case "THU" | "THURSDAY" => Thursday
            case "FRI" | "FRIDAY" => Friday
            case "SAT" | "SATURDAY" => Saturday
            case _ => throw new IllegalArgumentException("Invalid value for day of week: " + v)
        }
    }
}

object Int {
    def unapply(s : String) : Option[Int] = try {
        Some(s.toInt)
    } catch {
        case _ : java.lang.NumberFormatException => None
    }
}

This fails on a few points:

  1. The individual values aren't subclasses of CalendarField - they are simply Values.
  2. I've defined an apply method but DayOfWeek(_) doesn't work - my (vague) guess this is because it expects to call a constructor and DayOfWeek is an object, not a class? Or is it because Enumeration(s:String) is already used? Is there a way round this?

Any suggestions on how to get round these problems, or neater solutions, would be greatly appreciated. Thanks.

like image 697
Russell Avatar asked May 20 '11 18:05

Russell


People also ask

How do you find the day of the week in a string?

String[] days = new String[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; Display the day name. The following is the final example.

How do you create an enum in Scala?

In Scala, there is no enum keyword unlike Java or C. Scala provides an Enumeration class which we can extend in order to create our enumerations. Every Enumeration constant represents an object of type Enumeration. Enumeration values are defined as val members of the evaluation.

Can we define enum inside a method?

We can an enumeration inside a class. But, we cannot define an enum inside a method. If you try to do so it generates a compile time error saying “enum types must not be local”.

How enums are used?

Enums are used when we know all possible values at compile-time, such as choices on a menu, rounding modes, command-line flags, etc. It is not necessary that the set of constants in an enum type stay fixed for all time. In Java (from 1.5), enums are represented using enum data type.


1 Answers

I'd probably implement something like this:

sealed trait DayOfWeek
case object Monday extends DayOfWeek
case object Tuesday extends DayOfWeek
// etc.

object DayOfWeek {
   def unapply(s: String): Option[DayOfWeek] = s.toUpperCase match {
      case Int(x) => x match {
         case 1 => Some(Sunday)
         // ...
         case _ => None
      }
      case "SUN" | "SUNDAY" => Some(Sunday)
      // ...
      case _ => None
   }

   def apply(s: String): DayOfWeek = s match {
      case DayOfWeek(d) => d
      case _ => throw new IllegalArgumentException(
                   "Invalid value for day of week: " + s)
   }

}

like image 125
Aaron Novstrup Avatar answered Sep 30 '22 10:09

Aaron Novstrup