ChrisU
ChrisU

Reputation: 11

Scala: List of constants with individual access

I'm new to scala and I need a structure where I can easily add new indivdual accessable constants and also iterate over all of them. Something like this:

object Constants {
    val A = Something(...)
    val B = Something(...)
    val C = Something(...)
    // ...

    val listOfConstants = (A, B, C, ...)
}

But without the need to add the constant to the list manually. I considered a Map but this would make it harder to access the constants and I ended up writing this:

def getElements[T : ClassTag](c : Any) : Set[T] = {
    var result : Set[T] = Set()
    for (field <- c.getClass.getDeclaredFields) {
        field.setAccessible(true)
        field.get(c) match {
            case t: T => result += t
            case _ =>
        }
    }
    result
}

and then using the following line for structures like this

val listOfConstants = getElements[Something](Constants)

Is this a dirty solution? Are there better alternatives?

Upvotes: 1

Views: 1128

Answers (3)

dk14
dk14

Reputation: 22374

You could use scala's default Enumeration, but it has it's own caveats. The best enumaration library I know is Enumeratum. It allows you to write something like this:

object MyEnum extends Enum[Something] {

  val values = findValues

  case object A extends Something
  case object B extends Something
  case object C extends Something
  case object D extends Something

}

findValues is a macros that automatically finds all sub-objects of Something (inside MyEnum) in compile-time.

To add this lib using SBT:

libraryDependencies += "com.beachape" %% "enumeratum" % "1.4.0"

Upvotes: 3

radumanolescu
radumanolescu

Reputation: 4161

Try enumerations, for instance http://www.scala-lang.org/api/current/scala/Enumeration.html, or How to model type-safe enum types?. You can also write your enum in Java and use it from Scala

For instance, here's an enum defined in Java that you can use from Scala - and comes with a map of all its possible values, so you can get by key, iterate on the values, etc. The map of values is constructed automatically, so it does not need to be maintained manually.

import java.util.Collections;
import java.util.Map;
import java.util.HashMap;

/**
 * Demonstrates parsing of an enum from the contained value
 */
public enum WithFrom implements Something {
    TWO("one plus 1"), SIX("two plus 4");

    WithFrom(String expr) {
        this.expr = expr;
    }

    private final String expr;

    public static final Map<String, WithFrom> fromValue = Collections
            .unmodifiableMap(new HashMap<String, WithFrom>() {
                private static final long serialVersionUID = 7205142682214758287L;

                {
                    for (WithFrom wf : WithFrom.values()) {
                        put(wf.expr, wf);
                    }
                }
            });
}

Upvotes: 2

Anatoly
Anatoly

Reputation: 456

You could create an Enumeration and use its values: ValueSet method.

Upvotes: 1

Related Questions