Custom Search
|
Date: November 21, 2005
From: "Judson, Ross" <rjudson@xxxxxxxxxxxxxxxxxx>
Scala performs type inferencing -- making use of context to attempt a
determination of type. Does doing the same thing with traits make
sense? That is, if we define a trait to have a "signature" of some sort
(the set of abstract methods), could the compiler automatically
construct a view? Given:
trait BuySellProperty {
def buyProperty(address: String): boolean;
def sellProperty(address: String): boolean;
}
class Agent {
def buyProperty(address: String): boolean = {
Console.println("Buy"); true
}
def sellProperty(address: String): boolean = {
Console.println("Sell"); true
}
}
def usage[A %> BuySellProperty](bs: A) = bs.buyProperty("somewhere");
The compiler would automatically construct:
def view(agent: Agent): BuySellProperty;
The compiler can implement by building a flyweight object, or by
modifying the runtime rep of Agent have a "with" clause.
This goes to the "duck typing" issue. I'm not entirely sure about
whether that is advisable or not. Scala's FunctionN[T...] notation
already performs this sort of thing. Trait inferencing opens this
mechanism up past functions to include more sophisticated protocols.
The essential "win" (and maybe it isn't one!) here is that a given class
need not formally commit to its set of types. The compiler can
determine if a class could be a member of a type, make that happen
automatically.
RJ
Date: November 21, 2005
From: Michel Schinz <Michel.Schinz@xxxxxxx>
In-reply-to:
<pan.2005.11.20.06.04.14.901106@xxxxxxxxx>
References:
<dldct1$69g$1@xxxxxxxxxxxxx> <9F4C4A76-C1A7-4066-9113-8B9A015987D1@xxxxxxx> <437AE457.4070909@xxxxxxxx> <437AE82B.3080606@xxxxxxx> <pan.2005.11.20.06.04.14.901106@xxxxxxxxx>
Le 20 nov. 05 à 07:04, Kannan Goundan a écrit : [...]
I'm curious; what are the implementation options? The two options I'm aware of:1. The current .Net implementation (multiple typeinfo objects shared byobject instances created with the same type parameters).2. Storing a reference to an array of type info objects (one element per type parameter) in each object. This is the best you can do with the JVM,right?
Not really. If you manage to find a way to suitably encode the types of your language into Java types, then you can use the run time types of the JVM to implement your own. This is the route taken by NextGen [1], where the NextGen type List<Int> is represented by the Java type List$Int (the actual name mangling is more complicated than that, but you get the idea). Unfortunately, the type system of Scala is too powerful to be encoded in that fashion.
I see the increased space usage but what causes the performance to be sobad? Is it the metadata creation that is so slow?
Yes (if by "metadata" you mean type representations). That said, the current implementation is not optimised, and does not cache type representations like the .NET implementation or Viroli's EGO compiler [2] do. It's certainly possible to do much better than the current implementation, although I doubt we could beat the .NET implementation, since we cannot modify the JVM.
Using a downcast or an "instanceof" check sometimes indicates a problem with the program's design (often caused by a limitation in the language'stype system). I run into such cases in Java or C++ but Scala's typesystem seems powerful enough to avoid forcing you to fall back on runtimechecks during "normal" programming.
The compiler itself produces thousands of instanceof tests in its encoding of pattern matching. The vast majority of them can be simplified to tests on the Java type of the objects, but not all. (And currently they aren't, because once again the implementation is not optimised).
Michel. [1] http://japan.cs.rice.edu/nextgen/[2] http://bart.disi.unige.it/EOS/modules/c-html/?elena/ publications.html#V-WOOD2004
Date: November 20, 2005
From: Kannan Goundan <cakoose@xxxxxxxxx>
References:
<dldct1$69g$1@xxxxxxxxxxxxx> <9F4C4A76-C1A7-4066-9113-8B9A015987D1@xxxxxxx> <437AE457.4070909@xxxxxxxx> <437AE82B.3080606@xxxxxxx>
On Wed, 16 Nov 2005 09:04:59 +0100, Burak Emir wrote: > No runtime types, unless we find an efficient encoding. Since we cannot > rely on anything from the JVM, seems unlikely we will ever have them. I'm curious; what are the implementation options? The two options I'm aware of: 1. The current .Net implementation (multiple typeinfo objects shared by object instances created with the same type parameters). 2. Storing a reference to an array of type info objects (one element per type parameter) in each object. This is the best you can do with the JVM, right? I see the increased space usage but what causes the performance to be so bad? Is it the metadata creation that is so slow? Using a downcast or an "instanceof" check sometimes indicates a problem with the program's design (often caused by a limitation in the language's type system). I run into such cases in Java or C++ but Scala's type system seems powerful enough to avoid forcing you to fall back on runtime checks during "normal" programming. Are there any particular uses of runtime type information people have in mind? Maybe some of them can be handled differently. - Kannan
Date: November 19, 2005
From: Burak Emir <Burak.Emir@xxxxxxx>
In-reply-to:
<dln9n7$lcg$1@xxxxxxxxxxxxx>
References:
<dln9n7$lcg$1@xxxxxxxxxxxxx>
Val wrote:
Hello. I have 2 questions : 1 - How to convert Int from/to Float ? What I want to do is : Math.sqrt(n.toFloat).toInt
n.asInstanceOf[Float]
2 - Is there a way to define a value inside a for comprehension ? I have : for (val a <- divisors(p); a*a < p; goodSum(a + (p/a))) yield Pair(a,p/a);Note that p/a is defined and maybe computed several time, and I'd rather write :for (val a <- divisors(p); val b = p/a; a < b; goodSum(a + b)) yield Pair(a,b);
It's slightly gross, but here's a solution for (val a <- divisors(p); val b <- List(p/a); a*a < p; goodSum(a + b)) yield Pair(a,p/a);We are thinking about introducing something like "val x = rhs" in for comprehension...
Thank you.
You're welcome. cheers, Burak -- Burak Emir http://lamp.epfl.ch/~emir
Date: November 19, 2005
From: Val <valery@xxxxxxxxxxx>
Hello.
I have 2 questions :
1 - How to convert Int from/to Float ?
What I want to do is :
Math.sqrt(n.toFloat).toInt
2 - Is there a way to define a value inside a for comprehension ?
I have :
for (val a <- divisors(p); a*a < p; goodSum(a + (p/a)))
yield Pair(a,p/a);
Note that p/a is defined and maybe computed several time, and I'd rather
write :
for (val a <- divisors(p); val b = p/a; a < b; goodSum(a + b))
yield Pair(a,b);
Thank you.
-- Valery
Date: November 18, 2005
From: Iulian Dragos <iulian.dragos@xxxxxxx>
In-reply-to:
<437D8E81.90609@xxxxxxx>
References:
<OF8D1F3868.63A9803B-ONC12570BC.00604010-C12570BC.0061ECB4@xxxxxxxxxxxxxxxxxxx> <437D8E81.90609@xxxxxxx>
On Fri, 2005-11-18 at 09:19 +0100, Burak Emir wrote:
> Hello Mathias,
>
> Mathias.Weyel@xxxxxxxxxx wrote:
>
> >Hi!
> >
> >As stated before, I am about to write a scala plugin for the Idea IDE by
> >Jetbrains. I was able to generate a lexer for the language (at the moment
> >omitting xml expressions) and syntax highlighting works already fine. The
> >only thing I don't understand is the third way of writing identifiers. The
> >"normal" (=Java) style and the special-character-identifiers were no
> >problem, but what's this "arbitrary string between back quotes"?
> >
> >
> >
> def `I am a method with an astonishingly long name that even can contain
> spaces`(x: Int) =
> `luckily the JVM supports arbitrary identifiers, so there is no reason
> why the language shouldn't`(x * 2);
Funny enough, it's not entirely true. The following program compiles and
runs fine with Java 1.4:
object Foo with Application {
val `a ` = 10;
def `a name`(x: Int) = x;
Console.println(`a name`(`a `));
}
But fails if we attempt to verify it:
$ scala -verify -cp classes Foo
Exception in thread "main" java.lang.ClassFormatError: Foo (Illegal
Method name "a name")
at java.lang.ClassLoader.defineClass0(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:539)
at java.security.SecureClassLoader.defineClass
(SecureClassLoader.java:123)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:251)
at java.net.URLClassLoader.access$100(URLClassLoader.java:55)
at java.net.URLClassLoader$1.run(URLClassLoader.java:194)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:187)
at java.lang.ClassLoader.loadClass(ClassLoader.java:289)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:274)
at java.lang.ClassLoader.loadClass(ClassLoader.java:235)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:302)
I guess we should encode these names the same way we do with operators.
Iulian
Date: November 18, 2005
From: Burak Emir <Burak.Emir@xxxxxxx>
In-reply-to:
<OF8D1F3868.63A9803B-ONC12570BC.00604010-C12570BC.0061ECB4@xxxxxxxxxxxxxxxxxxx>
References:
<OF8D1F3868.63A9803B-ONC12570BC.00604010-C12570BC.0061ECB4@xxxxxxxxxxxxxxxxxxx>
Hello Mathias, Mathias.Weyel@xxxxxxxxxx wrote:
def `I am a method with an astonishingly long name that even can contain spaces`(x: Int) = `luckily the JVM supports arbitrary identifiers, so there is no reason why the language shouldn't`(x * 2);Hi! As stated before, I am about to write a scala plugin for the Idea IDE by Jetbrains. I was able to generate a lexer for the language (at the moment omitting xml expressions) and syntax highlighting works already fine. The only thing I don't understand is the third way of writing identifiers. The "normal" (=Java) style and the special-character-identifiers were no problem, but what's this "arbitrary string between back quotes"?
The far bigger problem is that of the parser. For the plugin to provide any kind of non-trivial support (code folding, outline, adv. highlighting, ...), a parser is needed. I would like to take the parser of the new scala compiler that is under development and put some adapter to the interface Idea provides for parsers. Can someone please give me some introduction to
And why did you write your own lexer then?
The parser (apart from the XML stuff) is mostly a quite standard LL(1) recursive descent parser. One function stands for one non-terminal, the decision on which righthand-side to take is based on the next token.the structure of the parser and how it works? Figuring out that all by myself could take quite some time whereas you developers know it pretty well I guess and could perhaps provide some brief advice quite easily.
scala-xml literals correspond to real XML, and XML is specified by a context-free grammar. It is impossible to give a regexp describing XML. It is just as impossible to give a regexp describing the language of correctly nested parentheses: A = ( A ) | A A | eps (you can apply the pumping lemma for regular languages to show this nonexistence formally.)Is it possible to describe scala-xml-literals as a regular expression for the JFlex-generated Lexer?
No need to despair though, I don't know about that IDE, but maybe you can at least achieve some syntax high-lighting by using plain regexps. Keep in mind that an XML expression is started by a '<' which is preceded by '(','{',' ','=' and followed by an XML name start character (not every '<' starts an XML expression).
cheers, Burak -- Burak Emir http://lamp.epfl.ch/~emir
Date: November 17, 2005
From: Jamie Webb <j@xxxxxxxxxxxxxxx>
In-reply-to:
<loom.20051117T214922-282@xxxxxxxxxxxxxx>
References:
<loom.20051117T214922-282@xxxxxxxxxxxxxx>
On Thu, Nov 17, 2005 at 08:54:39PM +0000, Erol Akarsu wrote: > How hard to call Scala from Java environment? I don't any example about this. Pretty easy. The main difficulty is that Scala has to make use of some name mangling in order to shoehorn its features into the Java ABI. Most notably, to instantiate a Scala class from Java, you have to use 'new MyClass$class()' (though apparently this is going away soon). And of course all the Scala generic types get erased and replaced with Object. > Have we done any benchmarking on Scala? I've done a very small amount, but it depends very much on how you use the language: if you stick to the subset of Scala that is pretty much identical to Java, then the Scala compiler will produce pretty much identical bytecode (in practice Scala appears to be one or two percent slower; I haven't looked at the generated code itself to see why). However, Scala includes a number of features which make for nicer code, but are not as efficient at runtime, so if you make heavy use of those in inner loops you may see a more significant slowdown. In general speed is unlikely to be a reason to choose Java over Scala. If it were that important, you'd be writing native code. There are a couple of numbers available at shootout.alioth.debian.org, but no-one's found the time to contribute many Scala programs yet. -- Jamie Webb
Date: November 17, 2005
From: Erol Akarsu <eakarsu_33@xxxxxxxxx>
Hi: I am learning the scala which is combining all nice features from so many languages, that is excellent! How hard to call Scala from Java environment? I don't any example about this. It seems very easy to call any Java class from inside Scala, that is very good. Have we done any benchmarking on Scala? How faster or slower than Java? Thanks Best Regards Erol Akarsu
Date: November 17, 2005
From: Mathias.Weyel@xxxxxxxxxx
Hi! As stated before, I am about to write a scala plugin for the Idea IDE by Jetbrains. I was able to generate a lexer for the language (at the moment omitting xml expressions) and syntax highlighting works already fine. The only thing I don't understand is the third way of writing identifiers. The "normal" (=Java) style and the special-character-identifiers were no problem, but what's this "arbitrary string between back quotes"? The far bigger problem is that of the parser. For the plugin to provide any kind of non-trivial support (code folding, outline, adv. highlighting, ...), a parser is needed. I would like to take the parser of the new scala compiler that is under development and put some adapter to the interface Idea provides for parsers. Can someone please give me some introduction to the structure of the parser and how it works? Figuring out that all by myself could take quite some time whereas you developers know it pretty well I guess and could perhaps provide some brief advice quite easily. Is it possible to describe scala-xml-literals as a regular expression for the JFlex-generated Lexer? cheers Mathias ----------------------------------------- Diese E-Mail enthaelt vertrauliche oder rechtlich geschuetzte Informationen. Wenn Sie nicht der beabsichtigte Empfaenger sind, informieren Sie bitte sofort den Absender und loeschen Sie diese E-Mail. Das unbefugte Kopieren dieser E-Mail oder die unbefugte Weitergabe der enthaltenen Informationen ist nicht gestattet. The information contained in this message is confidential or protected by law. If you are not the intended recipient, please contact the sender and delete this message. Any unauthorised copying of this message or unauthorised distribution of the information contained herein is prohibited.
Date: November 17, 2005
From: Andrew Kennedy <akenn@xxxxxxxxxxxxx>
References:
<dldct1$69g$1@xxxxxxxxxxxxx> <9F4C4A76-C1A7-4066-9113-8B9A015987D1@xxxxxxx> <dlf952$i0h$1@xxxxxxxxxxxxx> <437B356A.8000706@xxxxxxx> <20051116171230.GA16192@xxxxxxxxxxxxxxxxx>
Matt Hellige <matt <at> immute.net> writes: > > Do you have any comments on the paper "GADTs and Object-Oriented > Programming" by Kennedy and Russo? ACM has the paper locked up, but > there's an abstract at http://research.microsoft.com/~akenn/generics/. > I've just updated that page with a pointer to the paper. Find it at http://research.microsoft.com/~akenn/generics/gadtoop.pdf Cheers - Andrew.
Date: November 17, 2005
From: Gary T. Leavens <leavens@xxxxxxxxxxxxxx>
Hi all, I now have some teaching materials to share about Scala. They are on my web site for our graduate course "Programming Languages 1" (Com S 541) at Iowa State University. The link that should stay live for this is: http://www.cs.iastate.edu/~leavens/ComS541Fall05/ There is are two homeworks in http://www.cs.iastate.edu/~leavens/ComS541Fall05/homework/ a directory of some samples http://www.cs.iastate.edu/~leavens/ComS541Fall05/scala/src/ and some strangely formatted lecture notes (in English) http://www.cs.iastate.edu/~leavens/ComS541Fall05/lectures/scala/ Feel free to look around. (I'm happy to hear comments, but I'm unlikely to be able to respond to lots of email about this. :-) Gary T. Leavens
Date: November 16, 2005
From: Geoffrey Alan Washburn <geoffw@xxxxxxxxxxxxx>
In-reply-to:
<437B356A.8000706@xxxxxxx>
References:
<dldct1$69g$1@xxxxxxxxxxxxx> <9F4C4A76-C1A7-4066-9113-8B9A015987D1@xxxxxxx> <dlf952$i0h$1@xxxxxxxxxxxxx> <437B356A.8000706@xxxxxxx>
Martin Odersky wrote:
Or alternately things like val foo : List[T] if (foo.isInstanceOf(List[String]]) { // type of foo is refined to be List[String] // without vacuous cast }The last you can do for monomorphic types with a pattern match: val foo: Any; foo match { case f: String => // here, f is known to be of type String } But it works for List[String] only if option -Xruntimetypes is given.In fact, the new version of Scala will have support for GADT's which should enable a programming style where type representations can be constructed and passed explicitly. Once this works, we will evaluate whether or not this can adequately replace runtime types.
Thanks for the information. I was mostly curious to see how the technology compared/complimented Stephanie Weirich's work on Type-directed Java.
Date: November 16, 2005
From: Matt Hellige <matt@xxxxxxxxxx>
In-reply-to:
<437B356A.8000706@xxxxxxx>
References:
<dldct1$69g$1@xxxxxxxxxxxxx> <9F4C4A76-C1A7-4066-9113-8B9A015987D1@xxxxxxx> <dlf952$i0h$1@xxxxxxxxxxxxx> <437B356A.8000706@xxxxxxx>
[Martin Odersky <martin.odersky@xxxxxxx>] > > In fact, the new version of Scala will have support for GADT's which > should enable a programming style where type representations can be > constructed and passed explicitly. Once this works, we will evaluate > whether or not this can adequately replace runtime types. > This is great news! Do you have any info on the Scala implementation of GADTs? Is there a paper available or anything? I'm not really convinced that this will eliminate the need for RTTI, but it seems that you're not either... Do you have any comments on the paper "GADTs and Object-Oriented Programming" by Kennedy and Russo? ACM has the paper locked up, but there's an abstract at http://research.microsoft.com/~akenn/generics/. Thanks! Matt -- Matt Hellige matt@xxxxxxxxxx
Date: November 16, 2005
From: Stéphane Micheloud <stephane.micheloud@xxxxxxx>
Dear Scala users, Version 1.4.0.3 of Scala has been released ! Changes are listed on the following page: http://scala.epfl.ch/downloads/changes.html -- The Scala Team
Date: November 16, 2005
From: Martin Odersky <martin.odersky@xxxxxxx>
In-reply-to:
<dlf952$i0h$1@xxxxxxxxxxxxx>
References:
<dldct1$69g$1@xxxxxxxxxxxxx> <9F4C4A76-C1A7-4066-9113-8B9A015987D1@xxxxxxx> <dlf952$i0h$1@xxxxxxxxxxxxx>
Or alternately things like
val foo : List[T]
if (foo.isInstanceOf(List[String]]) {
// type of foo is refined to be List[String]
// without vacuous cast
}
The last you can do for monomorphic types with a pattern match:
val foo: Any;
foo match {
case f: String =>
// here, f is known to be of type String
}
But it works for List[String] only if option -Xruntimetypes is given.
In fact, the new version of Scala will have support for GADT's which
should enable a programming style where type representations can be
constructed and passed explicitly. Once this works, we will evaluate
whether or not this can adequately replace runtime types.
Cheers -- Martin
Date: November 16, 2005
From: Geoffrey Alan Washburn <geoffw@xxxxxxxxxxxxx>
In-reply-to:
<9F4C4A76-C1A7-4066-9113-8B9A015987D1@xxxxxxx>
References:
<dldct1$69g$1@xxxxxxxxxxxxx> <9F4C4A76-C1A7-4066-9113-8B9A015987D1@xxxxxxx>
Michel Schinz wrote:
Le 15 nov. 05 à 20:28, Geoffrey Alan Washburn a écrit :The changelog references experimental support for something called "runtime types", but I couldn't find anything in the document explaining what exactly runtime types allow in Scala. Can someone elaborate?They allow pretty much the same things as Java run time types, but with full Scala types. This means that the two primitives "isInstanceOf" and "asInstanceOf" work as you would expect. For example, an expression like:List(1).isInstanceOf[List[String]]returns "false" as it should with run time types enabled, and not "true" as it does currently.
Okay, I was actually kind of hoping for some features that allowed for comparisons of type parameters themselves say
if(T subtypeof U) {
....
} else {
....
}
Or alternately things like
val foo : List[T]
if (foo.isInstanceOf(List[String]]) {
// type of foo is refined to be List[String]
// without vacuous cast
}
Date: November 16, 2005
From: robert kuzelj <robert.kuzelj@xxxxxxxx>
In-reply-to:
<437AE82B.3080606@xxxxxxx>
References:
<dldct1$69g$1@xxxxxxxxxxxxx> <9F4C4A76-C1A7-4066-9113-8B9A015987D1@xxxxxxx> <437AE457.4070909@xxxxxxxx> <437AE82B.3080606@xxxxxxx>
hi burak, >> can anybody confirm this? > No runtime types, unless we find an efficient encoding. Since we cannot > rely on anything from the JVM, seems unlikely we will ever have them. so in order to have a efficient implementation you optimize it away? having a "slow" version of something is ok for almost 95% of all solutions imo. having a solution where i would have to recompile all libs to enable runtime times is ugly but ok. having no runtime times (erased) at all...bummer! maybe a bit of zen by master knuth will be appropriate: "premature optimization is the root of all evil". > We are developing a reflection API, but it will have to deal with erased > types, like Java. in a language that has heavily "generified" libraries this is as good as saying you have only 1/3 of the typeinfos at your hands. maybe the powers that be can ponder upon that decision once again. ciao robertj
Date: November 16, 2005
From: Burak Emir <Burak.Emir@xxxxxxx>
In-reply-to:
<437AE457.4070909@xxxxxxxx>
References:
<dldct1$69g$1@xxxxxxxxxxxxx> <9F4C4A76-C1A7-4066-9113-8B9A015987D1@xxxxxxx> <437AE457.4070909@xxxxxxxx>
robert kuzelj wrote:
No runtime types, unless we find an efficient encoding. Since we cannot rely on anything from the JVM, seems unlikely we will ever have them.hi,1. They exist only in the current version of the Scala compiler, as far as I know. Since the compiler is currently being rewritten, chances are they will disappear in the process. (I don't know whether there are plans to port the stuff one day, this is something only people still affiliated with the project know).can anybody confirm this?
[...]
We are developing a reflection API, but it will have to deal with erased types, like Java.compared to the current state of affairs. It seems that for many practical purposes, the erasure-based approximation of run time types that we have is enough.as long as the reflective faciltities and metaprogramming options are underdeveloped if existing at all you might be right. but in general i wouldnt agree on that.
cheers, Burak -- Burak Emir http://lamp.epfl.ch/~emir
Date: November 16, 2005
From: robert kuzelj <robert.kuzelj@xxxxxxxx>
In-reply-to:
<9F4C4A76-C1A7-4066-9113-8B9A015987D1@xxxxxxx>
References:
<dldct1$69g$1@xxxxxxxxxxxxx> <9F4C4A76-C1A7-4066-9113-8B9A015987D1@xxxxxxx>
hi, > 1. They exist only in the current version of the Scala compiler, as > far as I know. Since the compiler is currently being rewritten, chances > are they will disappear in the process. (I don't know whether there are > plans to port the stuff one day, this is something only people still > affiliated with the project know). can anybody confirm this? > 2. It takes some effort to be able to actually use them, as you have > to recompile all the standard libraries with run time types enabled first. > > 3. They slow down *all* programs, sometimes quite consequently (by > 100% in some cases), performance is in the eye of the beholder. and quite frankly they don't bring that much > compared to the current state of affairs. It seems that for many > practical purposes, the erasure-based approximation of run time types > that we have is enough. as long as the reflective faciltities and metaprogramming options are underdeveloped if existing at all you might be right. but in general i wouldnt agree on that. ciao robertj
Date: November 16, 2005
From: Michel Schinz <Michel.Schinz@xxxxxxx>
In-reply-to:
<dldct1$69g$1@xxxxxxxxxxxxx>
References:
<dldct1$69g$1@xxxxxxxxxxxxx>
Le 15 nov. 05 à 20:28, Geoffrey Alan Washburn a écrit :
The changelog references experimental support for something called "runtime types", but I couldn't find anything in the document explaining what exactly runtime types allow in Scala. Can someone elaborate?
They allow pretty much the same things as Java run time types, but with full Scala types. This means that the two primitives "isInstanceOf" and "asInstanceOf" work as you would expect. For example, an expression like:
List(1).isInstanceOf[List[String]]returns "false" as it should with run time types enabled, and not "true" as it does currently.
That said, if you're interested in run time types, there are a few caveats you should be aware of:
1. They exist only in the current version of the Scala compiler, as far as I know. Since the compiler is currently being rewritten, chances are they will disappear in the process. (I don't know whether there are plans to port the stuff one day, this is something only people still affiliated with the project know).
2. It takes some effort to be able to actually use them, as you have to recompile all the standard libraries with run time types enabled first.
3. They slow down *all* programs, sometimes quite consequently (by 100% in some cases), and quite frankly they don't bring that much compared to the current state of affairs. It seems that for many practical purposes, the erasure-based approximation of run time types that we have is enough.
Michel.
Date: November 15, 2005
From: Geoffrey Alan Washburn <geoffw@xxxxxxxxxxxxx>
The changelog references experimental support for something called "runtime types", but I couldn't find anything in the document explaining what exactly runtime types allow in Scala. Can someone elaborate?
Date: November 14, 2005
From: "Judson, Ross" <rjudson@xxxxxxxxxxxxxxxxxx>
object main {
def main(args : Array[String]) : Unit = {
import swing._;
val helloButton = button("Hello");
val testButton = button("Testing")(e => Console.println("Test button clicked."));
val f = frame +
North / (flowPanel + "Hello Label:" + helloButton + button("Testing")) +
South / (flowPanel + "First Label" + "Second Label:" + testButton) +
West / (verticalBox +
"First Label" +
"Second Label" +
"<html>This is <b>bold</b></html>") +
East / (gridBagPanel + GridInset(4,4,4,4) +
"grid bag a" > "gb b" > "gc c" >|
"grid bag d" >- "span" >|
button("Gotcha") > "this is a long line" ) +
Center / (panel + Background(java.awt.Color.BLUE.darker()));
helloButton(evt => { helloButton.setText("clicked"); f.jc.validate() });
f.exitOnClose;
f.title = "Packed up!";
f.visible = true;
}
object swing {
import java.awt._;
import java.awt.event._;
import javax.swing._;
import javax.swing.event._;
val borderLayout = new BorderLayout();
type JFunc = (JComponent) => unit;
trait JApply {
def / (comp: JComponent) : JFunc;
}
trait Setup[T] {
def apply(t: T): unit;
}
trait Setter extends Setup[JComponent];
case class Constraint(con: Object) with JApply {
def / (comp: JComponent): JFunc = parent => parent.add(comp, con);
}
val Center = Constraint(BorderLayout.CENTER);
val North = Constraint(BorderLayout.NORTH);
val South = Constraint(BorderLayout.SOUTH);
val East = Constraint(BorderLayout.EAST);
val West = Constraint(BorderLayout.WEST);
val flowLayout = new FlowLayout();
def frame = new SwingFrame();
def frame(tl: String) = { val f = new SwingFrame(); f.title = tl; f }
def panel = new SwingPanel();
def flowPanel = panel + flowLayout;
def gridBagPanel = new GridBagPanel();
class GridBagPanel extends SwingPanel {
val gc = new GridBagConstraints();
gc.gridx = 0; gc.gridy = 0;
setLayout(new GridBagLayout());
lastConstraint = gc;
private def jfunc(comp: JComponent) : JFunc = parent => parent.add(comp, gc);
def xmove(comp: Swing, n: int): this.type = {
gc.gridx = gc.gridx + n;
jc.add(comp, gc);
this;
}
def ymove(comp: Swing, n: int): this.type = {
gc.gridy = gc.gridy + n;
jc.add(comp, gc);
this;
}
def moveto(comp: Swing, x: int, y: int): this.type = {
gc.gridx = x;
gc.gridy = y;
jc.add(comp, gc);
this;
}
def >! (comp: Swing): this.type = {
jc.add(comp, gc);
this;
}
def > (comp: Swing) = xmove(comp, 1);
def >> (comp: Swing) = xmove(comp, 2);
def >>> (comp: Swing) = xmove(comp, 3);
def < (comp: Swing) = xmove(comp, -1);
def << (comp: Swing) = xmove(comp, -2);
def <<< (comp: Swing) = xmove(comp, -3);
def >- (comp: Swing) = { gc.gridwidth = 2; xmove(comp, 1) }
def >-- (comp: Swing) = { gc.gridwidth = 3; xmove(comp, 1) }
def >| (comp: Swing): this.type = moveto(comp, 0, gc.gridy + 1);
def >| (gs: GridSetter): this.type = { gs(this); this}
def >| (setter: Setup[this.type]): this.type = { setter(this); this }
}
trait GridSetter extends Setup[GridBagPanel];
case class GridInset(top: int, left: int, bottom: int, right: int) extends GridSetter {
def apply(gb: GridBagPanel): unit = {
Console.println("Grid Inset");
gb.gc.insets = new Insets(top, left, bottom, right);
}
}
case class Remainder extends GridSetter {
def apply(gb: GridBagPanel): unit = gb.gc.gridwidth = GridBagConstraints.REMAINDER;
}
def box = new SwingBox(BoxLayout.Y_AXIS);
def verticalBox = box;
def horizontalBox = new SwingBox(BoxLayout.X_AXIS);
def borderPanel = panel;
def button = new SwingButton();
def button(text: String) = new SwingButton(text);
case class Background(color: Color) extends Setter {
def apply(comp: JComponent) = comp.setBackground(color);
}
def background(color: Color): JFunc = x => x.setBackground(color);
type ActionFunction = (ActionEvent) =>unit;
type ActionSource[T] = (T) => unit;
type SimpleAction = () => unit;
def view(af: ActionFunction) : ActionListener = new ActionListener() {
def actionPerformed(event: ActionEvent) = af(event);
}
// def view(str: String): JComponent = new SwingLabel(str);
def view(s : Swing): JComponent = s.jc;
trait SwingComponent {
def sc: Swing;
def jc: JComponent;
var lastConstraint: Object;
def setLayout(layout: LayoutManager) : unit;
def plusComponent(comp: JComponent): this.type = { jc.add(comp, lastConstraint); this }
def layout(layout: LayoutManager): this.type = { setLayout(layout); this };
def center(comp: JComponent): this.type;
def north(comp: JComponent): this.type;
def west(comp:JComponent): this.type;
def south(comp: JComponent): this.type;
def east(comp:JComponent): this.type;
def click(func: SimpleAction): this.type = { func(); this }
def click(click: ActionFunction): this.type = {
if (this.isInstanceOf[AbstractButton])
this.asInstanceOf[AbstractButton].addActionListener(click);
this;}
def apply(clk: ActionFunction): this.type = click(clk);
def + (str: String): this.type = plusComponent(new SwingLabel(str));
def + (layoutMan: LayoutManager): this.type = layout(layoutMan);
def + (comp: JComponent): this.type = plusComponent(comp);
def + (constraint: Constraint): this.type = { lastConstraint = constraint.con; this }
def + (jfunc: JFunc): this.type = { jfunc(jc); this }
def + (setter: Setup[this.type]): this.type = { setter(this); this }
def + (setter: Setter): this.type = { setter(jc); this }
def visible = jc.isVisible();
def visible_= (v: boolean) = jc.setVisible(v);
}
trait Swing: JComponent with SwingComponent {
def sc: Swing = this;
def jc: JComponent = this;
private def bl(comp: JComponent, pos: Object): this.type = { jc.add(comp, pos); this }
def center(comp: JComponent): this.type = bl(comp, Center);
def north(comp: JComponent): this.type = bl(comp, North);
def south(comp: JComponent): this.type = bl(comp, South);
def west(comp: JComponent): this.type = bl(comp, West);
def east(comp: JComponent): this.type = bl(comp, East);
}
def view(str: String): Swing = new SwingLabel(str);
class SwingHelp {
var lastConstraint: Object = _;
}
class SwingBox(axis: int) extends Box(axis) with Swing with SwingHelp {
}
class SwingButton extends JButton with Swing with SwingHelp {
def t = getText();
def t_= (text: String) = setText(text);
def this(text: String) = { this(); setText(text); }
}
class SwingPanel extends JPanel with Swing with SwingHelp {
setLayout(borderLayout);
}
class SwingLabel(text: String) extends JLabel(text) with Swing with SwingHelp {
}
class SwingFrame extends JFrame with SwingComponent with SwingHelp {
def title: String = getTitle();
def title_=(t: String) = setTitle(t);
def contentPane: SwingPanel = getContentPane().asInstanceOf[SwingPanel];
def sc: Swing = contentPane;
def jc: JComponent = contentPane;
def center(comp: JComponent): this.type = { contentPane.center(comp); this }
def north(comp: JComponent): this.type = { contentPane.north(comp); this }
def south(comp: JComponent): this.type = { contentPane.south(comp); this }
def east(comp: JComponent): this.type = { contentPane.east(comp); this }
def west(comp: JComponent): this.type = { contentPane.west(comp); this }
def exitOnClose: this.type = { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this }
override def visible = isVisible();
override def visible_= (v: boolean) = setVisible(v);
setContentPane(panel);
contentPane.setName(getName() + ".contentPane");
setLocationByPlatform(true);
setSize(800, 600);
}
}
}
Date: November 14, 2005
From: Iulian Dragos <iulian.dragos@xxxxxxx>
In-reply-to:
<43778F3B.3030606@xxxxxxxx>
References:
<43778F3B.3030606@xxxxxxxx>
On Sun, 2005-11-13 at 20:08 +0100, robert kuzelj wrote:
> slowly moving my self from one hurdle to the next.
> so here the next one:
>
> abstract class OuterBase
> {
> type self <: InnerBase;
>
> abstract class InnerBase: self
> {
> def get: self;
> }
> }
>
> abstract class OuterBaseUser
> {
> val ob: OuterBase;
> class InnerBase[T <: ob.InnerBase]
> {
> def exec(p: T):Unit =
> {
> var g = p.get;
> exec(g);
> }
> }
> }
>
> why do i get his error?
>
> [scalac] ....scala:153: type mismatch;
> [scalac] found : OuterBaseUser.this.ob.self
> [scalac] required: T
> [scalac] exec(g);
> [scalac] ^
>
The problem is that OuterBase#self and T are unrelated types. Method get
returns an object of type 'self', which is an arbitrary subtype of
OuterBase#InnerBase. Method 'exec' expects a T, which is (another)
arbitrary subtype of OuterBase#InnerBase (actually, ob.InnerBase, but
that's not essential here). They are not defined as being equal. If you
want them to be equal, you can simply remove the type parameter from
InnerBase, and use ob.self instead:
abstract class OuterBaseUser {
val ob: OuterBase;
class InnerBase {
def exec(p: ob.self):Unit = {
var g = p.get;
exec(g);
}
}
}
or move the type parameter from class level to method level:
class InnerBase {
def exec[T <: ob.self](p: T):Unit = {
var g = p.get;
exec(g);
}
}
this way, each call of 'exec' may have a different binding for T, and
the recursive call's T inside exec doesn't have to be equal to the T of
the value parameter p.
Iulian
Date: November 14, 2005
From: Jamie Webb <j@xxxxxxxxxxxxxxx>
In-reply-to:
<4377C3BD.5020000@xxxxxxxx>
References:
<43751187.2070405@xxxxxxxx> <20051112004641.GD11284@xxxxxxxxxxxxxxxx> <4377C3BD.5020000@xxxxxxxx>
On Sun, Nov 13, 2005 at 11:52:45PM +0100, robert kuzelj wrote:
> i played a bit around with your solution. one question
> i could answer for myself is: why did you choose the
> composition approach?
I like it because it reduces coupling between the data structure and
its contents, i.e. one has Node[Foo] just as List[Foo], etc. The only
reason the NodeContent trait is required at all is to support the odd
createChild operation.
To see how this is useful, consider for example the situation where
you want the same data structured in several different ways. If the
Node is built right into the data, the data can only possibly be a
member of one tree. See Stroustrup's sorry attempts to justify
virtual/non-virtual base classes in C++ for more insight...
If your intention is really to create a class of different-but-similar
data structures, then the subclassing solution probably makes more
sense. Indeed, Node may be better thought of as a mixin rather than a
base class, since all it's doing is providing a couple of reusable
methods. Regardless, it's certainly nicer than the first solution I
gave.
BTW you can avoid the casting business using self-types again:
abstract class Node[A <: Node[A]] : A
{
var parent : A = null;
private var children : Map[String, A] = null;
def getChild(key: String) : A = this;
def addChild(child : Node[A]) : A = this;
def createChild() : A;
}
-- Jamie Webb
Date: November 13, 2005
From: robert kuzelj <robert.kuzelj@xxxxxxxx>
In-reply-to:
<20051112004641.GD11284@xxxxxxxxxxxxxxxx>
References:
<43751187.2070405@xxxxxxxx> <20051112004641.GD11284@xxxxxxxxxxxxxxxx>
hi jamie,
> But, I imagine this can be refactored such that your
> implementation-specific members are stored using composition, giving
> the following, which might be nicer to use:
>
> class Node[A <: NodeContent[A]](val content : A)
> {
> var parent : Node[A] = null;
> private var children : Map[String, Node[A]] = null;
>
> def getChild(key: String) : Node[A] = null;
> def addChild(child : Node[A]) : Node[A] = null;
> def createChild() : Node[A] = content.createChild();
> }
>
> trait NodeContent[A <: NodeContent[A]]
> {
> def createChild() : Node[A];
> }
>
> class Foo extends NodeContent[Foo]
> {
> def createChild() = null;
> def foo : Node[Foo] = null;
> }
>
> object NodeTest
> {
> // Avoid having to select the content explicitly.
> // Unfortunately this must be done separately for each
> // NodeContent, since views can't return type variables.
> // Probably this is just obfuscation anyway.
> def view(x : Node[Foo]) : Foo = x.content;
>
> def main(argv : Arr[String]) = {
> var foon = new Node(new Foo);
> foon = foon.createChild().foo.parent;
> }
> }
i played a bit around with your solution. one question
i could answer for myself is: why did you choose the
composition approach?
why not use a pure node subclassing approach like this?
<code>
import scala.collection.mutable.Map;
abstract class Node[A <: Node[A]]
{
var parent : Node[A] = null;
private var children : Map[String, Node[A]] = null;
def getChild(key: String) : Node[A] = this;
def addChild(child : Node[A]) : Node[A] = this;
def createChild() : Node[A];
}
class FooNode extends Node[FooNode]
{
def createChild() = new FooNode;
def foo : FooNode = this;
}
class BarNode extends Node[BarNode]
{
def createChild() = new BarNode;
def bar : BarNode = this;
}
//ok i have to do to a bit of view magic and a type case.
def view(x : Node[FooNode]) : FooNode = x.asInstanceOf[FooNode];
def view(x : Node[BarNode]) : BarNode = x.asInstanceOf[BarNode];
var foon = new FooNode;
foon = foon.createChild().foo.parent.foo;
var barn: BarNode = new BarNode().bar.parent.createChild();
</code>
what additional benefits could one reap from your solution?
ciao robertj
Date: November 13, 2005
From: robert kuzelj <robert.kuzelj@xxxxxxxx>
slowly moving my self from one hurdle to the next.
so here the next one:
abstract class OuterBase
{
type self <: InnerBase;
abstract class InnerBase: self
{
def get: self;
}
}
abstract class OuterBaseUser
{
val ob: OuterBase;
class InnerBase[T <: ob.InnerBase]
{
def exec(p: T):Unit =
{
var g = p.get;
exec(g);
}
}
}
why do i get his error?
[scalac] ....scala:153: type mismatch;
[scalac] found : OuterBaseUser.this.ob.self
[scalac] required: T
[scalac] exec(g);
[scalac] ^
ciao robertj
Date: November 12, 2005
From: "Gabriel Riba" <griba2010@xxxxxx>
Hi! I have been using hotscripts.com to find software for several years, and recent-ly added some of my own and I thought why not add there some info about Scala. I think that you have a great tool that few people know. So I added some words in a salesman slang style. You will find it in the section http://hotscripts.com/Tools_and_Utilities/Development_Tools/index.html or more specifically this entry at http://hotscripts.com/Detailed/54233.html If you rate it, the entry will keep the foremost places. -------------------------------------------------------------------- Some time ago I found a web that keeps an index of popularity of programming languages http://www.tiobe.com/index.htm?tiobe_index I told them about Scala and another language that got my attention, Mercury at http://www.cs.mu.oz.au/research/mercury/ but they answered that the web presence of theese languages was too low to be monitored. So let's spread the word somehow. Salut! Gabriel Riba. Barcelona (Spain).
Date: November 12, 2005
From: Michal Politowski <mpol@xxxxxxxxxxxxxxxxxxx>
In-reply-to:
<4375EDDE.2010205@xxxxxxxx>
References:
<43751187.2070405@xxxxxxxx> <20051112004641.GD11284@xxxxxxxxxxxxxxxx> <4375BC67.4080705@xxxxxxxx> <4375C494.10203@xxxxxxxx> <20051112125634.GA17150@xxxxxxxxxxxxxxxxxxx> <4375EDDE.2010205@xxxxxxxx>
On Sat, 12 Nov 2005 14:27:58 +0100, robert kuzelj wrote:
> hi,
>
> > Well. You promise to return a Node, which is some as of yet undetermined
> > subtype of BaseNode, and then proceed to return an instance of BaseNode.
> > There is no guarantee here that a BaseNode is a Node, actually unless there
> > is an alias definition type Node = BaseNode it is not, so the compiler
> > protests.
>
> just to confirm: the type bound "X <: Y" states pure subtyping relation.
> it may not be read as "X may be a Y or a subytype of Y"?
In a type declaration
type X <: Y
it restricts X to be a subtype of Y, but we do not know which concrete subtype
yet.
So if it can be done with any Y it can be done with an (o: X)
but you cannot assume any specific subtype of Y (Y itself included) to be X.
> > Maybe you might get what you need by making addChild return type to be
> > this.type
> > if you want to return this from it.
> concerning the return value this is possible. but the implementation
> of addChild is a bit more "complex".
>
> type self <: BaseNode;
> abstract class BaseNode
> {
> protected var children_ : Map[String, self] = null;
> ...
> var parent: self = null;
> def key: String = ...
>
> def addChild(_child: self):self =
> {
> children_(_child.key) = _child;
> _child.parent = this;
> return this;
> }
> }
>
> well i can get away with the error on return in addChild
> by changing the declaration to "def addChild(_child: self):this.type"
> but i still have the same error on this line "_child.parent = this;"
> and i cant change that to " var parent: this.type = null;".
> (well sometimes that works - but is i have understood it would be
> wrong).
>
> so the question is can i somehow define "type self ?" to include
> BaseNode as well?
You cannot do that, if I understand what you mean.
But I just remembered about explicit self-typing.
How about:
type self <: BaseNode;
abstract class BaseNode : self {
...
def addChild(child: self): this.type = {
children(child.key) = child;
child.parent = this; // No problem here, this is considered to be of type
self
this
}
};
--
Michał Politowski
Talking has been known to lead to communication if practiced carelessly.
Date: November 12, 2005
From: robert kuzelj <robert.kuzelj@xxxxxxxx>
In-reply-to:
<20051112125634.GA17150@xxxxxxxxxxxxxxxxxxx>
References:
<43751187.2070405@xxxxxxxx> <20051112004641.GD11284@xxxxxxxxxxxxxxxx> <4375BC67.4080705@xxxxxxxx> <4375C494.10203@xxxxxxxx> <20051112125634.GA17150@xxxxxxxxxxxxxxxxxxx>
hi,
> Well. You promise to return a Node, which is some as of yet undetermined
> subtype of BaseNode, and then proceed to return an instance of BaseNode.
> There is no guarantee here that a BaseNode is a Node, actually unless there
> is an alias definition type Node = BaseNode it is not, so the compiler
> protests.
just to confirm: the type bound "X <: Y" states pure subtyping relation.
it may not be read as "X may be a Y or a subytype of Y"?
> Maybe you might get what you need by making addChild return type to be
> this.type
> if you want to return this from it.
concerning the return value this is possible. but the implementation
of addChild is a bit more "complex".
type self <: BaseNode;
abstract class BaseNode
{
protected var children_ : Map[String, self] = null;
...
var parent: self = null;
def key: String = ...
def addChild(_child: self):self =
{
children_(_child.key) = _child;
_child.parent = this;
return this;
}
}
well i can get away with the error on return in addChild
by changing the declaration to "def addChild(_child: self):this.type"
but i still have the same error on this line "_child.parent = this;"
and i cant change that to " var parent: this.type = null;".
(well sometimes that works - but is i have understood it would be
wrong).
so the question is can i somehow define "type self ?" to include
BaseNode as well?
ciao robertj
Date: November 12, 2005
From: Michal Politowski <mpol@xxxxxxxxxxxxxxxxxxx>