This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Pattern matching on strings

12 replies
Grzegorz Kossakowski
Joined: 2009-01-28,
User offline. Last seen 42 years 45 weeks ago.

Hello,

I want to do something like:

str match {
case "prefix1" :: suffix => ...
case "prefix2" :: suffix => ...
case prefix :: "suffix" => ...
}

Is this kind of matching possible with Scala?

I know that behind-the-scenes there is recursive structure (List) involved and not flat one but still I wonder if this
can be handled nicely in Scala somehow.

normen.mueller
Joined: 2008-10-31,
User offline. Last seen 3 years 8 weeks ago.
Re: Pattern matching on strings

Grzegorz Kossakowski wrote:
> str match {
> case "prefix1" :: suffix => ...

As strings a sequences try:

case Seq('p','r','e','f','i','x','1',suffix@_*) => ...

> case "prefix2" :: suffix => ...
> case prefix :: "suffix" => ...
> }
>
> Is this kind of matching possible with Scala?
>
> I know that behind-the-scenes there is recursive structure (List) involved and not flat one but still I wonder if this
> can be handled nicely in Scala somehow.
>

Cheers,

Grzegorz Kossakowski
Joined: 2009-01-28,
User offline. Last seen 42 years 45 weeks ago.
Re: Pattern matching on strings

