- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
First steps into generic types
Wed, 2011-05-18, 08:20
Hi!
I just made my first steps in Scala and tried to expand the simple OO
Expr class given in "Scala by Example" with a type parameter:
abstract class Expr[ T ] {
def eval: T
}
class Number[ T ]( n: T ) extends Expr[ T ] {
def eval: T = n
}
class Sum[ T <% Numeric[ T ] ]( e1: Expr[ T ], e2: Expr[ T ] )
extends Expr[ T ] {
def eval: T = e1.eval + e2.eval
}
This yields the (unexpected for me) compiler error:
error: type mismatch;
found : T
required: String
def eval: T = e1.eval + e2.eval
^
one error found
Please help me understand what's wrong here. Obviously, the concept of
type parameters is quite different from what I'm used to coding in C+
+, where the equivalent code would not give an error, as nothing is
generated (no instance of Sum) and only syntax is checked at this
level.
Regards,
Matthias
Wed, 2011-05-18, 10:47
#2
Re: First steps into generic types
Hi!
On May 18, 9:31 am, Sonnenschein wrote:
> "e1.eval" returns T <: Any because in "abstract class Expr[ T ]" T is
> unconstrained, not Numeric or whatever you'd like.
> Any has no "+" defined, so the compiler only sees the implicit
> conversion to String.
I changed the line
abstract class Expr[ T ] {
to
abstract class Expr[ T <% Numeric[ T ] ] {
Unfortunately, that does not help.
Regards,
Matthias
Wed, 2011-05-18, 10:57
#3
Re: Re: First steps into generic types
Numeric doesn't work like that. It's a type class, so you'll want a context bound:
abstract class Expr[T : Numeric] {
def eval: T
}
class Number[T : Numeric]( n: T ) extends Expr[T] {
def eval: T = n
}
class Sum[T : Numeric](e1: Expr[T], e2: Expr[T] )extends Expr[T] {
def eval: T = e1.eval + e2.eval
}
(disclaimer, this was hastily written and is untested)
On 18 May 2011 10:41, Matthias Kluwe <mkluwe@gmail.com> wrote:
--
Kevin Wright
gtalk / msn : kev.lee.wright@gmail.comkev.lee.wright@gmail.commail: kevin.wright@scalatechnology.com
vibe / skype: kev.lee.wrightquora: http://www.quora.com/Kevin-Wright
twitter: @thecoda
"My point today is that, if we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent": the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger" ~ Dijkstra
abstract class Expr[T : Numeric] {
def eval: T
}
class Number[T : Numeric]( n: T ) extends Expr[T] {
def eval: T = n
}
class Sum[T : Numeric](e1: Expr[T], e2: Expr[T] )extends Expr[T] {
def eval: T = e1.eval + e2.eval
}
(disclaimer, this was hastily written and is untested)
On 18 May 2011 10:41, Matthias Kluwe <mkluwe@gmail.com> wrote:
Hi!
On May 18, 9:31 am, Sonnenschein <peter.em...@arcor.de> wrote:
> "e1.eval" returns T <: Any because in "abstract class Expr[ T ]" T is
> unconstrained, not Numeric or whatever you'd like.
> Any has no "+" defined, so the compiler only sees the implicit
> conversion to String.
I changed the line
abstract class Expr[ T ] {
to
abstract class Expr[ T <% Numeric[ T ] ] {
Unfortunately, that does not help.
Regards,
Matthias
--
Kevin Wright
gtalk / msn : kev.lee.wright@gmail.comkev.lee.wright@gmail.commail: kevin.wright@scalatechnology.com
vibe / skype: kev.lee.wrightquora: http://www.quora.com/Kevin-Wright
twitter: @thecoda
"My point today is that, if we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent": the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger" ~ Dijkstra
Wed, 2011-05-18, 18:37
#4
Re: First steps into generic types
Hi!
On 18 Mai, 05:47, Kevin Wright wrote:
> Numeric doesn't work like that. It's a type class, so you'll want a context
> bound:
>
> abstract class Expr[T : Numeric] {
> def eval: T
> }
>
> class Number[T : Numeric]( n: T ) extends Expr[T] {
> def eval: T = n
> }
>
> class Sum[T : Numeric](e1: Expr[T], e2: Expr[T] )extends Expr[T] {
> def eval: T = e1.eval + e2.eval
> }
>
> (disclaimer, this was hastily written and is untested)
Hmm, does not work here, same error: type mismatch;
found : T
required: String
def eval: T = e1.eval + e2.eval
Regards,
Matthias
Wed, 2011-05-18, 19:27
#5
Re: Re: First steps into generic types
Guys, "T" does not implement "+". Why do you expect it to?
To use Numeric implicit conversions you have to import it.
On Wed, May 18, 2011 at 14:32, Matthias Kluwe wrote:
> Hi!
>
> On 18 Mai, 05:47, Kevin Wright wrote:
>> Numeric doesn't work like that. It's a type class, so you'll want a context
>> bound:
>>
>> abstract class Expr[T : Numeric] {
>> def eval: T
>> }
>>
>> class Number[T : Numeric]( n: T ) extends Expr[T] {
>> def eval: T = n
>> }
>>
>> class Sum[T : Numeric](e1: Expr[T], e2: Expr[T] )extends Expr[T] {
>> def eval: T = e1.eval + e2.eval
>> }
>>
>> (disclaimer, this was hastily written and is untested)
>
> Hmm, does not work here, same error: type mismatch;
> found : T
> required: String
> def eval: T = e1.eval + e2.eval
>
> Regards,
> Matthias
Thu, 2011-05-19, 19:27
#6
Re: First steps into generic types
Hi!
On 18 Mai, 20:22, Daniel Sobral wrote:
> Guys, "T" does not implement "+". Why do you expect it to?
I skipped through the mentiones text "Scala By Example" and read (p.
60 ) that I could use
Set[A <: Ordered[A]]
to "enforce the comparability of a type by demanding that the type is
a subtype of Ordered" (which defines "<" that is needed in the ordered
set example).
I have to admit: By looking at the scala.math docs I simply _guessed_
I'd have to use Numeric.
> To use Numeric implicit conversions you have to import it.
I do not know how to do that until now.
Regards,
Matthias
Thu, 2011-05-19, 21:27
#7
Re: First steps into generic types
Hi Matthias,
imo playing with Numeric is nothing for the first steps. But maybe
this discussion helps:
http://groups.google.com/group/scala-user/browse_thread/thread/9303f68d2...
Cheers, Peter
Thu, 2011-05-19, 23:27
#8
Re: Re: First steps into generic types
On Thu, May 19, 2011 at 15:16, Matthias Kluwe wrote:
>
>> To use Numeric implicit conversions you have to import it.
>
> I do not know how to do that until now.
Ok, basic lessons.
Lesson 1: type classes. One of the patterns of code in Scala is the
type class pattern. If you know Java, it is very much like
Comparator, whose instances define a method that can compare two T.
The important point here is that a type class defines some object that
knows how to do something to other objects, as opposed to the other
objects themselves being able to do it (like in Comparable).
The type class pattern is defined in one of two ways:
def method[A : Numeric](x: A, y: A) = ...
def method[A](x: A, y: A)(implicit ev: Numeric[A]) = ...
These declarations are identical, except that the the implicit
parameter is anonymous in the first one, whereas the second one is
explicit.
Lesson 2: Implicits must be "carried". That is, if you call a method
that requires Numeric[A], then _your_ method must be able to provide
that as well. For example:
def addAll[A](list: List[A]): A = list.sum // doesn't work, because
sum requires implicit Numeric[A]
You can do this using the first syntax, which is shorter:
def addAll[A : Numeric](list: List[A]): A = list.sum // works, because
addAll received an implicit as parameter, even if anonymously
Lesson 3: Numeric type class
The Numeric type class defines some methods that do basic arithmetic.
For example:
def add[A](x: A, y: A)(implicit ev: Numeric[A]) = ev.plus(x, y)
See scaladoc for more methods, but it is generally agreed that this
looks ugly, so we don't want to do it that way.
Lesson 4: Numeric Ops
For that reason, there is an implicit conversion that add operators to
a type based on the Numeric for that type. It works like this:
def add[A](x: A, y: A)(implicit ev: Numeric[A]) = {
import ev._
x + y
}
If you used the first syntax, you then have to get the implicit first.
You can do that like this:
def add[A : Numeric](x: A, y: A) = {
val ev = implicitly[Numeric[A]] // cannot import directly
import ev._
x + y
}
What actually happens in the examples above is that ev contains an
implicit that converts from A to Ops[A], and Ops[A] has the method
"+".
Lesson 5: Ops for free
If you are going to do a lot of stuff with Numeric, all this importing
might get tedious. On Scala 2.9.0 you can do a single import that will
make every numeric work with ops automatically:
import Numeric.Implicits._
def add[A : Numeric](x: A, y: A) = x + y
Lesson 6: Ordering
Another type class you might be interested in is Ordering, which is
Scala's version of Comparator. Same stuff applies.
Fri, 2011-05-20, 21:07
#9
Re: First steps into generic types
Hi!
On 19 Mai, 18:23, Daniel Sobral wrote:
> On Thu, May 19, 2011 at 15:16, Matthias Kluwe wrote:
>
> >> To use Numeric implicit conversions you have to import it.
>
> > I do not know how to do that until now.
>
> Ok, basic lessons.
>
> [...]
>
> import Numeric.Implicits._
>
> def add[A : Numeric](x: A, y: A) = x + y
Wow, pretty much overwhelming.
Thank you for the elaborate answer!
I made this (simple) example working by adding the mentioned import
and changing the bound to "context bounds". I've yet to understand
what that *is*.
The answer to http://stackoverflow.com/questions/2982276/what-is-a-context-bound-in-scala
says it is a "shorthand form" "for passing a ClassManifest[T] into the
method as an implicit parameter". Phoey.
Regards,
Matthias
Fri, 2011-05-20, 23:27
#10
Re: Re: First steps into generic types
On Fri, May 20, 2011 at 17:01, Matthias Kluwe wrote:
>
> I made this (simple) example working by adding the mentioned import
> and changing the bound to "context bounds". I've yet to understand
> what that *is*.
>
> The answer to http://stackoverflow.com/questions/2982276/what-is-a-context-bound-in-scala
> says it is a "shorthand form" "for passing a ClassManifest[T] into the
> method as an implicit parameter". Phoey.
Perhaps you'll like this one better:
http://stackoverflow.com/questions/4465948/context-and-view-bounds-again...
Fri, 2011-06-17, 08:27
#11
Generic types
Hi all,
Could anyone suggest why following code gives such an unexpected
output?
class C[R,S] {
def apply(i:Any) = i match {
case i:R => println("case 1")
case i:S => println("case 2")
case _ => println("Other")
}
}
object mytest extends Application{
val c = new C[Int, Double]
c(1)
c(1.0)
c("Hello")
}
output:
case 1
case 1
case 1
whereas I think the output should be:
case 1
case 2
Other
With Thanks
Jiasnsen
Fri, 2011-06-17, 09:07
#12
Re: Generic types
Hi,
this seems to be due to type erasure in JVM. All your cases are reduced
to case i: Object since type parameters of C are reduced to C[Object,
Object]. Therefore all three examples match the first case.
Did you get compiler warning for that?
> Hi all,
>
> Could anyone suggest why following code gives such an unexpected
> output?
>
> class C[R,S] {
> def apply(i:Any) = i match {
> case i:R => println("case 1")
> case i:S => println("case 2")
> case _ => println("Other")
> }
> }
>
> object mytest extends Application{
>
> val c = new C[Int, Double]
> c(1)
> c(1.0)
> c("Hello")
> }
>
> output:
> case 1
> case 1
> case 1
>
> whereas I think the output should be:
> case 1
> case 2
> Other
>
> With Thanks
> Jiasnsen
Fri, 2011-06-17, 09:37
#13
Re: Generic types
Jiasnsen,
On 2011-06-17 9:20, Jiansen wrote:
> Could anyone suggest why following code gives such an unexpected
> output?
this happens because of type erasure. If you run the scala compiler with
-unchecked you will see the following warning:
[...]
warning: abstract type R in type pattern R is unchecked since it is
eliminated by erasure
case i:R => println("case 1")
[...]
The information about type parameters is not available at runtime. You
can read a detailed explanation in "Programming in Scala", section 15.2
or at [1].
Regards
Simon
Fri, 2011-06-17, 20:37
#14
Re: Re: Generic types
Variations on this issue have come up a lot recently. Is there a compelling reason why the warning that's displayed in this circumstance with -unchecked should not be enabled by default? Also, is there somewhere that this is documented as an FAQ : my code won't compile because... entry?
Thanks,
Matthew
On 17 June 2011 08:52, Simon Olofsson <simon@olofsson.de> wrote:
--
Matthew Pocockmailto: turingatemyhamster@gmail.comgchat: turingatemyhamster@gmail.com msn: matthew_pocock@yahoo.co.ukirc.freenode.net: drdozer(0191) 2566550
Thanks,
Matthew
On 17 June 2011 08:52, Simon Olofsson <simon@olofsson.de> wrote:
Jiasnsen,
On 2011-06-17 9:20, Jiansen wrote:
Could anyone suggest why following code gives such an unexpected
output?
this happens because of type erasure. If you run the scala compiler with -unchecked you will see the following warning:
[...]
warning: abstract type R in type pattern R is unchecked since it is eliminated by erasure
case i:R => println("case 1")
[...]
The information about type parameters is not available at runtime. You can read a detailed explanation in "Programming in Scala", section 15.2 or at [1].
[1] http://bit.ly/ZJ2UO
Regards
Simon
--
Matthew Pocockmailto: turingatemyhamster@gmail.comgchat: turingatemyhamster@gmail.com msn: matthew_pocock@yahoo.co.ukirc.freenode.net: drdozer(0191) 2566550
Fri, 2011-06-17, 21:27
#15
Re: Re: Generic types
Variations on this issue have come up a lot recently. Is there a compelling reason why the warning that's displayed in this circumstance with -unchecked should not be enabled by default? Also, is there somewhere that this is documented as an FAQ : my code won't compile because... entry?
Thanks,
Matthew
On 17 June 2011 08:52, Simon Olofsson <simon@olofsson.de> wrote:
--
Matthew Pocockmailto: turingatemyhamster@gmail.comgchat: turingatemyhamster@gmail.com msn: matthew_pocock@yahoo.co.ukirc.freenode.net: drdozer(0191) 2566550
Thanks,
Matthew
On 17 June 2011 08:52, Simon Olofsson <simon@olofsson.de> wrote:
Jiasnsen,
On 2011-06-17 9:20, Jiansen wrote:
Could anyone suggest why following code gives such an unexpected
output?
this happens because of type erasure. If you run the scala compiler with -unchecked you will see the following warning:
[...]
warning: abstract type R in type pattern R is unchecked since it is eliminated by erasure
case i:R => println("case 1")
[...]
The information about type parameters is not available at runtime. You can read a detailed explanation in "Programming in Scala", section 15.2 or at [1].
[1] http://bit.ly/ZJ2UO
Regards
Simon
--
Matthew Pocockmailto: turingatemyhamster@gmail.comgchat: turingatemyhamster@gmail.com msn: matthew_pocock@yahoo.co.ukirc.freenode.net: drdozer(0191) 2566550
Fri, 2011-06-17, 22:07
#16
Re: Generic types
On 2011-06-17 21:28, Matthew Pocock wrote:
> Is there a compelling reason why the warning that's displayed in this
> circumstance with -unchecked should not be enabled by default?
I don't know the exact reason, but my guess would be that it's "just a
warning" and it may be too verbose. You get a hint what to do:
warning: there were 1 unchecked warnings; re-run with -unchecked for
details
Also, there might be cases when you don't care about such warnings :)
Simon
Sat, 2011-06-18, 01:47
#17
Re: Generic types
Jiasnsen,
You can accomplish what you want using Manifests. It just adds a
little more verbosity to your case statements:
scala> class C[R:Manifest,S:Manifest] {
| def apply[T: Manifest](i: T) = i match {
| case i if(implicitly[Manifest[T]] == implicitly[Manifest[R]])
=> println("case 1")
| case i if(implicitly[Manifest[T]] == implicitly[Manifest[S]])
=> println("case 2")
| case _ => println("other")
| }}
defined class C
scala> val c = new C[Int,Double]
c: C[Int,Double] = C@22721290
scala> c(1)
case 1
scala> c(1.0)
case 2
scala> c("Hello")
other
Regards,
Alan
On Jun 17, 4:20 am, Jiansen wrote:
> Hi all,
>
> Could anyone suggest why following code gives such an unexpected
> output?
>
> class C[R,S] {
> def apply(i:Any) = i match {
> case i:R => println("case 1")
> case i:S => println("case 2")
> case _ => println("Other")
> }
>
> }
>
> object mytest extends Application{
>
> val c = new C[Int, Double]
> c(1)
> c(1.0)
> c("Hello")
>
> }
>
> output:
> case 1
> case 1
> case 1
>
> whereas I think the output should be:
> case 1
> case 2
> Other
>
> With Thanks
> Jiasnsen
Sun, 2011-06-19, 19:27
#18
Re: Re: Generic types
On Fri, Jun 17, 2011 at 8:28 PM, Matthew Pocock <turingatemyhamster@gmail.com> wrote:
Personally, I think -unchecked and -deprecated should be enabled by default. It's what I do for all my projects.
Best,Ismael
Variations on this issue have come up a lot recently. Is there a compelling reason why the warning that's displayed in this circumstance with -unchecked should not be enabled by default?
Personally, I think -unchecked and -deprecated should be enabled by default. It's what I do for all my projects.
Best,Ismael
Sun, 2011-06-19, 19:47
#19
Re: Re: Generic types
That makes sense --- let more advanced users turn it off if they want, but newbies should get them by default!
On Sun, Jun 19, 2011 at 2:17 PM, Ismael Juma <ismael@juma.me.uk> wrote:
On Sun, Jun 19, 2011 at 2:17 PM, Ismael Juma <ismael@juma.me.uk> wrote:
On Fri, Jun 17, 2011 at 8:28 PM, Matthew Pocock <turingatemyhamster@gmail.com> wrote:
Variations on this issue have come up a lot recently. Is there a compelling reason why the warning that's displayed in this circumstance with -unchecked should not be enabled by default?
Personally, I think -unchecked and -deprecated should be enabled by default. It's what I do for all my projects.
Best,Ismael
Mon, 2011-06-20, 10:17
#20
Re: Re: Generic types
+1
I agree that the default should be to enable these settings.
Regards,
Rüdiger
2011/6/19 Ismael Juma :
> On Fri, Jun 17, 2011 at 8:28 PM, Matthew Pocock
> wrote:
>>
>> Variations on this issue have come up a lot recently. Is there a
>> compelling reason why the warning that's displayed in this circumstance with
>> -unchecked should not be enabled by default?
>
> Personally, I think -unchecked and -deprecated should be enabled by default.
> It's what I do for all my projects.
> Best,
> Ismael
Mon, 2011-06-20, 14:27
#21
Re: Generic types
W dniu 2011-06-18 02:37, AlanP pisze:
> Jiasnsen,
>
> You can accomplish what you want using Manifests. It just adds a
> little more verbosity to your case statements:
>
> scala> class C[R:Manifest,S:Manifest] {
> | def apply[T: Manifest](i: T) = i match {
> | case i if(implicitly[Manifest[T]] == implicitly[Manifest[R]])
> => println("case 1")
> | case i if(implicitly[Manifest[T]] == implicitly[Manifest[S]])
> => println("case 2")
> | case _ => println("other")
> | }}
> defined class C
Hmm, if we have this magic Manifest thing that brings back full generic
type information to runtime, and in the type spec of the class Manifests
are listed for the generic types, wouldn't it be a good idea if such
Manifest checking code be generated automatically by the compiler?
So:
class C[R,S] {
def apply(i:Any) = i match {
case i:R => println("case 1")
case i:S => println("case 2")
case _ => println("Other")
}
}
generates a warning, so I add Manifests to it:
class C[R : Manifest, S : Manifest] {
def apply[T: Manifest](i:T) = i match {
case i:R => println("case 1")
case i:S => println("case 2")
case _ => println("Other")
}
}
and voilla, the types are checked and the matching works as intended?
Of course, this could also affect the .isInstanceOf operator.
What do you think?
Regards,
Piotr
>
> scala> val c = new C[Int,Double]
> c: C[Int,Double] = C@22721290
>
> scala> c(1)
> case 1
>
> scala> c(1.0)
> case 2
>
> scala> c("Hello")
> other
>
> Regards,
>
> Alan
>
>
>
> On Jun 17, 4:20 am, Jiansen wrote:
>> Hi all,
>>
>> Could anyone suggest why following code gives such an unexpected
>> output?
>>
>> class C[R,S] {
>> def apply(i:Any) = i match {
>> case i:R => println("case 1")
>> case i:S => println("case 2")
>> case _ => println("Other")
>> }
>>
>> }
>>
>> object mytest extends Application{
>>
>> val c = new C[Int, Double]
>> c(1)
>> c(1.0)
>> c("Hello")
>>
>> }
>>
>> output:
>> case 1
>> case 1
>> case 1
>>
>> whereas I think the output should be:
>> case 1
>> case 2
>> Other
>>
>> With Thanks
>> Jiasnsen
>
Mon, 2011-06-20, 23:37
#22
Re: Re: Generic types
No, because it requires the calling code to also have Manifest information, and so on.
2011/6/20 Piotr Kołaczkowski <pkolaczk@elka.pw.edu.pl>
2011/6/20 Piotr Kołaczkowski <pkolaczk@elka.pw.edu.pl>
W dniu 2011-06-18 02:37, AlanP pisze:
Jiasnsen,
You can accomplish what you want using Manifests. It just adds a
little more verbosity to your case statements:
scala> class C[R:Manifest,S:Manifest] {
| def apply[T: Manifest](i: T) = i match {
| case i if(implicitly[Manifest[T]] == implicitly[Manifest[R]])
=> println("case 1")
| case i if(implicitly[Manifest[T]] == implicitly[Manifest[S]])
=> println("case 2")
| case _ => println("other")
| }}
defined class C
Hmm, if we have this magic Manifest thing that brings back full generic type information to runtime, and in the type spec of the class Manifests are listed for the generic types, wouldn't it be a good idea if such Manifest checking code be generated automatically by the compiler?
So:
class C[R,S] {
def apply(i:Any) = i match {
case i:R => println("case 1")
case i:S => println("case 2")
case _ => println("Other")
}
}
generates a warning, so I add Manifests to it:
class C[R : Manifest, S : Manifest] {
def apply[T: Manifest](i:T) = i match {
case i:R => println("case 1")
case i:S => println("case 2")
case _ => println("Other")
}
}
and voilla, the types are checked and the matching works as intended?
Of course, this could also affect the .isInstanceOf operator.
What do you think?
Regards,
Piotr
scala> val c = new C[Int,Double]
c: C[Int,Double] = C@22721290
scala> c(1)
case 1
scala> c(1.0)
case 2
scala> c("Hello")
other
Regards,
Alan
On Jun 17, 4:20 am, Jiansen<jianse...@gmail.com> wrote:
Hi all,
Could anyone suggest why following code gives such an unexpected
output?
class C[R,S] {
def apply(i:Any) = i match {
case i:R => println("case 1")
case i:S => println("case 2")
case _ => println("Other")
}
}
object mytest extends Application{
val c = new C[Int, Double]
c(1)
c(1.0)
c("Hello")
}
output:
case 1
case 1
case 1
whereas I think the output should be:
case 1
case 2
Other
With Thanks
Jiasnsen
Tue, 2011-06-21, 11:27
#23
Re: Generic types
I can't see how the proposition affects the calling code. I haven't said
anything about the compiler *adding* Manifest declarations itself, just
*using* it, when present.
What I propose is to make the compiler use the Manifest information if
it is available (appropriate Manifest passed as an argument to the
method or class constructor), or to fallback to current behaviour if it
is not available (generating an unchecked warning).
Regards,
Piotr
W dniu 2011-06-21 00:27, Naftoli Gugenheim pisze:
> No, because it requires the calling code to also have Manifest
> information, and so on.
>
> 2011/6/20 Piotr Kołaczkowski
> >
>
> W dniu 2011-06-18 02:37, AlanP pisze:
>
> Jiasnsen,
>
> You can accomplish what you want using Manifests. It just adds a
> little more verbosity to your case statements:
>
> scala> class C[R:Manifest,S:Manifest] {
> | def apply[T: Manifest](i: T) = i match {
> | case i if(implicitly[Manifest[T]] ==
> implicitly[Manifest[R]])
> => println("case 1")
> | case i if(implicitly[Manifest[T]] ==
> implicitly[Manifest[S]])
> => println("case 2")
> | case _ => println("other")
> | }}
> defined class C
>
>
>
> Hmm, if we have this magic Manifest thing that brings back full
> generic type information to runtime, and in the type spec of the
> class Manifests are listed for the generic types, wouldn't it be a
> good idea if such Manifest checking code be generated automatically
> by the compiler?
>
>
> So:
>
>
> class C[R,S] {
> def apply(i:Any) = i match {
> case i:R => println("case 1")
> case i:S => println("case 2")
> case _ => println("Other")
> }
> }
>
>
> generates a warning, so I add Manifests to it:
>
>
> class C[R : Manifest, S : Manifest] {
> def apply[T: Manifest](i:T) = i match {
> case i:R => println("case 1")
> case i:S => println("case 2")
> case _ => println("Other")
> }
> }
>
> and voilla, the types are checked and the matching works as intended?
> Of course, this could also affect the .isInstanceOf operator.
>
> What do you think?
>
> Regards,
> Piotr
>
>
>
>
>
>
> scala> val c = new C[Int,Double]
> c: C[Int,Double] = C@22721290
>
> scala> c(1)
> case 1
>
> scala> c(1.0)
> case 2
>
> scala> c("Hello")
> other
>
> Regards,
>
> Alan
>
>
>
> On Jun 17, 4:20 am,
> Jiansen > wrote:
>
> Hi all,
>
> Could anyone suggest why following code gives such an unexpected
> output?
>
> class C[R,S] {
> def apply(i:Any) = i match {
> case i:R => println("case 1")
> case i:S => println("case 2")
> case _ => println("Other")
> }
>
> }
>
> object mytest extends Application{
>
> val c = new C[Int, Double]
> c(1)
> c(1.0)
> c("Hello")
>
> }
>
> output:
> case 1
> case 1
> case 1
>
> whereas I think the output should be:
> case 1
> case 2
> Other
>
> With Thanks
> Jiasnsen
>
>
>
>
>
Tue, 2011-06-21, 18:37
#24
Re: Re: Generic types
That's pretty much what the current behavior is
def f[A : Manifest] = { def g = new Array[A](0) g}
g uses the manifest from its enclosing scope to create an array.
Same deal here
class X[A : Manifest] { def g = new Array[A](0) }
Don't know what you mean by "unchecked" warning. The check that a manifest is available is static. It occurs at compile time, not runtime.
2011/6/21 Piotr Kołaczkowski <pkolaczk@elka.pw.edu.pl>
def f[A : Manifest] = { def g = new Array[A](0) g}
g uses the manifest from its enclosing scope to create an array.
Same deal here
class X[A : Manifest] { def g = new Array[A](0) }
Don't know what you mean by "unchecked" warning. The check that a manifest is available is static. It occurs at compile time, not runtime.
2011/6/21 Piotr Kołaczkowski <pkolaczk@elka.pw.edu.pl>
What I propose is to make the compiler use the Manifest information if it is available (appropriate Manifest passed as an argument to the method or class constructor), or to fallback to current behaviour if it is not available (generating an unchecked warning).
Regards,
Piotr
Tue, 2011-06-21, 19:17
#25
Re: Generic types
No, it is not what I meant.
What about this:
def f[A : Manifest](x: Any) = x.isInstanceOf[A] // unchecked warning
Actually, in this example, the compiler has all the information required
to generate proper runtime type checking code, so unchecked warning here
is really not required. I think adding an isInstanceOf method working
this way is even possible to do now, without touching the compiler, only
by means of manifests and implicit conversions (it must have a different
name, though).
Or this:
def f[A : Manifest](x: Any) = x match {
case _: A =>
case _: Any =>
}
A solution for this has already been proposed in this thread, using
manifests in guards directly, but it is really not readable and looks
like boilerplate code. Isn't the whole point of Scala avoiding
boilerplate code?
If I have some spare time, I'll try to code a compiler plugin for this ;)
Regards,
Piotr
W dniu 2011-06-21 19:33, James Iry pisze:
> That's pretty much what the current behavior is
>
> def f[A : Manifest] = {
> def g = new Array[A](0)
> g
> }
>
> g uses the manifest from its enclosing scope to create an array.
>
> Same deal here
>
> class X[A : Manifest] {
> def g = new Array[A](0)
> }
>
> Don't know what you mean by "unchecked" warning. The check that a
> manifest is available is static. It occurs at compile time, not runtime.
>
> 2011/6/21 Piotr Kołaczkowski
> >
>
> What I propose is to make the compiler use the Manifest information
> if it is available (appropriate Manifest passed as an argument to
> the method or class constructor), or to fallback to current
> behaviour if it is not available (generating an unchecked warning).
>
> Regards,
> Piotr
>
Wed, 2011-06-22, 01:47
#26
Re: Re: Generic types
From my phone so it may make comedy errors. It is the run time that has theknowledge, not the compiler. A ptddggagdmtjw clever compiler perhaps could handle this, but we don't have side effects and psi in the compiler.
Matthew
On 21 Jun 2011 19:14, "Piotr Kołaczkowski" <pkolaczk@elka.pw.edu.pl> wrote:
No, it is not what I meant.
What about this:
def f[A : Manifest](x: Any) = x.isInstanceOf[A] // unchecked warning
Actually, in this example, the compiler has all the information required to generate proper runtime type checking code, so unchecked warning here is really not required. I think adding an isInstanceOf method working this way is even possible to do now, without touching the compiler, only by means of manifests and implicit conversions (it must have a different name, though).
Or this:
def f[A : Manifest](x: Any) = x match {
case _: A =>
case _: Any =>
}
A solution for this has already been proposed in this thread, using manifests in guards directly, but it is really not readable and looks like boilerplate code. Isn't the whole point of Scala avoiding boilerplate code?
If I have some spare time, I'll try to code a compiler plugin for this ;)
Regards,
Piotr
W dniu 2011-06-21 19:33, James Iry pisze:
>
<mailto:pkolaczk [at] elka [dot] pw [dot] edu.pl>>
> That's pretty much what the current behavior is
>
> def f[A : Manifest] = {
> def g = new Arr...
>
> What I propose is to make the compiler use the Manifest information
> if it is available ...
Wed, 2011-06-22, 07:07
#27
Re: Re: Generic types
Hi Matthias,
"e1.eval" returns T <: Any because in "abstract class Expr[ T ]" T is
unconstrained, not Numeric or whatever you'd like.
Any has no "+" defined, so the compiler only sees the implicit
conversion to String.
Peter