2

I am new to Scala, and was trying to understand match.

When I try to run the following code, the javaw VM does not respond (keeps waiting for ever - trying this from eclipse)

case GenericProfile(user) => processGenericProfile(_)
case _ => println("Invalid data found")

However, the following section works just fine:

case GenericProfile(user) => processGenericProfile(GenericProfile(user))
case _ => println("Invalid data found")

I am trying to understand why the first scenario would fail to respond. I do not want to pass GenericProfile(user) - I would like to know how this can be simplified. Thnaks!!

felixmd
  • 200
  • 1
  • 6

1 Answers1

8

without seeing how processGenericProfile and GenericProfile are defined it's hard to tell for sure, but I think your first case (case GenericProfile(user) => processGenericProfile(_)) is just returning a partially applied function processGenericProfile and not applying it to the results on the left hand of the case as I understand you want to do...

Consider this REPL sessions, where I give "fake" definitions for processGenericProfile and GenericProfile

scala> case class GenericProfile(user: String)
defined class GenericProfile

scala> def processGenericProfile(u: GenericProfile) = "processed"
processGenericProfile: (u: GenericProfile)java.lang.String

scala> GenericProfile("Paolo") match {
     | case GenericProfile(user) => processGenericProfile(_)
     | case _ => "wrong"
     | }
res0: java.lang.Object = <function1>

See the return type of the match? It's likely that you are not stuck, the match returns a function and does not apply it, so you're waiting for something to happen, but scala thinks it has already done what you wanted to do (return a function).

If you need to capture the whole GenericProfile, instead of just the user it contains, you can use an alias with the @ symbol, like this:

    scala> GenericProfile("Paolo") match {
         | case u @ GenericProfile(user) => processGenericProfile(u)
         | case _ => "wrong"
         | }
    res2: java.lang.String = processed

One last thing. I'm not sure what the "user" in case GenericProfile(user) represents. The way I wrote it, it's a name that is bound to the value contained in the GenericProfile. I.e. in the first case we're saying "if the item we're checking is a GenericProfile, take the string it contains ("Paolo" in this case) and bind it to a name user.

Since you are not using that value on the right-hand side, you can also do:

case u @ GenericProfile(_) => processGenericProfile(u)

where the _ on the left hand side makes it explicit that you're discarding the matched user and you're just interested in checking that the type is a GenericProfile.

If instead "user" is a variable that you defined previously (i.e. you want your case statement to check that you have a GenericProfile for a specific user), then you need to tell scala that user is something you defined and not a name you want to bind to whatever is found in GenericProfile. That can be done by surrounding your identifier (user) with backticks, like this:

val user="Paolo"

GenericProfile("Paolo") match {
    case u @ GenericProfile(`user`) => processGenericProfile(u) 
                                               //now this only matches                      
                                               //GenericProfile("Paolo")
    case GenericProfile(_) => "not Paolo"    
    case _ => "wrong"
}
Community
  • 1
  • 1
Paolo Falabella
  • 24,914
  • 3
  • 72
  • 86
  • You were right - I was unknowingly using a partial function. Thanks for the detailed response - Inspiring!! – felixmd Nov 18 '12 at 12:13