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

Addicted to Pattern Matching

19 replies
kolotyluk
Joined: 2010-06-04,
User offline. Last seen 5 weeks 15 hours ago.

When I first started trying to learn Scala a few years ago there was so
much hype in the documentation about how wonderful pattern matching was,
but I didn't really pay much attention to it as I could not get a feel
for the utility of it.

Now that I have been writing more product code in Scala, increasingly I
find myself using match/case so much now that I am getting addicted to
it. In fact I am increasingly finding new ways to make use of it and new
ways to structure my code to make better use of it - for example
creating case classes for function results.

Yesterday I started using regular expressions in Scala for the first
time, and I really like how well they work with match/case.

Another thing I really like is that pattern matching can improve the
readability of the code substantially. Sometimes if you take the time to
set up your pattern matching code the problem and solution just jump
right out at you.

One disappointment was I could not seem to get pattern matching to work
well with arrays, such as Array[String]. I found various examples on the
web, but could not seem to get any of them working. Fortunately
converting Array[String] to List[String] is trivial, and lists work
great with pattern matching. I always prefer working with lists, but all
programs start with main(arguments : Array[String]).

Has anyone else found themselves getting addicted to pattern matching?
Now when I promote Scala to others at work and elsewhere I'll be
spending more time on the joys of pattern matching.

Does anyone know of a really good treatment of pattern matching from the
basics to more sophisticated stuff - preferably with tons of examples?

Are there plans to add further enhancements to pattern matching in Scala?

Cheers, Eric

Adam Jorgensen
Joined: 2011-04-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Addicted to Pattern Matching
Pattern matching and case classes are awesome. 'Nuff said :-)

On 31 January 2012 10:40, Eric Kolotyluk <eric [dot] kolotyluk [at] gmail [dot] com> wrote:
When I first started trying to learn Scala a few years ago there was so much hype in the documentation about how wonderful pattern matching was, but I didn't really pay much attention to it as I could not get a feel for the utility of it.

Now that I have been writing more product code in Scala, increasingly I find myself using match/case so much now that I am getting addicted to it. In fact I am increasingly finding new ways to make use of it and new ways to structure my code to make better use of it - for example creating case classes for function results.

Yesterday I started using regular expressions in Scala for the first time, and I really like how well they work with match/case.

Another thing I really like is that pattern matching can improve the readability of the code substantially. Sometimes if you take the time to set up your pattern matching code the problem and solution just jump right out at you.

One disappointment was I could not seem to get pattern matching to work well with arrays, such as Array[String]. I found various examples on the web, but could not seem to get any of them working. Fortunately converting Array[String] to List[String] is trivial, and lists work great with pattern matching. I always prefer working with lists, but all programs start with main(arguments : Array[String]).

Has anyone else found themselves getting addicted to pattern matching? Now when I promote Scala to others at work and elsewhere I'll be spending more time on the joys of pattern matching.

Does anyone know of a really good treatment of pattern matching from the basics to more sophisticated stuff - preferably with tons of examples?

Are there plans to add further enhancements to pattern matching in Scala?

Cheers, Eric

Simon Ochsenreither
Joined: 2011-07-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Addicted to Pattern Matching
I have never been a fan of it. Couldn't care less if it was removed in Scala 3.

In my opinion the three most over-hyped features of Scala are Enumerations, Pattern Matching and Actors and the amount of bugs associated with them is just terrifying.
odersky
Joined: 2008-07-29,
User offline. Last seen 45 weeks 6 days ago.
Re: Re: Addicted to Pattern Matching

On Tue, Jan 31, 2012 at 12:32 PM, Simon Ochsenreither
wrote:
> I have never been a fan of it. Couldn't care less if it was removed in Scala
> 3.
>
> In my opinion the three most over-hyped features of Scala are Enumerations,
> Pattern Matching and Actors and the amount of bugs associated with them is
> just terrifying.

2.10 will have the new pattern matcher and akka as a go-forward
alternative for actors. I am not sure there are open enumeration bugs
in trunk. If there are we should fix them before 2.10 comes out.

So the future looks bright :-)

Cheers

Chris Twiner
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Addicted to Pattern Matching

On Tue, Jan 31, 2012 at 12:32 PM, Simon Ochsenreither
wrote:
> I have never been a fan of it. Couldn't care less if it was removed in Scala
> 3.
>
> In my opinion the three most over-hyped features of Scala are Enumerations,
> Pattern Matching and Actors and the amount of bugs associated with them is
> just terrifying.

heresy :-)

you can take the other two (although I never remember hype around
Enumerations, adts yes but never those since 2.6), I'm also more than
happy to see by-names disappear and have Function0 take their
place,.....

but pattern matching must be pried from my long dead cold hands. (I
say that as one who doesn't pattern match much, but when I do its a
godsend - there is a meme poster in that)

E. Labun
Joined: 2010-06-20,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Addicted to Pattern Matching

On 2012-01-31 12:39, martin odersky wrote:
> 2.10 will have the new pattern matcher

What will be different in the new pattern matcher?

Thank you,
EL

fanf
Joined: 2009-03-17,
User offline. Last seen 2 years 30 weeks ago.
Re: Re: Addicted to Pattern Matching

On 31/01/2012 14:33, Eugen Labun wrote:
> On 2012-01-31 12:39, martin odersky wrote:
>> 2.10 will have the new pattern matcher
>
> What will be different in the new pattern matcher?

It's virtual, so maybe it will help :)

More seriously, what I know is that it will be simpler to test and
update, and will allow to solve really old bug on the pattern matcher.

There was some discussion about it in the Scala developer list, but as
it seems to be of some interest for the community, perhaps it will be
really cool to have a blog post or a paper about it ?

Cheers,

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Re: Addicted to Pattern Matching

On Tue, Jan 31, 2012 at 11:33, Eugen Labun wrote:
> On 2012-01-31 12:39, martin odersky wrote:
>>
>> 2.10 will have the new pattern matcher
>
>
> What will be different in the new pattern matcher?

The implementation. It abstracts pattern matching in terms of
flatMap/orElse, just like for-comprehensions are implemented in terms
of flatMap/map/foreach/withFilter. In its current implementation, it
uses Option to implement the matching, and optimizes it down to
if/else or switch. One can provide an alternative to Option, though,
which enables some interesting stuff.

gkossakowski
Joined: 2010-03-11,
User offline. Last seen 33 weeks 5 days ago.
Re: Re: Addicted to Pattern Matching
On 31 January 2012 14:46, Francois <fanf42 [at] gmail [dot] com> wrote:
More seriously, what I know is that it will be simpler to test and update, and will allow to solve really old bug on the pattern matcher.

Yes, for the time being the most important fact: new pattern matcher implementation fixes lots of annoying bugs that people would regularly hit when using Lift, Dispatcher or even regexps.
--
Grzegorz Kossakowski

sreque 2
Joined: 2011-11-15,
User offline. Last seen 42 years 45 weeks ago.
Re: Addicted to Pattern Matching

How else do you data-oriented programming (fixed number of possibly
disjoint types, unlimited number of operations) well? I'll tell you
how I have to do it in C#. It's called the visitor pattern, and it's
so painful that no one uses it unless absolutely necessary. Pattern-
matching with sealed types opens up a whole new incredibly useful
programming style!

On Jan 31, 5:32 am, Simon Ochsenreither
wrote:
> I have never been a fan of it. Couldn't care less if it was removed in
> Scala 3.
>
> In my opinion the three most over-hyped features of Scala are Enumerations,
> Pattern Matching and Actors and the amount of bugs associated with them is
> just terrifying.

kolotyluk
Joined: 2010-06-04,
User offline. Last seen 5 weeks 15 hours ago.
Re: Addicted to Pattern Matching

OK, I will just have to assume Simon is being sarcastic and really does
love pattern matching.

I am so tired of the limitations of the C, C++, Java style switch
statement. In C# I cannot believe how many times I switch on String
cases - that small improvement is so incredibly useful. I am glad the
Java is finally catching up in this regard, but both Java and C# are a
far cry from Scala. Over the years I make much more use of switch in
Java than when I used to rely more on chains of if-then-else (which can
get really ugly).

