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

scala's signature dish: appetizer

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

Scala's Signature Dish, Chapter I

1) This ends with a puzzle. You like puzzles, don't you?
2) A couple days ago retronym took me to the restaurant "Scala" where I
actually ordered their signature dish. No enlightenments yet but I'm
still hopeful.

I am going to attempt to distill the signature problem and why it isn't
fixed yet, but in case I can draw in more interested parties by
uncharacteristically documenting a little bit, here is a quick overview
of signatures. There are two bytecode constructs which communicate the
key characteristics of the blobs of data you find in there. The older,
pre-generics one is called a "descriptor" and the one tacked on later a
"signature", although the latter term is often misused for both. Fields
and methods get both varieties; class definitions only get signatures.
Descriptors have no knowledge of type parameters, but they are
approximately equivalent to a signature after erasing the types.

Why do we care about signatures? Here is how things look to java, and
everything else in the world beyond the scala compiler (which reads its
own, much richer signature format when parsing scala bytecode, but
relies on java generic signatures for reading java since that's all
there is.)

// ...with signatures
class Cell[T](val x: T) // put a T in, get a T out
// ...without signatures
class Cell(val x: Object) // put whatever you want in, take an Object out

To see some sweet signature action, download a 2.9 nightly and:

// define this in the repl
class Bippy[A <: Function0[_ <: Comparable[_]]] extends Mutable {
var x: List[A] = _
def f[B, C <: A](x: Int, y: B) = ((x, y))
}

scala> :javap -verbose Bippy
// trimmed to relevant constant pool entries
const #3 = Asciz x;
const #4 = Asciz Lscala/collection/immutable/List;;
const #5 = Asciz Lscala/collection/immutable/List;;
const #18 = Asciz f;
const #19 = Asciz (ILjava/lang/Object;)Lscala/Tuple2;;
const #38 = Asciz
(ITB;)Lscala/Tuple2;;
const #45 = Asciz
;>;>Ljava/lang/Object;Lscala/Mutable;Lscala/ScalaObject;;

[4] field descriptor // notice the raw List type
[5] field signature // "TA;" means "type parameter A"
[19] method descriptor // "I" is primitive Int; "L...;" is a class.
[38] method signature // "C:TA" means tparam C is bounded by A.
[45] class signature // "+" is covariance; "*" a wildcard.

Notice there is a lot more information in the generic signatures. That
is the point. There are a number of restrictions on exactly how you
create a signature. The most important for our purposes is that you
cannot parameterize a type on primitives. The one-character primitive
type tags cannot appear as type arguments or type bounds unless you
enjoy the music of breakage.

Before we come to the next chapter wherein we examine the problem,
consider the following scala code. The questions for you are:

1) What signatures should go into classes A and B?
1b) "Eclipse crashes." Pay $50 and go back to square 1.
2) Given those signatures, does the java code compile?
2b) "You broke reflection." Lose a turn.
3) Try again. Would you like to buy some bridge methods?
3b) The troll grabbed you! Pay $100 or be eaten and lose infinity turns.
4) Do you like apples? How do you like these apples?

// it's some scala code
trait A[T] {
def f(): T = Predef.error("")
def g(x: Int) = ()
}
class B extends A[Int] { }

// and some java code
public class J {
public void sigs() {
B b = new B();
b.g(b.f());
}
}

Chris Twiner
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: scala's signature dish: appetizer

Seems I really must get on trunk you guys are having so much fun there.

Perhaps more importantly, assuming this was in Zürich, how was the restaurant?

On 11 Mar 2011 21:13, "Paul Phillips" <paulp [at] improving [dot] org> wrote:

Scala's Signature Dish, Chapter I

1) This ends with a puzzle.  You like puzzles, don't you?
2) A couple days ago retronym took me to the restaurant "Scala" where I actually ordered their signature dish.  No enlightenments yet but I'm still hopeful.

I am going to attempt to distill the signature problem and why it isn't fixed yet, but in case I can draw in more interested parties by uncharacteristically documenting a little bit, here is a quick overview of signatures.  There are two bytecode constructs which communicate the key characteristics of the blobs of data you find in there.  The older, pre-generics one is called a "descriptor" and the one tacked on later a "signature", although the latter term is often misused for both.  Fields and methods get both varieties; class definitions only get signatures. Descriptors have no knowledge of type parameters, but they are approximately equivalent to a signature after erasing the types.

Why do we care about signatures? Here is how things look to java, and everything else in the world beyond the scala compiler (which reads its own, much richer signature format when parsing scala bytecode, but relies on java generic signatures for reading java since that's all there is.)

 // ...with signatures
 class Cell[T](val x: T)   // put a T in, get a T out
 // ...without signatures
 class Cell(val x: Object) // put whatever you want in, take an Object out

To see some sweet signature action, download a 2.9 nightly and:

 // define this in the repl
 class Bippy[A <: Function0[_ <: Comparable[_]]] extends Mutable {
   var x: List[A] = _
   def f[B, C <: A](x: Int, y: B) = ((x, y))
 }

 scala> :javap -verbose Bippy
 // trimmed to relevant constant pool entries
 const #3 = Asciz      x;
 const #4 = Asciz      Lscala/collection/immutable/List;;
 const #5 = Asciz      Lscala/collection/immutable/List<TA;>;;
 const #18 = Asciz     f;
 const #19 = Asciz     (ILjava/lang/Object;)Lscala/Tuple2;;
 const #38 = Asciz <B:Ljava/lang/Object;C:TA;>(ITB;)Lscala/Tuple2<Ljava/lang/Object;TB;>;;
 const #45 = Asciz <A::Lscala/Function0<+Ljava/lang/Comparable<*>;>;>Ljava/lang/Object;Lscala/Mutable;Lscala/ScalaObject;;

 [4] field descriptor    // notice the raw List type
 [5] field signature     // "TA;" means "type parameter A"
 [19] method descriptor  // "I" is primitive Int; "L...;" is a class.
 [38] method signature   // "C:TA" means tparam C is bounded by A.
 [45] class signature    // "+" is covariance; "*" a wildcard.

Notice there is a lot more information in the generic signatures.  That is the point.  There are a number of restrictions on exactly how you create a signature.  The most important for our purposes is that you cannot parameterize a type on primitives.  The one-character primitive type tags cannot appear as type arguments or type bounds unless you enjoy the music of breakage.

Before we come to the next chapter wherein we examine the problem, consider the following scala code.  The questions for you are:

1) What signatures should go into classes A and B?
1b) "Eclipse crashes."  Pay $50 and go back to square 1.
2) Given those signatures, does the java code compile?
2b) "You broke reflection."  Lose a turn.
3) Try again.  Would you like to buy some bridge methods?
3b) The troll grabbed you! Pay $100 or be eaten and lose infinity turns.
4) Do you like apples? How do you like these apples?

 // it's some scala code
 trait A[T] {
   def f(): T = Predef.error("")
   def g(x: Int) = ()
 }
 class B extends A[Int] { }

 // and some java code
 public class J {
   public void sigs() {
     B b = new B();
     b.g(b.f());
   }
 }

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