Helper for lifting PartialFunction

112 views
Skip to first unread message

Alois Cochard

unread,
Dec 12, 2012, 9:25:29 AM12/12/12
to scala-...@googlegroups.com
Hi folks,

I write very often code like this:

def myFunction(x: Foo) = x.field match {
  case "a" => Some(Bar0(x))
  case "b" => Some(Bar1(x))
  case _ => None
}


And this give me the feeling of repeating myself, so I wrote this little helper function:

def f[A, B](x: A)(f: PartialFunction[A, B]): Option[B] = if (f.isDefinedAt(x)) Some(f(x)) else None 


So now I can write something like that:

def myFunction(x: Foo) = f(x.field)(_ match {
  case "a" => Some(Bar0(x))
  case "b" => Some(Bar1(x))
})


This sounds quite basic, and useful to reduce boilerplate, but I wasn't able to find something like that in stdlib, am I missing something? would worth an addition or there is a better way?

I tried using PartialFunction.lift ... but unfortunately I can't get it inferring type nicely so I end with less readable code.

Cheers

Alois Cochard




Jason Zaugg

unread,
Dec 12, 2012, 9:33:36 AM12/12/12
to Alois Cochard, scala-...@googlegroups.com


On Wednesday, December 12, 2012, Alois Cochard wrote:
Hi folks,

I write very often code like this:

def myFunction(x: Foo) = x.field match {
  case "a" => Some(Bar0(x))
  case "b" => Some(Bar1(x))
  case _ => None
}

scala> import PartialFunction._
import PartialFunction._

scala> condOpt(0) { case 0 | 1 | 2 => "low" } 
res4: Option[java.lang.String] = Some(low)

And relatedly:

scala> cond(0) { case -1 => false; case 0 | 1 | 2 => true } 
res7: Boolean = true

scala> cond(99) { case -1 => false; case 0 | 1 | 2 => true } 
res8: Boolean = false

-jason 

Simon Schäfer

unread,
Dec 12, 2012, 9:33:46 AM12/12/12
to scala-...@googlegroups.com
What about PartialFunction.condOpt?

On Wed 12 Dec 2012 03:25:29 PM CET, Alois Cochard wrote:
> Hi folks,
>
> I write very often code like this:
>
> /def myFunction(x: Foo) = x.field match {/
> / case "a" => Some(Bar0(x))/
> / case "b" => Some(Bar1(x))/
> / case _ => None/
> /}/
>
>
> And this give me the feeling of repeating myself, so I wrote this
> little helper function:
>
> /def f[A, B](x: A)(f: PartialFunction[A, B]): Option[B] = if
> (f.isDefinedAt(x)) Some(f(x)) else None /
> /
> /
>
> So now I can write something like that:
>
> /def myFunction(x: Foo) = f(x.field)(_ match {/
> / case "a" => Some(Bar0(x))/
> / case "b" => Some(Bar1(x))/
> /})/
>
>
> This sounds quite basic, and useful to reduce boilerplate, but I
> wasn't able to find something like that in stdlib, am I missing
> something? would worth an addition or there is a better way?
>
> I tried using PartialFunction.lift ... but unfortunately I can't get
> it inferring type nicely so I end with less readable code.
>
> Cheers
>
> Alois Cochard
> /
> /
>
>
>

Mirko Stocker

unread,
Dec 12, 2012, 9:34:36 AM12/12/12
to scala-...@googlegroups.com
On Wednesday 12 December 2012 06:25:29 Alois Cochard wrote:
> This sounds quite basic, and useful to reduce boilerplate, but I wasn't able
> to find something like that in stdlib, am I missing something? would worth
> an addition or there is a better way?

Have you seen PartialFunction.condOpt? It seems to provide what you need:

PartialFunction.condOpt(x.field) {
case "a" => Bar0(x)
case "b" => Bar1(x)
}

Cheers

Mirko

--
Mirko Stocker | m...@misto.ch
Work: http://ifs.hsr.ch | http://infoq.com
Personal: http://misto.ch | http://twitter.com/m_st

Jason Zaugg

unread,
Dec 12, 2012, 9:40:47 AM12/12/12
to Alois Cochard, scala-...@googlegroups.com
On Wed, Dec 12, 2012 at 3:33 PM, Jason Zaugg <jza...@gmail.com> wrote:
scala> condOpt(0) { case 0 | 1 | 2 => "low" } 
res4: Option[java.lang.String] = Some(low)

