Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Case Sensitive withName's #5

Closed
adamdecaf opened this issue Mar 5, 2015 · 6 comments
Closed

Case Sensitive withName's #5

adamdecaf opened this issue Mar 5, 2015 · 6 comments
Assignees

Comments

@adamdecaf
Copy link

Often when reading message blobs from outside parties the case sensitivity will vary from message to message. It's often nice to not have to worry "did I .toLowerCase? or should it be .toUpperCase" the specific values you're reading out.

@lloydmeta
Copy link
Owner

As of now, the withName method is case sensitive by design, so that there are no surprises when coming from the standard lib Enumeration and because I think it makes sense (no pun intended). Convoluted example; in a Drinks enum, coke may not be the same as Coke.

That said, I'm open to the idea of making withName optionally case insensitive, such as via an optional parameter caseInsensitive parameter that defaults to false.

@adamdecaf
Copy link
Author

What about an import? This is what I've used in a few projects to soften the impact of throwing an exception when trying to parse incoming data I don't control.

import scalaz.Monoid
object SafeEnumeration {
  implicit final class SafeEnumerationReads[E <: Enumeration](val enum: E) extends AnyVal {
    def safeWithName(name: String): Option[E#Value] = enum.values.find(_.toString equalsIgnoreCase name)
    def withNameOrZero(name: String)(implicit m: Monoid[E#Value]): E#Value = safeWithName(name) getOrElse m.zero
  }
}

Then it's really easy to use both methods on some enumeration.

object FacebookProfileCategory extends Enumeration {
  val `Musician/Band` = Value("Musician/Band")
  val Company = Value("Company")
  val Other = Value("Other")

  implicit val categoryMonoid = new Monoid[Value] {
    def zero = Other
    def append(x: Value, y: => Value) = ???
  }
}

@lloydmeta
Copy link
Owner

Wow, that is pretty cool :) I like the way you used implicits and monoids to make it slick.

However, I think introducing a separate method 1. that doesn't throw and 2. allows for case-insensitive matching might be a better compromise here because then we can cache the case-insensitive map (faster) and it is easier to use for end-users.

e.g. On Enum[A]

trait Enum[A] {

  lazy val caseInsensitiveNamesToValuesMap: Map[String, A] = values map (v => v.toString.toLowerCase -> v) toMap

  def withNameOption(name: String, caseInsensitive: Boolean = false): Option[A] = {
    if (caseInsensitive)
      caseInsensitiveNamesToValuesMap get name.toLowerCase
    else
      namesToValuesMap get name
  }
}

What do you think?

@adamdecaf
Copy link
Author

Not bad, maybe the boolean should be two methods?

@lloydmeta lloydmeta self-assigned this Mar 6, 2015
@lloydmeta
Copy link
Owner

Done !

@adamdecaf
Copy link
Author

Cool thanks!
On Mar 6, 2015 12:26 AM, "Lloyd" notifications@github.com wrote:

Done !


Reply to this email directly or view it on GitHub
#5 (comment).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants