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

Re: Private vals and case classes (SI-5407)

6 replies
extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.

On Wed, Jan 25, 2012 at 9:26 AM, Grzegorz Kossakowski
wrote:
> Oh, I forgot that custom-defined extractor are not handled the same way
> as synthesized ones. Now it makes sense even if it's really unfortunate.

BTW I had a pretty brilliant idea which I told adriaan about but not others, so:

The reason extractors are slow is that the interface is impoverished.
There is no way to find out anything about an extractor without
calling it, requiring 100% of the extractor logic to run, requiring
successful matches to be wrapped in a Some, and then decomposing the
option.

What if we gave ourselves this.

object :: {
def isUndefinedAt(x: Any) = x.isInstanceOf[List[_]]
def unapply_1[T](x: List[T]): T = x.hd
def unapply_2[T](xs: List[T]): List[T] = xs.tl
}

(It doesn't actually have to be called "isUndefinedAt", I just think
it's funny.)

Now you can write extractors for arbitrary, non-case classes - even
ones you can't control, like String - with something close to zero
performance penalty relative to case classes. The unapply_N methods
throw an exception if called with something which doesn't match, so no
Option is needed there. We could do this right now with no particular
difficulty.

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Private vals and case classes (SI-5407)

2012/1/25 √iktor Ҡlang :
>   val unapply = { case x: List[_] => x }

That's not an extractor, that's a type test.

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Private vals and case classes (SI-5407)

2012/1/25 √iktor Ҡlang :
> Is the possibilities for recursion killing this baby?

BTW, the possibility of recursion already kills babies.

object IntMap {
private[immutable] case object Nil extends IntMap[Nothing] {
// Important! Without this equals method in place, an infinite
// loop from Map.equals => size => pattern-match-on-Nil => equals
// develops. Case objects and custom equality don't mix without
// careful handling.
override def equals(that : Any) = that match {
case _: this.type => true
case _: IntMap[_] => false // The only empty IntMaps are eq Nil
case _ => super.equals(that)
}
}
}

Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: Private vals and case classes (SI-5407)


On Wed, Jan 25, 2012 at 6:35 PM, Paul Phillips <paulp [at] improving [dot] org> wrote:
On Wed, Jan 25, 2012 at 9:26 AM, Grzegorz Kossakowski
<grzegorz [dot] kossakowski [at] gmail [dot] com> wrote:
> Oh, I forgot that custom-defined extractor are not handled the same way
> as synthesized ones. Now it makes sense even if it's really unfortunate.

BTW I had a pretty brilliant idea which I told adriaan about but not others, so:

The reason extractors are slow is that the interface is impoverished.
There is no way to find out anything about an extractor without
calling it, requiring 100% of the extractor logic to run, requiring
successful matches to be wrapped in a Some, and then decomposing the
option.

What if we gave ourselves this.

object :: {
 def isUndefinedAt(x: Any) = x.isInstanceOf[List[_]]
 def unapply_1[T](x: List[T]): T = x.hd
 def unapply_2[T](xs: List[T]): List[T] = xs.tl
}

(It doesn't actually have to be called "isUndefinedAt", I just think
it's funny.)

Now you can write extractors for arbitrary, non-case classes - even
ones you can't control, like String - with something close to zero
performance penalty relative to case classes.  The unapply_N methods
throw an exception if called with something which doesn't match, so no
Option is needed there.  We could do this right now with no particular
difficulty.

Is the possibilities for recursion killing this baby?
object :: {  val unapply = { case x: List[_] => x }}

--
Viktor Klang

Akka Tech LeadTypesafe - The software stack for applications that scale

Twitter: @viktorklang
Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: Private vals and case classes (SI-5407)

Point was to use partial functions instead of method w. Option return type.

On Jan 25, 2012 6:40 PM, "Paul Phillips" <paulp [at] improving [dot] org> wrote:
2012/1/25 √iktor Ҡlang <viktor [dot] klang [at] gmail [dot] com>:
>   val unapply = { case x: List[_] => x }

That's not an extractor, that's a type test.
extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Private vals and case classes (SI-5407)

2012/1/25 √iktor Ҡlang :
> Point was to use partial functions instead of method w. Option return type.

You can define them that way already.

class Extractor[T, R](pf: PartialFunction[T, R]) { def unapply(x: T)
= pf lift x }
val unapply = new Extractor[Any, (Any, Any)]({ case xs: List[_] =>
((xs.head, xs.tail.head)) })

println(List(1, 2, 3) match { case unapply(x: Int, y: Int) => x + y })

Maybe I still don't understand you, but partial functions don't offer
anything we don't have already. The key aspect of unapply_1,
unapply_2, etc. is that you can obtain the individual product elements
directly and without wrapping.

d_m
Joined: 2010-11-11,
User offline. Last seen 35 weeks 2 days ago.
Re: Private vals and case classes (SI-5407)

On Wed, Jan 25, 2012 at 09:35:07AM -0800, Paul Phillips wrote:
> Now you can write extractors for arbitrary, non-case classes - even
> ones you can't control, like String - with something close to zero
> performance penalty relative to case classes. The unapply_N methods
> throw an exception if called with something which doesn't match, so no
> Option is needed there. We could do this right now with no particular
> difficulty.

This sounds great! It would be awesome to reduce/eliminate the boxing
that extractors currently have to do.

+100

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