It may be true there are bugs or other issues with pattern matching in
Scala, but I have not encountered them enough (if at all) to find it a
problem. I used the programming language SR over almost 20 years ago,
and I really love how well pattern matching work on events, but I have
not had a chance to do that sort of thing again until recently when
working with Scala. Now that I have been writing production code in
Scala, I just keep finding more an more situations where I can clean up
my code using match/case. Now it is becoming instictive and I write the
code first based on match/case instead of the result of refactoring.

When you think about it, one of the things the human brain is really
good at is pattern matching. One of the reasons I keep stressing that
there needs to be more good concrete examples of Scala code is that I
can often look a well written piece of code and more easily infer what
is going on than reading pages and pages of theory of how to write the
code. Oddly enough, in the past I have often had trouble understanding
people's example of pattern matching in Scala, but now that I have more
experience with it I am finding those example easier to understand.

When I first encountered recursion in University I had trouble
understanding examples of it, but the more I practiced writing code with
it, the more able I was to understand other people's examples.

For the most part I find pattern matching much easier to grok that many
of the sophisticated examples of FP I see in Scala, and I think people
who struggle with FP in Scala, might appreciate trying to master pattern
matching a little more as a way to offset any frustration with mastering FP.

Maybe one day you will be able to do Prolog type stuff in Scala with
pattern matching. I jest of course :-)

Cheers, Eric

On 2012-01-31 3:32 AM, Simon Ochsenreither wrote:
> I have never been a fan of it. Couldn't care less if it was removed in
> Scala 3.
>
> In my opinion the three most over-hyped features of Scala are
> Enumerations, Pattern Matching and Actors and the amount of bugs
> associated with them is just terrifying.

kolotyluk
Joined: 2010-06-04,
User offline. Last seen 5 weeks 15 hours ago.
Re: Addicted to Pattern Matching - Array[String]

Does anyone have any good examples of how to use match/case with
Array[String] - or is it just best to always convert Array[String] to
List[String]?

Cheers, Eric

kolotyluk
Joined: 2010-06-04,
User offline. Last seen 5 weeks 15 hours ago.
Re: Addicted to Pattern Matching - Error Results

One of the things I often do now is write functions that return a case
class ReturnResult, with subclasses NormalResult and ErrorResult. Then I
can write code like

fn(foo) match {
case NormalResult(blah) =>
case ErrorResult(blah) = >

While in many cases it is best to throw an exception, often this
return-result pattern works best for me, especially when I am
'scripting' and error results are just as likely as normal results. When
error results are less likely then I tend to prefer exceptions and try
blocks.

Does anyone else have any opinions on this?

Cheers, Eric

sreque 2
Joined: 2011-11-15,
User offline. Last seen 42 years 45 weeks ago.
Re: Addicted to Pattern Matching - Error Results

I think for this particular case, where a function can return either
of two values, people usually prefer using class Either or Scalaz's
Validation. That way, you don't have to create boilerplate case
classes each time you want to use this pattern. I actually took the
time to write an Either class in C#, which, even without pattern
matching or good ways of composing functions, has turned out to be
pretty handy. I still have a hard time structuring my programs
functionally with them or structuring all my code inside of a
Validation monad. For instance, In C#, the boiler plate required to
use the ValidationNEL applicative functor to accumulate errors is
pretty painful, especially as their is no type inference for Lambdas
except when passed as a function argument. Also, C#'s type inference
in general isn't nearly as good as Scala's, doesn't have a bottom
type, and, in 3.5, at least, doesn't have type variance to make life
easier. Even with all that, I still like using Eithers! :)

