开发者

how to expose test for a pattern match

开发者 https://www.devze.com 2023-01-15 12:02 出处:网络
I\'m rater new to scala, but basically have found my way around... Here, I\'m asking for the recommended/best practice/idiomatic way of implementing this:

I'm rater new to scala, but basically have found my way around...

Here, I'm asking for the recommended/best practice/idiomatic way of implementing this:

  • internally, MyClass uses a state type, which is implemented by a sealed hierarchy of case classes
  • but on the API, only some boolean predicate should be exposed, which gets implemented by matching against the (in开发者_开发技巧ternal) state.

Currently, my implementation is along the lines of...

def isSane: Boolean = state match {
    case Ok(_,'valid) => true
    case _            => false
}

But this solution feels awkward to me, as if expressing something in 3 lines of code which has only information content worth one line of code. Actually, what I'd like to write would be:

def isSane: boolean = state matches Ok(_, 'valid)

Probably/likely it's possible to implement a suitable operator yourself in scala, but before I look into that, I'd like to know what would be the usual way to solve this problem. Maybe there's also some existing library implementation around?


I'd do something like this:

abstract class State {
  def matches(pf: PartialFunction[State, Unit]) = pf isDefinedAt this
}

// then

def isSane = state matches { case Ok(_,'valid) => }

Because matches is defined to receive a partial function, you can follow it with a function literal with only the case statements that should result in true. You do not need to return anything, as the partial function is defined as returning Unit. Finally, the matches method uses the isDefinedAt method of partial functions to verify if there's a case statement covering itself.


I may be old-fashioned, but why not use polymorphism?

trait State { def sane: Boolean }

trait InvalidState extends State { def sane = false }

case class Ok(whatever: Whatever, s: Symbol) extends State {
   def sane = { s == 'valid }
}

case class Failure(msg: String) extends InvalidState 

case class WarmingUp extends InvalidState

// ...

def isSane(): Boolean = state.sane

Of course, if that's not a possibility for whatever reason, you can generalize Daniel's solution somewhat:

class Matcher[T](o: T) {
   def matches(pf: PartialFunction[T, Unit]) = pf isDefinedAt o
}

object Matcher {
   implicit def o2matcher[T](o: T): Matcher[T] = new Matcher(o)
}

// then
def isSane = state matches { case Ok(_,'valid) => }


If the Symbol property is statically known to be a property of the type of state:

def isSane: Boolean =
  state.secondSymbolPropertyWhateverItsCalled == 'valid

If you don't know that state is an Ok, then:

def isSane: Boolean =
  state.isInstanceOf[Ok] && state.asInstanceOf[Ok].symbolProp == 'valid

but at this point, it's not really superior to what you wrote.

Lastly, you could just define isSane on that hierarchy of types and delegate to it:

def isSane: Boolean =
  state.isSane
0

精彩评论

暂无评论...
验证码 换一张
取 消