3

As I was modelling expressions like Var("x") or Number(7) and writing an eval function with pattern matching, I ran into a case where I could not avoid using the ´asInstanceOf` method.

2 restrictions

  • I do not want to avoid pattern matching by declaring an eval method in Expr and define it in its subclasses (cf. Expression problem, I prefer pattern match).

  • I also do not want something like Var("x", 7).

sealed trait Expr
object Expr {
  def eval(e: Expr): Int = e match {
    case Number(n) => n
    case Var(_) => e.asInstanceOf[Var].getValue()
  }
}
case class Number(n: Int) extends Expr
case class Var(s: String) extends Expr {
  var value = 0
  def getValue(): Int = value
  def updateValue(x: Int): Unit = {
    this.value = x
  }
}
val x = Var("x")
x.updateValue(1)
Expr.eval(x) // 1

When I define the second case like this: case Var(x) => Var(x).getValue(), i get Expr.eval(x) // 0. This is, because Var(x) on the right side will construct a fresh Var with value 0.

I'm ok with using asInstanceOf but in the sense of improvement, I wonder if there is a cleaner solution than using asInstanceOf, which I haven't found yet.

colorblind
  • 158
  • 2
  • 7

1 Answers1

3

You can use @ to bind a variable to a pattern. Use it like this:

def eval(e: Expr): Int = e match {
    case Number(n) => n
    case v@Var(_) => v.getValue()
}

You can also check the type of a variable in a pattern match

def eval(e: Expr): Int = e match {
    case Number(n) => n
    case v: Var => v.getValue()
}
user
  • 7,435
  • 3
  • 14
  • 44
  • 1
    @colorblind oh ok, yeah. First I apologize if I sounded too imperative, it should have been more of an suggestion like: _" if this solves your problem, please consider accepting this answer"_. - Second, you can always change your mind an accept a different answer if you feel someone gave a better one. Third, being honest, given that yours was a quite basic question with a simple answer, it is improbable there will be a new one, so accepting it now makes sense. cheers :) – Luis Miguel Mejía Suárez May 11 '20 at 23:34
  • 2
    @colorblind probably you already see [this](https://stackoverflow.com/help/someone-answers) but just in case. And yes, comments are temporary, if they were already useful, we usually delete them, like in this case. Happy coding and welcome to the SO community. – Luis Miguel Mejía Suárez May 11 '20 at 23:47