On Jan 31, 8:39 pm, Eric Kolotyluk wrote:
> One of the things I often do now is write functions that return a case
> class ReturnResult, with subclasses NormalResult and ErrorResult. Then I
> can write code like
>
>     fn(foo) match {
>       case NormalResult(blah) =>
>       case ErrorResult(blah) = >
>
> While in many cases it is best to throw an exception, often this
> return-result pattern works best for me, especially when I am
> 'scripting' and error results are just as likely as normal results. When
> error results are less likely then I tend to prefer exceptions and try
> blocks.
>
> Does anyone else have any opinions on this?
>
> Cheers, Eric

Seth Tisue
Joined: 2008-12-16,
User offline. Last seen 34 weeks 3 days ago.
Re: Re: Addicted to Pattern Matching - Array[String]

On Tue, Jan 31, 2012 at 8:32 PM, Eric Kolotyluk
wrote:
> Does anyone have any good examples of how to use match/case with
> Array[String] - or is it just best to always convert Array[String] to
> List[String]?

What are you trying to do that doesn't work? Here's some simple things
that work:

Welcome to Scala version 2.9.1.final

scala> Array(1, 2, 3) match {
| case Array(x, y, z) => (x, y, z)
| }
res0: (Int, Int, Int) = (1,2,3)

scala> Array(4, 5, 6) match {
| case Array(_, z @ _*) => z
| }
res1: Seq[Int] = Vector(5, 6)

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Re: Addicted to Pattern Matching - Error Results

On Wed, Feb 1, 2012 at 00:39, Eric Kolotyluk wrote:
> One of the things I often do now is write functions that return a case class
> ReturnResult, with subclasses NormalResult and ErrorResult. Then I can write
> code like
>
>   fn(foo) match {
>     case NormalResult(blah) =>
>     case ErrorResult(blah) = >
>
> While in many cases it is best to throw an exception, often this
> return-result pattern works best for me, especially when I am 'scripting'
> and error results are just as likely as normal results. When error results
> are less likely then I tend to prefer exceptions and try blocks.
>
> Does anyone else have any opinions on this?

That's Either, without type erasure. There's certainly an advantage to
not having type erasure, in particular Either's type parameters are
type constructors themselves. For example:

// works
(either: Either[String, Int]) match {
case Right(n: Int) => // this is the "right" case, and we can reify n's type
case Left(error: String) => // this is the exception case, and we
can reify error's type too
}

/ doesn't work
(either: Either[String, List[Int]]) match {
case Left(list: List[_]) => // can't reify list's type
case _ =>
}

So, while Either's pattern is nice, it's seriously constrained by type erasure.

Also, its methods make using it on for-comprehensions very awkward.
For an example of how to do it better, see Parsers.ParseResult, or, of
course, Scalaz Validation. While Validation is somewhat verbose, it's
definitely one of Scalaz gateway drugs.

kolotyluk
Joined: 2010-06-04,
User offline. Last seen 5 weeks 15 hours ago.
Re: Re: Addicted to Pattern Matching - Array[String]

On 2012-01-31 10:46 PM, Seth Tisue wrote:
> On Tue, Jan 31, 2012 at 8:32 PM, Eric Kolotyluk
> wrote:
>> Does anyone have any good examples of how to use match/case with
>> Array[String] - or is it just best to always convert Array[String] to
>> List[String]?
> What are you trying to do that doesn't work? Here's some simple things
> that work:
>
> Welcome to Scala version 2.9.1.final
>
> scala> Array(1, 2, 3) match {
> | case Array(x, y, z) => (x, y, z)
> | }
> res0: (Int, Int, Int) = (1,2,3)
>
> scala> Array(4, 5, 6) match {
> | case Array(_, z @ _*) => z
> | }
> res1: Seq[Int] = Vector(5, 6)
>
I was trying to match a regex in one of the Array positions like

scala> val help = "help".r
help: scala.util.matching.Regex = help

scala> val c1 = Array("help")
c1: Array[java.lang.String] = Array(help)

scala> c1 match {
| case Array(help(_)) => println("ok")
| case _ => println("nope")
| }
nope

Is there a way to capture the tail of the array too?

Cheers, Eric

kolotyluk
Joined: 2010-06-04,
User offline. Last seen 5 weeks 15 hours ago.
Re: Re: Addicted to Pattern Matching - Error Results

On 2012-02-01 4:15 AM, Daniel Sobral wrote:
> On Wed, Feb 1, 2012 at 00:39, Eric Kolotyluk wrote:
>> One of the things I often do now is write functions that return a case class
>> ReturnResult, with subclasses NormalResult and ErrorResult. Then I can write
>> code like
>>
>> fn(foo) match {
>> case NormalResult(blah) =>
>> case ErrorResult(blah) =>
>>
>> While in many cases it is best to throw an exception, often this
>> return-result pattern works best for me, especially when I am 'scripting'
>> and error results are just as likely as normal results. When error results
>> are less likely then I tend to prefer exceptions and try blocks.
>>
>> Does anyone else have any opinions on this?
> That's Either, without type erasure. There's certainly an advantage to
> not having type erasure, in particular Either's type parameters are
> type constructors themselves. For example:
>
> // works
> (either: Either[String, Int]) match {
> case Right(n: Int) => // this is the "right" case, and we can reify n's type
> case Left(error: String) => // this is the exception case, and we
> can reify error's type too
> }
>
>
> / doesn't work
> (either: Either[String, List[Int]]) match {
> case Left(list: List[_]) => // can't reify list's type
> case _ =>
> }
>
> So, while Either's pattern is nice, it's seriously constrained by type erasure.
>
> Also, its methods make using it on for-comprehensions very awkward.
> For an example of how to do it better, see Parsers.ParseResult, or, of
> course, Scalaz Validation. While Validation is somewhat verbose, it's
> definitely one of Scalaz gateway drugs.
>

Here is one common way I use Error Results

val dropCommand = List("psql", "-U", "postgres", "-c", "DROP
DATABASE " + database + ";")

Run(dropCommand) match {
case NormalResult(process, outLines, errLines) =>
if (!errLines.isEmpty) {
emit("psql errors:")
emit(errLines)
}
if (!outLines.isEmpty) {
emit("psql output:")
emit(outLines)
}
return true
case ErrorResult(process, outLines, errLines) =>
emitError("psql exitValue = " + process.exitValue)
if (!errLines.isEmpty) {
emitError("psql errors:")
emitError(errLines)
// Succeed if the database does not exist
if (errLines.contains("database \"" + database + "\" does
not exist")) return true
}
if (!outLines.isEmpty) {
emitError("psql output:")
emitError(outLines)
}
}

While (I think) my code is fairly clear, it is more verbose than I would
like. How would Either make this better?

Cheers, Eric

Ryan Hendrickson
Joined: 2012-02-01,
User offline. Last seen 42 years 45 weeks ago.
RE: Re: Addicted to Pattern Matching - Array[String]

> I was trying to match a regex in one of the Array positions like
>
> scala> val help = "help".r
> help: scala.util.matching.Regex = help
>
> scala> val c1 = Array("help")
> c1: Array[java.lang.String] = Array(help)
>
> scala> c1 match {
> | case Array(help(_)) => println("ok")
> | case _ => println("nope")
> | }
> nope

The help regex doesn't have any capturing groups, which is why help(_) won't match anything. Try:

c1 match {
case Array(help()) => println("ok")
}

----------------------------------------

This message is intended exclusively for the individual(s) or entity to
which it is addressed. It may contain information that is proprietary,
privileged or confidential or otherwise legally exempt from disclosure.
If you are not the named addressee, you are not authorized to read,
print, retain, copy or disseminate this message or any part of it.
If you have received this message in error, please notify the sender
immediately by e-mail and delete all copies of the message.

adriaanm
Joined: 2010-02-08,
User offline. Last seen 31 weeks 4 days ago.
Re: Re: Addicted to Pattern Matching


On Wed, Feb 1, 2012 at 3:29 AM, Eric Kolotyluk <eric [dot] kolotyluk [at] gmail [dot] com> wrote:
Maybe one day you will be able to do Prolog type stuff in Scala with pattern matching. I jest of course :-)
this is exactly what the "virtual" part of the virtualized pattern matcher enables :-)
plug in LogicT instead of Option, et voila! (this is a ways down on my TODO list, but "should work" now (i.e., haven't tested it), and *will* work after higher-priority issues have been sorted out)
There will be blog posts and documentation about this, it's somewhere between "excise remaining dependencies on old pattern matcher" and "experiment with other zero-plus monads" on my TODO list. Think ScalaDays as a timeframe.
adriaan

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