class MyWindow extends JFrame {
public MyWindow() {
super("Hello World");
setDefaultLookAndFeelDecorated(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
JButton button = new JButton("Hello World");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Hello world");
}
});
getContentPane().add(button);
pack();
setSize(400, 300);
setVisible(true);
}
}
public class HelloWorldSwing {
public static void main(String[] args) {
MyWindow win = new MyWindow();
}
}
Scala:
code:
import javax.swing._;
class MyWindow2 extends JFrame("Hello World") {
import JFrame._;
setDefaultLookAndFeelDecorated(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
val button = new JButton("Hello world");
button addActionListener Print("Hello world");
getContentPane() add button;
pack;
setSize(400, 300);
setVisible(true);
import java.awt.event._;
case class Print(msg : String)
with ActionListener
with Application {
def actionPerformed(e : ActionEvent) =
Console println msg
}
}
object HelloWorldScala with Application {
val win = new MyWindow2
}
Sponsor Sponsor
wtd
Posted: Sun Dec 04, 2005 3:17 pm Post subject: (No subject)
Noteworthy differentiations from Java, in no particular order:
Import difference #1
code:
import javax.swing.*;
vs.
code:
import javax.swing._;
* is a valid identifier in Scala, and thus cannot be used the same way it is in Java. The used of _ does fit with how underscores are used in pattern matching, which is a nice bit of consistency.
Import difference #2: static imports and relativism
code:
import static javax.swing.JFrame.*;
vs.
code:
import JFrame._;
Static imports in Scala are less verbose and clearer than their Java counterparts.
Imports in general are also relative in Scala. In Java, the JFrame class had to be fully qualified. In Scala, we can simply specify the JFrame class, because it tries to look in javax.swing first.
Import difference #3: local imports
code:
import java.awt.event.*;
vs.
code:
import java.awt.event._;
In the Java program, we had to place this import at the top of the program, and import the names in java.awt.event into everything in this file.
In Scala, we used a local import.
Parameterized classes
code:
class MyWindow extends JFrame {
public MyWindow() {
super("Hello World");
vs.
code:
class MyWindow2 extends JFrame("Hello World")
Scala permits paramaterized classes, rather than having constructors in the Java sense. This makes a lot of sense, since it reduces repeated code. A contrived example:
code:
class Foo {
int bar;
double baz;
public Foo(int initBar, double initBaz) {
bar = initBar;
baz = initBaz;
}
}
vs.
code:
class Foo(initBar : int, initBaz : double) {
var bar = initBar;
var baz = initBaz;
}
Parameterized classes are a familiar site to anyone who has worked with Objective-Caml.
Local type inferencing
code:
JButton button = new JButton("Hello World");
vs.
code:
val button = new JButton("Hello world");
Local type inferencing is visible here. Why specify the type of "button"? "new JButton" does it quite well.
Additionally, "val" rather than "var" serves to make the variable "final".
Inner classes and magical infix operators from methods
case class Print(msg : String)
with ActionListener
with Application {
def actionPerformed(e : ActionEvent) =
Console println msg
}
Scala does not support anonymous inner classes. It does however support inner classes.
In this case we've made it a "case class", which removes the need to use "new".
The Print class mixes in ActionListener and Application. From ActionListener we get the obligation to implement actionPerformed, and from Application we get access to Console. Print of course is parameterized with the string that we actually want it to print, so that we can reuse this class.
Visible in this code snippet is the use of Scala's ability to turn methods into infix operators.
code:
Console println msg
Can also be called as:
code:
Console.println(msg)
Also visible is a reduction of braces and semi-colons.
Since actionPerformed contains only one expression, it can be expressed without braces. Additionally, since the braces for the Print class form natural punctuation, there's no need for a semi-colon following the actual println expression.
Main... or not
code:
public class HelloWorldSwing {
public static void main(String[] args) {
MyWindow win = new MyWindow();
}
}
vs.
code:
object HelloWorldScala with Application {
val win = new MyWindow2
}
Objects in Scala represent an alternative way of organizing variables and data. They are not instantiated like classes. They are essentially modules.
Here I've mixed Application into my object, meaning that I don't need a "main" method for such a simple program.
Again, local type inferencing is used to avoid repetitive typing of "MyWindow2".
wtd
Posted: Sun Dec 04, 2005 6:09 pm Post subject: (No subject)
Modified examples, where the button is a subclass of JButton.
In the Java example, the MyButton class has a constructor which takes two Strings. The first is the text to display in the button. This it passes to the constructor for the JButton class. The second String is the message to print to the console when the button is clicked.
In order to use this second value in the actionPerformed method, we have to assign it first to an instance variable which will still be in scope when the constructor is finished.
Scala dramatically simplifies this. The values passed to the class become accessible to any method.
wtd
Posted: Sun Dec 04, 2005 11:14 pm Post subject: (No subject)
Cervantes wrote:
So wtd, what's your review of Scala, so far? You seem to be spending a lot of time with it.
I rather like it.
It's not flawless, but it addresses a number of concerns I had in the Why Java Sucks thread.
wtd
Posted: Mon Dec 05, 2005 12:23 pm Post subject: (No subject)
A further use of mix-in composition to implement this absurdly simple program.
code:
import javax.swing._;
import java.awt.event._;
class PrintAction(msg : String)
with ActionListener {
def actionPerformed(e : ActionEvent) =
Console println msg
}
class MyButton2(title : String, msgToPrint : String)
extends JButton(title)
with PrintAction(msgToPrint) {
addActionListener(this)
}
class MyWindow2 extends JFrame("Hello World") {
import JFrame._;
setDefaultLookAndFeelDecorated(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
val button = new MyButton2("Hello world", "Hello world");
getContentPane() add button;
pack;
setSize(400, 300);
setVisible(true);
}
object HelloWorldScala with Application {
val win = new MyWindow2
}
The actionPerformed method is here defined within the PrintAction class, and then that class is mixed into the new button class.
I've also come to learn that Scala does in fact support anonymous inner classes, so the first Scaa example I gave can be more directly translated from the Java, and can better demonstrated the brevity the language makes possible.
code:
import javax.swing._;
import java.awt.event._;
class MyWindow2 extends JFrame("Hello World") {
import JFrame._;
setDefaultLookAndFeelDecorated(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
val button = new JButton("Hello world");
button addActionListener new ActionListener {
def actionPerformed(e : ActionEvent) =
Console println "Hello world"
};
getContentPane() add button;
pack;
setSize(400, 300);
setVisible(true);
}
object HelloWorldScala with Application {
val win = new MyWindow2
}
wtd
Posted: Tue Dec 06, 2005 1:51 pm Post subject: (No subject)
In the previous post I had this code:
code:
val button = new JButton("Hello world");
button addActionListener new ActionListener {
def actionPerformed(e : ActionEvent) =
Console println "Hello world"
};
getContentPane() add button
That's all well and good, and it's a pretty straightforward transition from Java, but with somewhat prettier syntax. Let's diverge a little bit further.
code:
getContentPane() add new JButton("Hello world") with ActionListener {
addActionListener(this);
Posted: Thu Dec 08, 2005 4:34 pm Post subject: (No subject)
For a possibly fairer comparison, and an example of using Java code within Scala seamlessly, I created the layout for my app in Java, but left actions for a superclass.
public class JMyWindow3UI extends JFrame {
protected final JTextField inputField;
protected final JSpinner numberOfCopies;
protected final JTextArea displayArea;
protected final JButton cut;
protected final JButton copy;
protected final JButton paste;
public JMyWindow3UI() {
super("JTest");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
inputField = new JTextField(50);
numberOfCopies = new JSpinner(new SpinnerNumberModel(1, 1, 256, 1));
displayArea = new JTextArea();
cut = new JButton("Cut");
copy = new JButton("Copy");
paste = new JButton("Paste");
Posted: Thu Dec 08, 2005 7:06 pm Post subject: (No subject)
Language seems to fit OK with the Java Philosophy. It's nice. But there are somethings I particularly don;t like, although it' just a matter of taste here.. really.. The language seems to be well-designed otherwise.
#1: I don't like replacing the * with _ in the import statements. * is universal as a "match everything" delimiter in many different languages and syntaxes.
#2: The infix notations is odd and can be very confusing. It fails to effectively establish a relationship between the object and the message (speaking in OO terms). Otherwise it's quite acceptable.
#3: I never did like mixins. I know it is a very powerful feature, but I can only imagine how complex OOD can be having it around. Although I believe Scala places particular restrictions on what classes can be mixed-in thus making it a whole lot "safer". Which is a good thing. Yet I still believe it can be improved further, can't it?
#4: I'm not a big fan of two character operators. Specially those "<-" ones. Although I can live with it.
wtd
Posted: Thu Dec 08, 2005 7:40 pm Post subject: (No subject)
rizzix wrote:
#1: I don't like replacing the * with _ in the import statements. * is universal as a "match everything" delimiter in many different languages and syntaxes.
code:
> val a = 2
val a: scala.Int(2) = 2
> Array(1,2,3).elements map a.* foreach Console.println
2
4
6
(): scala.Unit
You can perhaps see how, when * is a valid identifier, and we have (the equivalent of) static imports, that using * as a catch-all for imports is a problem.
Plus, think of Haskell, where _ is the catch-all, throw-away pattern. Scala does pattern matching.
rizzix wrote:
#2: The infix notations is odd and can be very confusing. It fails to effectively establish a relationship between the object and the message (speaking in OO terms). Otherwise it's quite acceptable.
Either syntax is available.
Plus, it offers a nice way to eliminate some syntactic noise, such as in the addition of the action listeners.
Or consider:
code:
myString.equals(otherString)
vs.
code:
myString equals otherString
rizzix
Posted: Thu Dec 08, 2005 9:53 pm Post subject: (No subject)
why not:
code:
myString.equals otherString
wtd
Posted: Thu Dec 08, 2005 11:04 pm Post subject: (No subject)
rizzix wrote:
why not:
code:
myString.equals otherString
I knew you were a closet Ruby fan!
You could do that, but the dilemna with allowing parentheses to be removed are precedence issues. Ruby certainly has this problem, and while it's surmountable, I can't help but think you'd find it rather distasteful.
I've found Scala's precendence rules quite nice.
rizzix
Posted: Thu Dec 08, 2005 11:21 pm Post subject: (No subject)
I'm not well versed in Ruby.. could you elaborate? Btw I was going to suggest
code:
mystring.equals: another_string;
(as in ObjC-ish) Would that resolve the issues in any way?