Normen Müller pisze:
> Grzegorz Kossakowski wrote:
>> str match {
>> case "prefix1" :: suffix => ...
>
> As strings a sequences try:
>
> case Seq('p','r','e','f','i','x','1',suffix@_*) => ...

Yes, this will work but it's far from being easy to use.

Is there any syntax sugar for it?

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Pattern matching on strings

On Mon, Mar 16, 2009 at 07:36:17PM +0100, Grzegorz Kossakowski wrote:
> str match {
> case "prefix1" :: suffix => ...
> case "prefix2" :: suffix => ...
> case prefix :: "suffix" => ...
> }
>
> Is this kind of matching possible with Scala?

Not quite like that. I can think of a bunch of not entirely satisfying
approaches. Here's a nice unappealing one:

scala> "abcdefgh".toSeq match { case Seq('a', 'b', 'c', x @ _*) => x.mkString }
res1: String = defgh

You can always do this sort of thing:

str match {
case x if x startsWith "prefix1" => ...
case x if x endsWith "suffix" => ...
}

Here's the best I could do with extractors on short notice, maybe
someone can be cleverer, perhaps using implicits.

object o {
case class Pre(prefix: String) {
def unapply(x: String) = if (x startsWith prefix) Some(x.substring(prefix.length)) else None
}
case class Suff(suffix: String) {
def unapply(x: String) = if (x endsWith suffix) Some(x.substring(0, x.length - suffix.length)) else None
}

def go(s: String) = {
val p1 = Pre("abcd")
val s1 = Suff("efgh")

s match {
case p1(x) => "'" + x + "' left"
case s1(x) => "'" + x + "' left"
case x => "no match"
}
}
}

scala> o.go("abcdbling")
res0: java.lang.String = 'bling' left

scala> o.go("blongefgh")
res1: java.lang.String = 'blong' left

In real life I just use regexps.

Randall R Schulz
Joined: 2008-12-16,
User offline. Last seen 1 year 29 weeks ago.
Re: Pattern matching on strings

On Monday March 16 2009, Grzegorz Kossakowski wrote:
> Normen Müller pisze:
> > Grzegorz Kossakowski wrote:
> >> str match {
> >> case "prefix1" :: suffix => ...
> >
> > As strings a sequences try:
> >
> > case Seq('p','r','e','f','i','x','1',suffix@_*) => ...
>
> Yes, this will work but it's far from being easy to use.
>
> Is there any syntax sugar for it?

Introduce an implicit conversion for String to Seq into the context
where you want to write those cases?

Randall Schulz

odersky
Joined: 2008-07-29,
User offline. Last seen 45 weeks 6 days ago.
Re: Pattern matching on strings

2009/3/16 Grzegorz Kossakowski :
> Hello,
>
> I want to do something like:
>
> str match {
>  case "prefix1" :: suffix => ...
>  case "prefix2" :: suffix => ...
>  case prefix :: "suffix" => ...
> }
>
> Is this kind of matching possible with Scala?
>
> I know that behind-the-scenes there is recursive structure (List) involved and not flat one but still I wonder if this
> can be handled nicely in Scala somehow.
>
I'd use a regex:

scala> val re1 = "abc(.*)".r
re1: scala.util.matching.Regex = abc(.*)

scala> "abcxyz" match {
| case re1(x) => println(x)
| case _ => println("not found")
| }
xyz

Cheers

Grzegorz Kossakowski
Joined: 2009-01-28,
User offline. Last seen 42 years 45 weeks ago.
Re: Pattern matching on strings

martin odersky pisze:
> I'd use a regex:
>
> scala> val re1 = "abc(.*)".r
> re1: scala.util.matching.Regex = abc(.*)
>
> scala> "abcxyz" match {
> | case re1(x) => println(x)
> | case _ => println("not found")
> | }
> xyz

If I want to check what kind of suffix I've got I should use guard in case statement, right?

Lauri Alanko
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Pattern matching on strings

On Mon, Mar 16, 2009 at 08:21:48PM +0100, martin odersky wrote:
> scala> val re1 = "abc(.*)".r
> re1: scala.util.matching.Regex = abc(.*)
>
> scala> "abcxyz" match {
> | case re1(x) => println(x)
> | case _ => println("not found")
> | }
> xyz

Isn't this (along with other similar examples) a compelling reason to
allow some way for an expression to stand for a StableId without
having to bind it to a temporary name somewhere far away?

Lauri

Derek Chen-Becker
Joined: 2008-12-16,
User offline. Last seen 42 years 45 weeks ago.
Re: Pattern matching on strings

Grzegorz Kossakowski wrote:
> If I want to check what kind of suffix I've got I should use guard in case statement, right?
>

Actually, since it's a match statement, you can use literals to match
groupings:

scala> val reg = "abc:(.*):(.*)".r
reg: scala.util.matching.Regex = abc:(.*):(.*)

scala> "abc:xyz:123" match {
| case reg("def", x) => print("DEF!")
| case reg("xyz", y) => print("xyz=>" + y)
| case reg(x, y) => print(x + ":" + y)
| }
xyz=>123

scala>

Grzegorz Kossakowski
Joined: 2009-01-28,
User offline. Last seen 42 years 45 weeks ago.
Re: Pattern matching on strings

Derek Chen-Becker pisze:
> Grzegorz Kossakowski wrote:
>> If I want to check what kind of suffix I've got I should use guard in case statement, right?
>>
>
> Actually, since it's a match statement, you can use literals to match
> groupings:
>
> scala> val reg = "abc:(.*):(.*)".r
> reg: scala.util.matching.Regex = abc:(.*):(.*)
>
> scala> "abc:xyz:123" match {
> | case reg("def", x) => print("DEF!")
> | case reg("xyz", y) => print("xyz=>" + y)
> | case reg(x, y) => print(x + ":" + y)
> | }
> xyz=>123
>
> scala>

I didn't think about it this way. This looks sweet.

Thanks for all suggestions. I'll pick this one as it seems to closest to what I wanted to achieve.

odersky
Joined: 2008-07-29,
User offline. Last seen 45 weeks 6 days ago.
Re: Pattern matching on strings

> Isn't this (along with other similar examples) a compelling reason to
> allow some way for an expression to stand for a StableId without
> having to bind it to a temporary name somewhere far away?

Maybe. The problem is how to distinguish between in and out parameters. I.e. in

case re1(x) =>

(x) is a bound variable, not an in-parameter. There are of course ways
to specify a disambiguation, for instance, you could say that in

case f(args1)...(argsN) =>

all but the last argument list are in-parameters whereas the last
argument list contains pattern bound variables. It's possible to do
this, but the question is whether it's worth the complications, and
whether it's clear enough for readers.

Cheers

Lauri Alanko
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Pattern matching on strings

On Tue, Mar 17, 2009 at 08:23:57PM +0100, martin odersky wrote:
> > Isn't this (along with other similar examples) a compelling reason to
> > allow some way for an expression to stand for a StableId without
> > having to bind it to a temporary name somewhere far away?
>
> Maybe. The problem is how to distinguish between in and out parameters.

In https://lampsvn.epfl.ch/trac/scala/ticket/785 I suggested that an
expression-as-StableId in a pattern could be indicated by wrapping the
expression in brackets. Hence, your example would be written as:

"abcxyz" match {
case {"abc(.*)".r}(x) => println(x)
case _ => println("not found")
}

To me this syntax extension wouldn't seem to be too intrusive.

Lauri

odersky
Joined: 2008-07-29,
User offline. Last seen 45 weeks 6 days ago.
Re: Pattern matching on strings

On Tue, Mar 17, 2009 at 8:47 PM, Lauri Alanko wrote:
> On Tue, Mar 17, 2009 at 08:23:57PM +0100, martin odersky wrote:
>> > Isn't this (along with other similar examples) a compelling reason to
>> > allow some way for an expression to stand for a StableId without
>> > having to bind it to a temporary name somewhere far away?
>>
>> Maybe. The problem is how to distinguish between in and out parameters.
>
> In https://lampsvn.epfl.ch/trac/scala/ticket/785 I suggested that an
> expression-as-StableId in a pattern could be indicated by wrapping the
> expression in brackets. Hence, your example would be written as:
>
> "abcxyz" match {
>  case {"abc(.*)".r}(x) => println(x)
>  case _                => println("not found")
> }
>
Yes, maybe. I fear for other readers it would look strange. I am not
sufficiently convinced yet it's a win, and also want to stop adding to
the syntax of Scala for a while.

Cheers

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland