- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Manifest, implicits and apply for DSL
Fri, 2009-03-06, 23:38
Dear Scala Fellows!
In a Scala DSL, I want to be able to write
withClass [String]
and
withClass [String] {
// ...
}
I want avoid to write classOf[...] all the time. The first one is
quite easy to implement:
def withClass[A](implicit clazz: scala.reflect.Manifest[A])
However, I have some trouble solving the 2nd one. I tried the
following solutions, none of them worked:
(1) Overloading the withClass method
def withClass[A](implicit clazz: scala.reflect.Manifest[A])
def withClass[A](block: => Unit)(implicit clazz: scala.reflect.Manifest[A])
When calling without the block, the Scala compiler does not know it I
want to call the non-block method or if I want to partially apply the
with-block method.
(2) Returning an object with an apply method
class Helper {
def apply(block: => Unit) = {...}
}
def withClass[A](implicit clazz: scala.reflect.Manifest[A]) = {
new Helper
}
When I try to pass the block, the scala compiler thinks that I want to
pass the block as the scala.reflect.Manifest parameter. Directly
calling apply works:
withClass [String].apply {
// ...
}
What else can I do?
Cheers,
Roman
Mon, 2009-03-09, 05:37
#2
Re: Manifest, implicits and apply for DSL
Actually, there may be an option 4) wait for Default Arguments (https://lampsvn.epfl.ch/trac/scala/export/16712/lamp-sip/named-args/sip.xhtml)
Though even then the syntax would not be exactly as you'd like.
--j
On Sun, Mar 8, 2009 at 9:19 PM, Jorge Ortiz <jorge.ortiz@gmail.com> wrote:
Though even then the syntax would not be exactly as you'd like.
--j
On Sun, Mar 8, 2009 at 9:19 PM, Jorge Ortiz <jorge.ortiz@gmail.com> wrote:
3) Use different method names.
On Fri, Mar 6, 2009 at 3:37 PM, Roman Roelofsen <roman.roelofsen@googlemail.com> wrote:
Dear Scala Fellows!
In a Scala DSL, I want to be able to write
withClass [String]
and
withClass [String] {
// ...
}
I want avoid to write classOf[...] all the time. The first one is
quite easy to implement:
def withClass[A](implicit clazz: scala.reflect.Manifest[A])
However, I have some trouble solving the 2nd one. I tried the
following solutions, none of them worked:
(1) Overloading the withClass method
def withClass[A](implicit clazz: scala.reflect.Manifest[A])
def withClass[A](block: => Unit)(implicit clazz: scala.reflect.Manifest[A])
When calling without the block, the Scala compiler does not know it I
want to call the non-block method or if I want to partially apply the
with-block method.
(2) Returning an object with an apply method
class Helper {
def apply(block: => Unit) = {...}
}
def withClass[A](implicit clazz: scala.reflect.Manifest[A]) = {
new Helper
}
When I try to pass the block, the scala compiler thinks that I want to
pass the block as the scala.reflect.Manifest parameter. Directly
calling apply works:
withClass [String].apply {
// ...
}
What else can I do?
Cheers,
Roman
Tue, 2009-03-10, 16:47
#3
Flagging Uniques
Scalars,
Behold the following code for finding a an array of Booleans that flag the first unique occurrence of each element of a sequence:
val seq: Seq[T]
val set = new HashSet[T]
val unique = for (v<-seq) yield if (set.contains(v)) false else { set += v; true }
It works, and is reasonably concise, but not exactly elegant. Just look at that ugly mutable set!
What would be a more functional way to do this? I have tried some ideas, but none came out more elegant than the above.
Andreas
Tue, 2009-03-10, 17:47
#4
Re: Flagging Uniques
What you're doing is essentially a fold with a List[Boolean] and a Set[T] as carryover... both of which can be immutable.
case class Carry[T](val list: List[Boolean], val set: Set[T])
val seq: Seq[Int] = List(1,2,3,1,2,3)
seq.foldLeft(Carry(Nil, Set[Int]())) { (carry, x) =>
Carry(!carry.set.contains(x) :: carry.list, carry.set + x)
}.list.reverse
result: List[Boolean] = List(true, true, true, false, false, false)
alex
On Tue, Mar 10, 2009 at 8:41 AM, Windemuth Andreas <windemut@yahoo.com> wrote:
case class Carry[T](val list: List[Boolean], val set: Set[T])
val seq: Seq[Int] = List(1,2,3,1,2,3)
seq.foldLeft(Carry(Nil, Set[Int]())) { (carry, x) =>
Carry(!carry.set.contains(x) :: carry.list, carry.set + x)
}.list.reverse
result: List[Boolean] = List(true, true, true, false, false, false)
alex
On Tue, Mar 10, 2009 at 8:41 AM, Windemuth Andreas <windemut@yahoo.com> wrote:
Scalars,
Behold the following code for finding a an array of Booleans that flag the first unique occurrence of each element of a sequence:
val seq: Seq[T]
val set = new HashSet[T]
val unique = for (v<-seq) yield if (set.contains(v)) false else { set += v; true }
It works, and is reasonably concise, but not exactly elegant. Just look at that ugly mutable set!
What would be a more functional way to do this? I have tried some ideas, but none came out more elegant than the above.
Andreas
Tue, 2009-03-10, 17:57
#5
Re: Flagging Uniques
Windemuth Andreas wrote:
>
> Scalars,
>
> Behold the following code for finding a an array of Booleans that flag
> the first unique occurrence of each element of a sequence:
>
> val seq: Seq[T]
> val set = new HashSet[T]
> val unique = for (v<-seq) yield if (set.contains(v)) false else {
> set += v; true }
>
> It works, and is reasonably concise, but not exactly elegant. Just look
> at that ugly mutable set!
>
> What would be a more functional way to do this? I have tried some ideas,
> but none came out more elegant than the above.
Not very elegant and probably slow as hell, but it's stateless:
seq.foldLeft((new HashSet : Set[T], List[Boolean]()))((t, value) => if
(t._1.contains(value)) (t._1, false :: t._2) else (t._1 + value, true ::
t._2))._2.reverse
/Jesper Nordenberg
Tue, 2009-03-10, 18:07
#6
Re: Flagging Uniques
On Tue, Mar 10, 2009 at 09:43:43AM -0700, Alex Boisvert wrote:
> What you're doing is essentially a fold with a List[Boolean] and a
> Set[T] as carryover... both of which can be immutable.
Alex was faster, but since I just wrote the one liner I have to send it:
scala> val xs = List("a", "b", "c", "b", "a", "c", "d", "b")
xs: List[java.lang.String] = List(a, b, c, b, a, c, d, b)
scala> xs.foldLeft(List[(String, Boolean)]())((l, e) => (e, !l.map(_._1).contains(e)) :: l).reverseMap(_._2)
res1: List[Boolean] = List(true, true, true, false, false, false, true, false)
Tue, 2009-03-10, 18:27
#7
Re: Flagging Uniques
Hi Andreas,
just playing around giving another solution:
def flagSeq[T]( s: Seq[T] ): List[Boolean] = {
def loop( e: T, s: Seq[T] ): List[Boolean] = (if( s.isEmpty ) List(true) else
loop(s.first, s.drop(1)) + !s.contains(e))
val sRev = s.reverse
loop( sRev.first, sRev.drop(1) )
}
val seq: Seq[Int] = List(1,2,4,2,5,1,5)
val x = flagSeq( seq )
The difference is that I'm reversing the List first and look if the element is
contained in the tail. Though it's not yet tail-recursive...
Regards, --- Jan.
Tue, 2009-03-10, 19:17
#8
Re: Flagging Uniques
On Tue, Mar 10, 2009 at 08:41:33AM -0700, Windemuth Andreas wrote:
> What would be a more functional way to do this? I have tried some
> ideas, but none came out more elegant than the above.
OK, this is better. It would look so much prettier if type inference on
Nil could cast its gaze a little bit forward.
xs./:(List[Boolean](), Set[String]())((ls, e) =>
(!ls._2.contains(e) :: ls._1, ls._2 + e))._1.reverse
Imaginary version requiring both additional sugar for tuples as
parameters and slightly non-local inference:
xs /: (Nil, Nil) (((l1, l2), e) => (!l2.contains(e) :: l1, l2 + e)._1.reverse
Tue, 2009-03-10, 19:27
#9
RE: Flagging Uniques
Slow as anything, but I think correct, clear and tail-recursive
def flag(m:List[Int], seen:List[Int]):List[Boolean] = {
m match {
case Nil => Nil
case x::xs => !seen.contains(x)::flag(xs, x::seen)
}
}
Jim
-----Original Message-----
From: Jan Kriesten [mailto:kriesten@mail.footprint.de]
Sent: Tuesday, March 10, 2009 1:17 PM
To: Windemuth Andreas
Cc: Scala list
Subject: Re: [scala] Flagging Uniques
Hi Andreas,
just playing around giving another solution:
def flagSeq[T]( s: Seq[T] ): List[Boolean] = {
def loop( e: T, s: Seq[T] ): List[Boolean] = (if( s.isEmpty )
List(true) else loop(s.first, s.drop(1)) + !s.contains(e))
val sRev = s.reverse
loop( sRev.first, sRev.drop(1) )
}
val seq: Seq[Int] = List(1,2,4,2,5,1,5)
val x = flagSeq( seq )
The difference is that I'm reversing the List first and look if the
element is contained in the tail. Though it's not yet tail-recursive...
Regards, --- Jan.
PLEASE READ: This message is for the named person's use only. It may contain confidential, proprietary or legally privileged information. No confidentiality or privilege is waived or lost by any mistransmission. If you receive this message in error, please delete it and all copies from your system, destroy any hard copies and notify the sender. You must not, directly or indirectly, use, disclose, distribute, print, or copy any part of this message if you are not the intended recipient. Nomura Holding America Inc., Nomura Securities International, Inc, and their respective subsidiaries each reserve the right to monitor all e-mail communications through its networks. Any views expressed in this message are those of the individual sender, except where the message states otherwise and the sender is authorized to state the views of such entity. Unless otherwise stated, any pricing information in this message is indicative only, is subject to change and does not constitute an offer to deal at any price quoted. Any reference to the terms of executed transactions should be treated as preliminary only and subject to our formal written confirmation.
Tue, 2009-03-10, 19:57
#10
Re: Flagging Uniques
Frohnhofer, James wrote:
> Slow as anything, but I think correct, clear and tail-recursive
>
> def flag(m:List[Int], seen:List[Int]):List[Boolean] = {
> m match {
> case Nil => Nil
> case x::xs => !seen.contains(x)::flag(xs, x::seen)
> }
> }
Unfortunately not tail recursive. You'll need to add a result parameter
for that:
def flag(m : List[Int], s : Set[Int], result : List[Boolean]) :
List[Boolean] =
m match {
case Nil => result
case x :: xs => flag(xs, s + x, !s.contains(x) :: result)
}
flag(seq, Set(), Nil).reverse
/Jesper Nordenberg
Tue, 2009-03-10, 20:07
#11
Re: Re: Flagging Uniques
On Tue, Mar 10, 2009 at 07:40:34PM +0100, Jesper Nordenberg wrote:
> Unfortunately not tail recursive. You'll need to add a result parameter
> for that:
>
> def flag(m : List[Int], s : Set[Int], result : List[Boolean]) :
> List[Boolean] =
> m match {
> case Nil => result
> case x :: xs => flag(xs, s + x, !s.contains(x) :: result)
> }
Indeed, and if you're not careful even this version won't be tail
recursive because it's neither final nor private, so if it were in a
class and not an object it would not be.
This all highlights the need for the @tailrec annotation which I have
working at home and warns when marked methods cannot be made tail
recursive, but in the meantime anyone who wants to be sure should look
at the bytecode. The version from by James finished like this:
107: invokestatic #70; //Method scala/runtime/BoxesRunTime.boxToBoolean:(Z)Ljava/lang/Boolean;
110: invokevirtual #74; //Method scala/List.$colon$colon:(Ljava/lang/Object;)Lscala/List;
113: areturn
Since :: was the last thing called in his version, it cannot be tail
recursive. Whereas jesper's last action was a call to flag, and so it
looks more like this:
105: invokevirtual #71; //Method scala/List.$colon$colon:(Ljava/lang/Object;)Lscala/List;
108: astore_3
109: astore_2
110: astore_1
111: goto 0
If you don't see a backward-branching goto, it's a bit unlikely it's
tail recursive.
Tue, 2009-03-10, 20:07
#12
Re: Re: Flagging Uniques
> This all highlights the need for the @tailrec annotation
it always struck me as lame that many languages where TCO is
considered an important topic do not actively warn you about things
which can't be TCO'd. (i've heard that the O'Caml compiler can tell
you.)
Tue, 2009-03-10, 20:17
#13
RE: Re: Flagging Uniques
Oh well. I tried.
Is it because '::' is actually the last function call and not 'flag'?
-----Original Message-----
From: news [mailto:news@ger.gmane.org] On Behalf Of Jesper Nordenberg
Sent: Tuesday, March 10, 2009 2:41 PM
To: scala@listes.epfl.ch
Subject: [scala] Re: Flagging Uniques
Frohnhofer, James wrote:
> Slow as anything, but I think correct, clear and tail-recursive
>
> def flag(m:List[Int], seen:List[Int]):List[Boolean] = {
> m match {
> case Nil => Nil
> case x::xs => !seen.contains(x)::flag(xs, x::seen)
> }
> }
Unfortunately not tail recursive. You'll need to add a result parameter
for that:
def flag(m : List[Int], s : Set[Int], result : List[Boolean]) :
List[Boolean] =
m match {
case Nil => result
case x :: xs => flag(xs, s + x, !s.contains(x) :: result)
}
flag(seq, Set(), Nil).reverse
/Jesper Nordenberg
PLEASE READ: This message is for the named person's use only. It may contain confidential, proprietary or legally privileged information. No confidentiality or privilege is waived or lost by any mistransmission. If you receive this message in error, please delete it and all copies from your system, destroy any hard copies and notify the sender. You must not, directly or indirectly, use, disclose, distribute, print, or copy any part of this message if you are not the intended recipient. Nomura Holding America Inc., Nomura Securities International, Inc, and their respective subsidiaries each reserve the right to monitor all e-mail communications through its networks. Any views expressed in this message are those of the individual sender, except where the message states otherwise and the sender is authorized to state the views of such entity. Unless otherwise stated, any pricing information in this message is indicative only, is subject to change and does not constitute an offer to deal at any price quoted. Any reference to the terms of executed transactions should be treated as preliminary only and subject to our formal written confirmation.
Tue, 2009-03-10, 20:27
#14
Re: Re: Flagging Uniques
On Tuesday March 10 2009, Raoul Duke wrote:
> > This all highlights the need for the @tailrec annotation
Offhand, that seems like a good idea.
> it always struck me as lame that many languages where TCO is
> considered an important topic do not actively warn you about things
> which can't be TCO'd. (i've heard that the O'Caml compiler can tell
> you.)
Clojure has a language-level construct that you must use if you want
tail-call optimization and it fails if not used at a properly
tail-recursive position. Clojure's originator (Rich Hickey) believes
that because his sole target execution platform, the JVM, does not
directly support tail-call optimization, he should not pretend to offer
it to the language's users with a silent fallback to an ordinary call.
Naturally, plain old recursive calls are OK, they just require new
stack frames for each one.
Randall Schulz
Wed, 2009-03-11, 17:57
#15
Re: Re: Flagging Uniques
On Tue, Mar 10, 2009 at 2:52 PM, Paul Phillips <paulp@improving.org> wrote:
This strikes me as a *great* idea, for education as much as anything.
The language has a lot of people like me, who are coming into it mainly from the OO side of things, who don't live and breathe functional style yet. The tail-call thing is one of the subtler details -- I understand it intellectually pretty well, but I still have to work through each case carefully to figure out whether it actually manages to tail-recurse or not. So having this annotation, to tell me when I mess it up, would be a huge benefit for really internalizing the technique...
This all highlights the need for the @tailrec annotation
This strikes me as a *great* idea, for education as much as anything.
The language has a lot of people like me, who are coming into it mainly from the OO side of things, who don't live and breathe functional style yet. The tail-call thing is one of the subtler details -- I understand it intellectually pretty well, but I still have to work through each case carefully to figure out whether it actually manages to tail-recurse or not. So having this annotation, to tell me when I mess it up, would be a huge benefit for really internalizing the technique...
Mon, 2009-03-16, 19:07
#16
@tailrec and @switch now in trunk
On Tue, Mar 10, 2009 at 12:02:27PM -0700, Raoul Duke wrote:
> it always struck me as lame that many languages where TCO is
> considered an important topic do not actively warn you about things
> which can't be TCO'd.
On Tue, Mar 10, 2009 at 12:17:01PM -0700, Randall R Schulz wrote:
> Offhand, that seems like a good idea.
On Wed, Mar 11, 2009 at 12:47:45PM -0400, Justin du coeur wrote:
> This strikes me as a *great* idea, for education as much as anything.
Who could resist such a groundswell of support?
$ scala
Welcome to Scala version 2.8.0.r0-b20090316104443
scala> import scala.annotation._
import scala.annotation._
// object is ok since method can't be overridden
scala> object o { @tailrec def foo(x: Int): Int = foo(x) }
defined module o
// class with a method neither private nor final
scala> class c { @tailrec def foo(x: Int): Int = foo(x) }
:7: error: could not optimize @tailrec annotated method
class c { @tailrec def foo(x: Int): Int = foo(x) }
^
scala> def isTrue(x: Char): Boolean = x < 'q'
isTrue: (Char)Boolean
// wrong way to get a switch
scala> def bar(c: Char) = (c: @switch) match {
| case 'a'|'b'|'c' => true
| case x if isTrue(x) => true
| case _ => false
| }
:8: error: could not emit switch for @switch annotated match
def bar(c: Char) = (c: @switch) match {
^
// right way to get a switch
scala> def bar(c: Char) = (c: @switch) match {
| case 'a'|'b'|'c' => true
| case x => isTrue(x)
| }
bar: (Char)Boolean
Mon, 2009-03-16, 19:57
#17
Re: @tailrec and @switch now in trunk
On Mon, Mar 16, 2009 at 11:04 AM, Paul Phillips <paulp@improving.org> wrote:
On Tue, Mar 10, 2009 at 12:02:27PM -0700, Raoul Duke wrote:
> it always struck me as lame that many languages where TCO is
> considered an important topic do not actively warn you about things
> which can't be TCO'd.
On Tue, Mar 10, 2009 at 12:17:01PM -0700, Randall R Schulz wrote:
> Offhand, that seems like a good idea.
On Wed, Mar 11, 2009 at 12:47:45PM -0400, Justin du coeur wrote:
> This strikes me as a *great* idea, for education as much as anything.
Who could resist such a groundswell of support?
$ scala
Welcome to Scala version 2.8.0.r0-b20090316104443
scala> import scala.annotation._
import scala.annotation._
// object is ok since method can't be overridden
scala> object o { @tailrec def foo(x: Int): Int = foo(x) }
defined module o
ooohhhh.... I've been wanting this!! Thank you!
// class with a method neither private nor final
scala> class c { @tailrec def foo(x: Int): Int = foo(x) }
<console>:7: error: could not optimize @tailrec annotated method
class c { @tailrec def foo(x: Int): Int = foo(x) }
^
scala> def isTrue(x: Char): Boolean = x < 'q'
isTrue: (Char)Boolean
// wrong way to get a switch
scala> def bar(c: Char) = (c: @switch) match {
| case 'a'|'b'|'c' => true
| case x if isTrue(x) => true
| case _ => false
| }
<console>:8: error: could not emit switch for @switch annotated match
def bar(c: Char) = (c: @switch) match {
^
// right way to get a switch
scala> def bar(c: Char) = (c: @switch) match {
| case 'a'|'b'|'c' => true
| case x => isTrue(x)
| }
bar: (Char)Boolean
--
Paul Phillips | We must respect the other fellow's religion, but only
Protagonist | in the sense and to the extent that we respect his
Empiricist | theory that his wife is beautiful and his children smart.
slap pi uphill! | -- H. L. Mencken
--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp
Mon, 2009-03-16, 20:17
#18
Re: @tailrec and @switch now in trunk
You deserve a kitten! @tailrec is *very* handy
On Mon, Mar 16, 2009 at 2:52 PM, David Pollak <feeder.of.the.bears@gmail.com> wrote:
On Mon, Mar 16, 2009 at 2:52 PM, David Pollak <feeder.of.the.bears@gmail.com> wrote:
On Mon, Mar 16, 2009 at 11:04 AM, Paul Phillips <paulp@improving.org> wrote:
On Tue, Mar 10, 2009 at 12:02:27PM -0700, Raoul Duke wrote:
> it always struck me as lame that many languages where TCO is
> considered an important topic do not actively warn you about things
> which can't be TCO'd.
On Tue, Mar 10, 2009 at 12:17:01PM -0700, Randall R Schulz wrote:
> Offhand, that seems like a good idea.
On Wed, Mar 11, 2009 at 12:47:45PM -0400, Justin du coeur wrote:
> This strikes me as a *great* idea, for education as much as anything.
Who could resist such a groundswell of support?
$ scala
Welcome to Scala version 2.8.0.r0-b20090316104443
scala> import scala.annotation._
import scala.annotation._
// object is ok since method can't be overridden
scala> object o { @tailrec def foo(x: Int): Int = foo(x) }
defined module o
ooohhhh.... I've been wanting this!! Thank you!
// class with a method neither private nor final
scala> class c { @tailrec def foo(x: Int): Int = foo(x) }
<console>:7: error: could not optimize @tailrec annotated method
class c { @tailrec def foo(x: Int): Int = foo(x) }
^
scala> def isTrue(x: Char): Boolean = x < 'q'
isTrue: (Char)Boolean
// wrong way to get a switch
scala> def bar(c: Char) = (c: @switch) match {
| case 'a'|'b'|'c' => true
| case x if isTrue(x) => true
| case _ => false
| }
<console>:8: error: could not emit switch for @switch annotated match
def bar(c: Char) = (c: @switch) match {
^
// right way to get a switch
scala> def bar(c: Char) = (c: @switch) match {
| case 'a'|'b'|'c' => true
| case x => isTrue(x)
| }
bar: (Char)Boolean
--
Paul Phillips | We must respect the other fellow's religion, but only
Protagonist | in the sense and to the extent that we respect his
Empiricist | theory that his wife is beautiful and his children smart.
slap pi uphill! | -- H. L. Mencken
--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp
Mon, 2009-03-16, 21:17
#19
Re: @tailrec and @switch now in trunk
On Mon, Mar 16, 2009 at 11:04 AM, Paul Phillips wrote:
>
> scala> def isTrue(x: Char): Boolean = x < 'q'
> isTrue: (Char)Boolean
>
> // wrong way to get a switch
> scala> def bar(c: Char) = (c: @switch) match {
> | case 'a'|'b'|'c' => true
> | case x if isTrue(x) => true
> | case _ => false
> | }
> :8: error: could not emit switch for @switch annotated match
> def bar(c: Char) = (c: @switch) match {
> ^
What is so bad about that form to make it worth adding the annotation?
I see an extra branch. Is there something bad about having
conditionals on the left side?
>
> // right way to get a switch
> scala> def bar(c: Char) = (c: @switch) match {
> | case 'a'|'b'|'c' => true
> | case x => isTrue(x)
> | }
> bar: (Char)Boolean
>
> --
> Paul Phillips | We must respect the other fellow's religion, but only
> Protagonist | in the sense and to the extent that we respect his
> Empiricist | theory that his wife is beautiful and his children smart.
> slap pi uphill! | -- H. L. Mencken
>
Mon, 2009-03-16, 21:37
#20
Re: @tailrec and @switch now in trunk
On Mon, 2009-03-16 at 13:10 -0700, J Robert Ray wrote:
> What is so bad about that form to make it worth adding the annotation?
> I see an extra branch. Is there something bad about having
> conditionals on the left side?
As the annotation says, you will not get a switch in the generated
bytecode. Instead you will get a chain of if/else statements. I would
guess that most people won't care about that particular annotation, but
it can be useful in some cases.
Best,
Ismael
Mon, 2009-03-16, 21:47
#21
Re: @tailrec and @switch now in trunk
On Mon, Mar 16, 2009 at 01:10:12PM -0700, J Robert Ray wrote:
> What is so bad about that form to make it worth adding the annotation?
> I see an extra branch. Is there something bad about having
> conditionals on the left side?
One day I checked in some code and the compiler stopped compiling, and
it turned out the reason was that I had made a change like this: from
val x = 'D'
to
val x: Char = 'D'
You can read about this in more detail here:
https://lampsvn.epfl.ch/trac/scala/ticket/1456
The scalac scanner has a giant switch statement which has lines that
look like this, and in fact are written like this specifically so it
will compile into a switch:
case 'A' | 'B' | 'C' | 'D' | 'E' |
'F' | 'G' | 'H' | 'I' | 'J' |
'K' | 'L' | 'M' | 'N' | 'O' |
'P' | 'Q' | 'R' | 'S' | 'T' |
'U' | 'V' | 'W' | 'X' | 'Y' |
'Z' | '$' | '_' |
'a' | 'b' | 'c' | 'd' | 'e' |
'f' | 'g' | 'h' | 'i' | 'j' |
'k' | 'l' | 'm' | 'n' | 'o' |
'p' | 'q' | 'r' | 's' | 't' |
'u' | 'v' | 'w' | 'x' | 'y' |
'z' =>
Altering x from an undeclared Char to a declared Char caused the
compiler to no longer infer the singleton type, which caused the giant
match statement not to compile into a switch anymore, which caused the
stack depth to go into the hundreds where before it had stayed in the
10-20 range, which broked the compiler.
Since I wasted most of a day figuring out what had happened, I decided
that in the future it'd be better if we could assert our particularly
high level of interest in certain matches compiling down to switches.
Mon, 2009-03-16, 21:57
#22
Re: @tailrec and @switch now in trunk
On Mon, Mar 16, 2009 at 7:04 PM, Paul Phillips wrote:
> // class with a method neither private nor final
> scala> class c { @tailrec def foo(x: Int): Int = foo(x) }
> :7: error: could not optimize @tailrec annotated method
> class c { @tailrec def foo(x: Int): Int = foo(x) }
> ^
This looks handy indeed!
Would it be hard to add the text in you comment to the error message?
BR,
John
Tue, 2009-03-17, 03:27
#23
Re: @tailrec and @switch now in trunk
Why @tailrec methods aren't final by default?
2009/3/16 Paul Phillips :
>
> On Tue, Mar 10, 2009 at 12:02:27PM -0700, Raoul Duke wrote:
>> it always struck me as lame that many languages where TCO is
>> considered an important topic do not actively warn you about things
>> which can't be TCO'd.
>
> On Tue, Mar 10, 2009 at 12:17:01PM -0700, Randall R Schulz wrote:
>> Offhand, that seems like a good idea.
>
> On Wed, Mar 11, 2009 at 12:47:45PM -0400, Justin du coeur wrote:
>> This strikes me as a *great* idea, for education as much as anything.
>
> Who could resist such a groundswell of support?
>
> $ scala
> Welcome to Scala version 2.8.0.r0-b20090316104443
>
> scala> import scala.annotation._
> import scala.annotation._
>
> // object is ok since method can't be overridden
> scala> object o { @tailrec def foo(x: Int): Int = foo(x) }
> defined module o
>
> // class with a method neither private nor final
> scala> class c { @tailrec def foo(x: Int): Int = foo(x) }
> :7: error: could not optimize @tailrec annotated method
> class c { @tailrec def foo(x: Int): Int = foo(x) }
> ^
>
> scala> def isTrue(x: Char): Boolean = x < 'q'
> isTrue: (Char)Boolean
>
> // wrong way to get a switch
> scala> def bar(c: Char) = (c: @switch) match {
> | case 'a'|'b'|'c' => true
> | case x if isTrue(x) => true
> | case _ => false
> | }
> :8: error: could not emit switch for @switch annotated match
> def bar(c: Char) = (c: @switch) match {
> ^
>
> // right way to get a switch
> scala> def bar(c: Char) = (c: @switch) match {
> | case 'a'|'b'|'c' => true
> | case x => isTrue(x)
> | }
> bar: (Char)Boolean
>
> --
> Paul Phillips | We must respect the other fellow's religion, but only
> Protagonist | in the sense and to the extent that we respect his
> Empiricist | theory that his wife is beautiful and his children smart.
> slap pi uphill! | -- H. L. Mencken
>
Tue, 2009-03-17, 04:17
#24
Re: @tailrec and @switch now in trunk
On Mon, Mar 16, 2009 at 11:18:17PM -0300, Andrés Testi wrote:
> Why @tailrec methods aren't final by default?
Not sure if I'm understanding you correctly, but if you're suggesting
that the @tailrec annotation itself cause the method to be final, this
is a bad idea. The line between language constructs and annotation
influence may be a bit blurry in places, but not that blurry.
I could enhance the error messages to say exactly why it failed, but
it's not a priority because I suspect if you know enough to include the
annotation, you also know enough to figure out what happened.
Tue, 2009-03-17, 08:37
#25
Re: @tailrec and @switch now in trunk
paulp is probably going to inspire a new generation of geek-first-person-shooter-rpg games, where the main hero chases bugs, proposes new syntax/utilities and strategically thinks for the future. This will all happen in "ScalaLand", and most specifically in paulp's dominion, "Scalaca". A new epoch of avatars is raising... Are we witnessing the Reign of PaulP?
GREAT JOB Paul!!!!
Christos.
P.S. At the rate you invent things, I just hope will not not make the compiler lame at some point ;-)
On Mon, Mar 16, 2009 at 8:04 PM, Paul Phillips <paulp@improving.org> wrote:
On Tue, Mar 10, 2009 at 12:02:27PM -0700, Raoul Duke wrote:
> it always struck me as lame that many languages where TCO is
> considered an important topic do not actively warn you about things
> which can't be TCO'd.
On Tue, Mar 10, 2009 at 12:17:01PM -0700, Randall R Schulz wrote:
> Offhand, that seems like a good idea.
On Wed, Mar 11, 2009 at 12:47:45PM -0400, Justin du coeur wrote:
> This strikes me as a *great* idea, for education as much as anything.
Who could resist such a groundswell of support?
$ scala
Welcome to Scala version 2.8.0.r0-b20090316104443
scala> import scala.annotation._
import scala.annotation._
// object is ok since method can't be overridden
scala> object o { @tailrec def foo(x: Int): Int = foo(x) }
defined module o
// class with a method neither private nor final
scala> class c { @tailrec def foo(x: Int): Int = foo(x) }
<console>:7: error: could not optimize @tailrec annotated method
class c { @tailrec def foo(x: Int): Int = foo(x) }
^
scala> def isTrue(x: Char): Boolean = x < 'q'
isTrue: (Char)Boolean
// wrong way to get a switch
scala> def bar(c: Char) = (c: @switch) match {
| case 'a'|'b'|'c' => true
| case x if isTrue(x) => true
| case _ => false
| }
<console>:8: error: could not emit switch for @switch annotated match
def bar(c: Char) = (c: @switch) match {
^
// right way to get a switch
scala> def bar(c: Char) = (c: @switch) match {
| case 'a'|'b'|'c' => true
| case x => isTrue(x)
| }
bar: (Char)Boolean
--
Paul Phillips | We must respect the other fellow's religion, but only
Protagonist | in the sense and to the extent that we respect his
Empiricist | theory that his wife is beautiful and his children smart.
slap pi uphill! | -- H. L. Mencken
--
__~O
-\ <, Christos KK Loverdos
(*)/ (*) http://ckkloverdos.com
Tue, 2009-03-17, 08:57
#26
Re: @tailrec and @switch now in trunk
Super cool !
On Mon, Mar 16, 2009 at 8:04 PM, Paul Phillips <paulp@improving.org> wrote:
On Mon, Mar 16, 2009 at 8:04 PM, Paul Phillips <paulp@improving.org> wrote:
On Tue, Mar 10, 2009 at 12:02:27PM -0700, Raoul Duke wrote:
> it always struck me as lame that many languages where TCO is
> considered an important topic do not actively warn you about things
> which can't be TCO'd.
On Tue, Mar 10, 2009 at 12:17:01PM -0700, Randall R Schulz wrote:
> Offhand, that seems like a good idea.
On Wed, Mar 11, 2009 at 12:47:45PM -0400, Justin du coeur wrote:
> This strikes me as a *great* idea, for education as much as anything.
Who could resist such a groundswell of support?
$ scala
Welcome to Scala version 2.8.0.r0-b20090316104443
scala> import scala.annotation._
import scala.annotation._
// object is ok since method can't be overridden
scala> object o { @tailrec def foo(x: Int): Int = foo(x) }
defined module o
// class with a method neither private nor final
scala> class c { @tailrec def foo(x: Int): Int = foo(x) }
<console>:7: error: could not optimize @tailrec annotated method
class c { @tailrec def foo(x: Int): Int = foo(x) }
^
scala> def isTrue(x: Char): Boolean = x < 'q'
isTrue: (Char)Boolean
// wrong way to get a switch
scala> def bar(c: Char) = (c: @switch) match {
| case 'a'|'b'|'c' => true
| case x if isTrue(x) => true
| case _ => false
| }
<console>:8: error: could not emit switch for @switch annotated match
def bar(c: Char) = (c: @switch) match {
^
// right way to get a switch
scala> def bar(c: Char) = (c: @switch) match {
| case 'a'|'b'|'c' => true
| case x => isTrue(x)
| }
bar: (Char)Boolean
--
Paul Phillips | We must respect the other fellow's religion, but only
Protagonist | in the sense and to the extent that we respect his
Empiricist | theory that his wife is beautiful and his children smart.
slap pi uphill! | -- H. L. Mencken
Tue, 2009-03-17, 09:37
#27
Re: @tailrec and @switch now in trunk
He also cleans code up, so I'd guess he won't make the compiler lame.
2009/3/17 Christos KK Loverdos :
>
> paulp is probably going to inspire a new generation of
> geek-first-person-shooter-rpg games, where the main hero chases bugs,
> proposes new syntax/utilities and strategically thinks for the future. This
> will all happen in "ScalaLand", and most specifically in paulp's dominion,
> "Scalaca". A new epoch of avatars is raising... Are we witnessing the Reign
> of PaulP?
> GREAT JOB Paul!!!!
>
>
> Christos.
> P.S. At the rate you invent things, I just hope will not not make the
> compiler lame at some point ;-)
> On Mon, Mar 16, 2009 at 8:04 PM, Paul Phillips wrote:
>>
>> On Tue, Mar 10, 2009 at 12:02:27PM -0700, Raoul Duke wrote:
>> > it always struck me as lame that many languages where TCO is
>> > considered an important topic do not actively warn you about things
>> > which can't be TCO'd.
>>
>> On Tue, Mar 10, 2009 at 12:17:01PM -0700, Randall R Schulz wrote:
>> > Offhand, that seems like a good idea.
>>
>> On Wed, Mar 11, 2009 at 12:47:45PM -0400, Justin du coeur wrote:
>> > This strikes me as a *great* idea, for education as much as anything.
>>
>> Who could resist such a groundswell of support?
>>
>> $ scala
>> Welcome to Scala version 2.8.0.r0-b20090316104443
>>
>> scala> import scala.annotation._
>> import scala.annotation._
>>
>> // object is ok since method can't be overridden
>> scala> object o { @tailrec def foo(x: Int): Int = foo(x) }
>> defined module o
>>
>> // class with a method neither private nor final
>> scala> class c { @tailrec def foo(x: Int): Int = foo(x) }
>> :7: error: could not optimize @tailrec annotated method
>> class c { @tailrec def foo(x: Int): Int = foo(x) }
>> ^
>>
>> scala> def isTrue(x: Char): Boolean = x < 'q'
>> isTrue: (Char)Boolean
>>
>> // wrong way to get a switch
>> scala> def bar(c: Char) = (c: @switch) match {
>> | case 'a'|'b'|'c' => true
>> | case x if isTrue(x) => true
>> | case _ => false
>> | }
>> :8: error: could not emit switch for @switch annotated match
>> def bar(c: Char) = (c: @switch) match {
>> ^
>>
>> // right way to get a switch
>> scala> def bar(c: Char) = (c: @switch) match {
>> | case 'a'|'b'|'c' => true
>> | case x => isTrue(x)
>> | }
>> bar: (Char)Boolean
>>
>> --
>> Paul Phillips | We must respect the other fellow's religion, but only
>> Protagonist | in the sense and to the extent that we respect his
>> Empiricist | theory that his wife is beautiful and his children
>> smart.
>> slap pi uphill! | -- H. L. Mencken
>
>
>
> --
> __~O
> -\ <, Christos KK Loverdos
> (*)/ (*) http://ckkloverdos.com
>
Tue, 2009-03-17, 10:27
#28
Re: @tailrec and @switch now in trunk
Unless, overwhelmed by the cleaning frenziness, he sweeps the whole of scalac out.
On Tue, Mar 17, 2009 at 10:32 AM, Ricky Clarkson <ricky.clarkson@gmail.com> wrote:
--
__~O
-\ <, Christos KK Loverdos
(*)/ (*) http://ckkloverdos.com
On Tue, Mar 17, 2009 at 10:32 AM, Ricky Clarkson <ricky.clarkson@gmail.com> wrote:
He also cleans code up, so I'd guess he won't make the compiler lame.
2009/3/17 Christos KK Loverdos <loverdos@gmail.com>:
>
> paulp is probably going to inspire a new generation of
> geek-first-person-shooter-rpg games, where the main hero chases bugs,
> proposes new syntax/utilities and strategically thinks for the future. This
> will all happen in "ScalaLand", and most specifically in paulp's dominion,
> "Scalaca". A new epoch of avatars is raising... Are we witnessing the Reign
> of PaulP?
> GREAT JOB Paul!!!!
>
>
> Christos.
> P.S. At the rate you invent things, I just hope will not not make the
> compiler lame at some point ;-)
> On Mon, Mar 16, 2009 at 8:04 PM, Paul Phillips <paulp@improving.org> wrote:
>>
>> On Tue, Mar 10, 2009 at 12:02:27PM -0700, Raoul Duke wrote:
>> > it always struck me as lame that many languages where TCO is
>> > considered an important topic do not actively warn you about things
>> > which can't be TCO'd.
>>
>> On Tue, Mar 10, 2009 at 12:17:01PM -0700, Randall R Schulz wrote:
>> > Offhand, that seems like a good idea.
>>
>> On Wed, Mar 11, 2009 at 12:47:45PM -0400, Justin du coeur wrote:
>> > This strikes me as a *great* idea, for education as much as anything.
>>
>> Who could resist such a groundswell of support?
>>
>> $ scala
>> Welcome to Scala version 2.8.0.r0-b20090316104443
>>
>> scala> import scala.annotation._
>> import scala.annotation._
>>
>> // object is ok since method can't be overridden
>> scala> object o { @tailrec def foo(x: Int): Int = foo(x) }
>> defined module o
>>
>> // class with a method neither private nor final
>> scala> class c { @tailrec def foo(x: Int): Int = foo(x) }
>> <console>:7: error: could not optimize @tailrec annotated method
>> class c { @tailrec def foo(x: Int): Int = foo(x) }
>> ^
>>
>> scala> def isTrue(x: Char): Boolean = x < 'q'
>> isTrue: (Char)Boolean
>>
>> // wrong way to get a switch
>> scala> def bar(c: Char) = (c: @switch) match {
>> | case 'a'|'b'|'c' => true
>> | case x if isTrue(x) => true
>> | case _ => false
>> | }
>> <console>:8: error: could not emit switch for @switch annotated match
>> def bar(c: Char) = (c: @switch) match {
>> ^
>>
>> // right way to get a switch
>> scala> def bar(c: Char) = (c: @switch) match {
>> | case 'a'|'b'|'c' => true
>> | case x => isTrue(x)
>> | }
>> bar: (Char)Boolean
>>
>> --
>> Paul Phillips | We must respect the other fellow's religion, but only
>> Protagonist | in the sense and to the extent that we respect his
>> Empiricist | theory that his wife is beautiful and his children
>> smart.
>> slap pi uphill! | -- H. L. Mencken
>
>
>
> --
> __~O
> -\ <, Christos KK Loverdos
> (*)/ (*) http://ckkloverdos.com
>
--
__~O
-\ <, Christos KK Loverdos
(*)/ (*) http://ckkloverdos.com
On Fri, Mar 6, 2009 at 3:37 PM, Roman Roelofsen <roman.roelofsen@googlemail.com> wrote: