- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Fwd: Scala Compiler question
Wed, 2009-02-25, 04:40
Hi,
The only public member called 'name' in JavaPerson is a method. In that case, when you do jperson.name = " ", is the same of jperson.name() = " ". (in scala parenthesis are optional).
In scala classes, the setter/getter are called implicit, but when you are using java classes, you must use the right functions signatures. In that case is to use the getName/setName.
When you have a 'var name' member in a scala class, implicit you have the method 'name' (getter) and a method 'name_=' (setter).
Looking by this generated byte code, it seems confusing. Have you seen the byte code generated by the use of the scala/java class? I guess the compiler change the code in this time.
[]s
Victor
On Tue, Feb 24, 2009 at 3:33 PM, Andres Almiray <aalmiray@yahoo.com> wrote:
Hi,
I've been doing a series of experiments to generate Scala friendly classes
from Java.
As you know the following Scala class:
class ScalaPerson(var name:String)
is compiled to the following byte code:
Compiled from "ScalaPerson.scala"
public class ScalaPerson extends java.lang.Object implements
scala.ScalaObject{
private java.lang.String name;
public ScalaPerson(java.lang.String);
public void name_$eq(java.lang.String);
public java.lang.String name();
public int $tag() throws java.rmi.RemoteException;
}
with that info in mind I create a JavaPerson class whose byte code output is
pretty much the same as ScalaPerson plus get/setName following the JavaBeans
convention:
Compiled from "JavaPerson.java"
public class JavaPerson extends java.lang.Object implements
scala.ScalaObject{
private java.lang.String name;
public JavaPerson(java.lang.String);
public void setName(java.lang.String);
public void name_$eq(java.lang.String);
public java.lang.String getName();
public java.lang.String name();
public int $tag();
}
The Java code not surprisingly is very verbose
import scala.ScalaObject;
public class JavaPerson implements ScalaObject {
private String name;
public JavaPerson( String name ) {
this.name = name;
}
public void setName( String name ) {
this.name = name;
}
public void name_$eq( String name ) {
setName(name);
}
public String getName() {
return name;
}
public String name() {
return getName();
}
public int $tag() {
return 0;
}
}
Now the problem comes when using JavaPerson from Scala
object Output {
def main(args: Array[String]) {
var sperson: ScalaPerson = new ScalaPerson("Scala")
println(sperson.name)
var jperson: JavaPerson = new JavaPerson("Java")
println(jperson.name)
sperson.name = "ScalaScala"
println(sperson.name)
// jperson.name = "JavaJava"
jperson.name_$eq( "JavaJava")
println(jperson.name)
}
}
when the comment is removed the compiler yields the following error
Output.scala:12: error: reassignment to val
jperson.name = "JavaJava"
^
one error found
scalac -version -> Scala compiler version 2.7.3.final -- Copyright
2002-2009, LAMP/EPFL
javac -version -> javac 1.6.0_12
I'll appreciate any pointers you can give me, thanks!
--
View this message in context: http://www.nabble.com/Scala-Compiler-question-tp22187692p22187692.html
Sent from the Scala - User mailing list archive at Nabble.com.
--
GNU/Linux user #5f5f5f - http://counter.li.org
--
GNU/Linux user #5f5f5f - http://counter.li.org
Thu, 2009-02-26, 15:57
#2
Re: Fwd: Scala Compiler question
The Scala compiler treats Scala files specially. There is a ScalaSig
classfile attribute that holds type information, including the fact
that a member is a method or a val/var. Normally you cannot trick the
compiler by naming convention alone. Maybe there's a simpler way to
achieve what you need. What exactly are you trying to do?
cheers,
iulian
On Wed, Feb 25, 2009 at 6:36 PM, Andres Almiray wrote:
>
>
> Victor Mateus Oliveira wrote:
>>
>> Looking by this generated byte code, it seems confusing. Have you seen the
>> byte code generated by the use of the scala/java class? I guess the
>> compiler
>> change the code in this time.
>>
>
> Yes, the main difference (other than name() calling setName() for example)
> is in the constructor
>
> javap -c ScalaPerson
> Compiled from "ScalaPerson.scala"
>
> public class ScalaPerson extends java.lang.Object implements
> scala.ScalaObject{
> public ScalaPerson(java.lang.String);
> Code:
> 0: aload_0
> 1: aload_1
> 2: putfield #12; //Field name:Ljava/lang/String;
> 5: aload_0
> 6: invokespecial #17; //Method java/lang/Object."":()V
> 9: return
>
> javap -c JavaPerson
>
> Compiled from "JavaPerson.java"
> public class JavaPerson extends java.lang.Object implements
> scala.ScalaObject{
> public JavaPerson(java.lang.String);
> Code:
> 0: aload_0
> 1: invokespecial #1; //Method java/lang/Object."":()V
> 4: aload_0
> 5: aload_1
> 6: putfield #2; //Field name:Ljava/lang/String;
> 9: return
>
>
> If JavaPerson.name() is changed to perform direct field assignment then both
> compiled byte codes (scala/java) are identical for that particular method.
>
>
Thu, 2009-02-26, 19:57
#3
Re: Fwd: Scala Compiler question
What I'd like to do is build a bridge between Groovy and Scala, by having
Groovy code be idiomatic Scala compatible. Let's say you start with the
following trait:
trait Foo {
@BeanProperty var foo: String
}
when compiled it will generate the following (roughly equivalent) Java
interface:
public interface Foo {
public void foo_$eq( java.lang.String arg );
public void setFoo( java.lang.String arg );
public String foo();
public String getFoo();
}
Implementing said interface from Groovy is quite simple, at least for the
methods that follow the JavaBeans convention, given that Groovy
automatically generates get/set for each property, but the Scala friendly
methods have to be coded by hand
class GroovyFoo implements Foo {
String foo
void foo_$eq(String foo){ setFoo(foo) }
String foo(){ getFoo() }
}
This can get tiresome quickly as you increase the number of properties, also
if more than 1 Groovy class implements a trait. In order to reduce this
complexity the ASTtransformations framework could be used to generate the
boilerplate code like this
@Scalify
class GroovyFoo implements Foo {
String foo
}
So, while the generated byte code appears to be 100% compatible it turns out
it is not, due to the problem that spun this thread. Given what you've
already said (the ScalaSig attribute) it might be hard to accomplish this
feat, unless of course I can create a proper ScalaSig classfile attribute
using the ASTtransformations framework.
Cheers,
Andres
Iulian Dragos wrote:
>
> The Scala compiler treats Scala files specially. There is a ScalaSig
> classfile attribute that holds type information, including the fact
> that a member is a method or a val/var. Normally you cannot trick the
> compiler by naming convention alone. Maybe there's a simpler way to
> achieve what you need. What exactly are you trying to do?
>
> cheers,
> iulian
>
> On Wed, Feb 25, 2009 at 6:36 PM, Andres Almiray
> wrote:
>>
>>
>> Victor Mateus Oliveira wrote:
>>>
>>> Looking by this generated byte code, it seems confusing. Have you seen
>>> the
>>> byte code generated by the use of the scala/java class? I guess the
>>> compiler
>>> change the code in this time.
>>>
>>
>> Yes, the main difference (other than name() calling setName() for
>> example)
>> is in the constructor
>>
>> javap -c ScalaPerson
>> Compiled from "ScalaPerson.scala"
>>
>> public class ScalaPerson extends java.lang.Object implements
>> scala.ScalaObject{
>> public ScalaPerson(java.lang.String);
>> Code:
>> 0: aload_0
>> 1: aload_1
>> 2: putfield #12; //Field name:Ljava/lang/String;
>> 5: aload_0
>> 6: invokespecial #17; //Method java/lang/Object."":()V
>> 9: return
>>
>> javap -c JavaPerson
>>
>> Compiled from "JavaPerson.java"
>> public class JavaPerson extends java.lang.Object implements
>> scala.ScalaObject{
>> public JavaPerson(java.lang.String);
>> Code:
>> 0: aload_0
>> 1: invokespecial #1; //Method java/lang/Object."":()V
>> 4: aload_0
>> 5: aload_1
>> 6: putfield #2; //Field name:Ljava/lang/String;
>> 9: return
>>
>>
>> If JavaPerson.name() is changed to perform direct field assignment then
>> both
>> compiled byte codes (scala/java) are identical for that particular
>> method.
>>
>>
Tue, 2009-03-03, 21:07
#4
Re: Scala Compiler question
>>>>> "Andres" == Andres Almiray writes:
>> when the comment is removed the compiler yields the following error
>>
>> Output.scala:12: error: reassignment to val jperson.name =
>> "JavaJava" ^ one error found
>>
>> scalac -version -> Scala compiler version 2.7.3.final -- Copyright
>> 2002-2009, LAMP/EPFL javac -version -> javac 1.6.0_12
>>
>> I'll appreciate any pointers you can give me, thanks!
Maybe the problem is the missing ScalaSig attribute in the class file?
Tue, 2009-03-03, 21:17
#5
Re: Scala Compiler question
Seth Tisue wrote:
>
>>>>>> "Andres" == Andres Almiray writes:
>
> >> when the comment is removed the compiler yields the following error
> >>
> >> Output.scala:12: error: reassignment to val jperson.name =
> >> "JavaJava" ^ one error found
> >>
> >> scalac -version -> Scala compiler version 2.7.3.final -- Copyright
> >> 2002-2009, LAMP/EPFL javac -version -> javac 1.6.0_12
> >>
> >> I'll appreciate any pointers you can give me, thanks!
>
> Maybe the problem is the missing ScalaSig attribute in the class file?
>
Victor Mateus Oliveira wrote:
>
> Looking by this generated byte code, it seems confusing. Have you seen the
> byte code generated by the use of the scala/java class? I guess the
> compiler
> change the code in this time.
>
Yes, the main difference (other than name() calling setName() for example)
is in the constructor
javap -c ScalaPerson
Compiled from "ScalaPerson.scala"
public class ScalaPerson extends java.lang.Object implements
scala.ScalaObject{
public ScalaPerson(java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #12; //Field name:Ljava/lang/String;
5: aload_0
6: invokespecial #17; //Method java/lang/Object."":()V
9: return
javap -c JavaPerson
Compiled from "JavaPerson.java"
public class JavaPerson extends java.lang.Object implements
scala.ScalaObject{
public JavaPerson(java.lang.String);
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: aload_0
5: aload_1
6: putfield #2; //Field name:Ljava/lang/String;
9: return
If JavaPerson.name() is changed to perform direct field assignment then both
compiled byte codes (scala/java) are identical for that particular method.