BTW, Scalex can find these things even faster than Simon, Mirko or I :)


-jason

Jason Zaugg

unread,
Dec 12, 2012, 9:41:29 AM12/12/12
to Alois Cochard, scala-...@googlegroups.com
On Wed, Dec 12, 2012 at 3:40 PM, Jason Zaugg <jza...@gmail.com> wrote:
BTW, Scalex can find these things even faster than Simon, Mirko or I :)

Alois Cochard

unread,
Dec 12, 2012, 9:47:55 AM12/12/12
to scala-...@googlegroups.com
Thanks guys, exactly that!

I'll try to get the "Scalex" reflex ;)

soul...@gmail.com

unread,
Dec 12, 2012, 9:48:18 AM12/12/12
to Mirko Stocker, scala-...@googlegroups.com
The name could be a bit more intention-revealing! Or am I missing something that makes the name clear?
Sent from my BlackBerry® wireless device

Paul Phillips

unread,
Dec 12, 2012, 9:53:54 AM12/12/12
to soul...@gmail.com, Mirko Stocker, scala-...@googlegroups.com

On Wed, Dec 12, 2012 at 6:48 AM, <soul...@gmail.com> wrote:
The name could be a bit more intention-revealing! Or am I missing something that makes the name clear?

No, they're just badly named. It's not my finest hour.

Daniel Sobral

unread,
Dec 12, 2012, 10:08:21 AM12/12/12
to Paul Phillips, soul...@gmail.com, Mirko Stocker, scala-debate
I never thought their problem was so much of name, but of where they have been put. I've never thought of either better names or better place to put them either, so I kept my mouth shut. Besides, the usual result of any controversy is the exclusion of the feature, which would be the worst result.


--
Daniel C. Sobral

I travel to the future all the time.

Alois Cochard

unread,
Dec 12, 2012, 10:47:00 AM12/12/12
to Daniel Sobral, Paul Phillips, soul...@gmail.com, Mirko Stocker, scala-debate
Would love to see it in Predef as I'll use it often, but I can easily live with import PartialFunction._

Chris Marshall

unread,
Dec 19, 2012, 10:02:32 AM12/19/12
to dcso...@gmail.com, scala-...@googlegroups.com
It belongs on a wrapper around any type, no? If this was in scalaz6, it would be in Identity:

scala> implicit class Identity[A](a: A) {
     |      def optionally[B](pf: PartialFunction[A, B]): Option[B] = pf.lift.apply(a) 
     |     }
defined class Identity

scala> 1.optionally { case i if i > 3 => i.toString + " foo" }
res0: Option[String] = None

scala> 1.optionally { case i if i > 0 => i.toString + " foo" }
res1: Option[String] = Some(1 foo)


From: dcso...@gmail.com
Date: Wed, 12 Dec 2012 13:08:21 -0200

Subject: Re: [scala-debate] Helper for lifting PartialFunction

Chris Marshall

unread,
Dec 19, 2012, 10:29:25 AM12/19/12
to dcso...@gmail.com, scala-...@googlegroups.com
Or perhaps more generally (using scalaz):

scala> implicit class Id0[A](a: A) {
     | class Lifter[M[_]: Pure] {
     |   def partially[B](pf: PartialFunction[A, B])(implicit E: Empty[M]) = pf.lift(a) map (b => implicitly[Pure[M]].pure(b)) getOrElse E.empty[B]
     |   def totally: M[A] = implicitly[Pure[M]].pure(a)
     | }
     | def liftInto[M[_]: Pure] = new Lifter[M]
     | def liftIntoOption = liftInto[Option]
     | }


scala> 4.liftIntoOption.partially { case i if i > 3 => i.toString + " foo" }
res6: Option[java.lang.String] = Some(4 foo)

scala> 4.liftInto[Stream].partially { case i if i > 3 => i.toString + " bar" }
res9: Stream[java.lang.String] = Stream(4 bar, ?)

scala> 2.liftInto[List].partially { case i if i > 3 => i.toString + " bat" }
res10: List[java.lang.String] = List()



From: oxbow...@hotmail.com
To: dcso...@gmail.com; scala-...@googlegroups.com
Subject: RE: [scala-debate] Helper for lifting PartialFunction
Date: Wed, 19 Dec 2012 15:02:32 +0000
Reply all
Reply to author
Forward
0 new messages