I'm reading the prerelease of the Scala book, since I'm working for a heavily Java-invested organization now and programming in Java feels like running a race with cement shoes. Politically, Jython doesn't seem like an option; Scala might be an easier sell.
Here's some of my impressions going through the book.
Scala is a decent scripting language
[updated this section thanks to comments from anonymous, Jörn, and Eric.]Here's how you can loop through each line in a file: Python:
import sys for line in open(sys.argv[0]): print lineScala:
import scala.io.Source Source.fromFile(args(0)).getLines.foreach(println)
The scala interpreter also has a REPL, which is nice for experimenting.
This article has more examples of basic scripting in scala.
Getters and setters
One thing I despise in Java is the huge amount of wasted lines of code dedicated to getFoo and setFoo methods. Sure, your IDE can autogenerate these for you, but it still takes up lines in your editor and effort to mentally block them out when examining an unfamiliar class to determine what it does.C# has Python-style properties, so in theory could be virtually free of this kind of boilerplate, since there is no syntactic difference between "foo.x = y" whether x is a raw field or a property. So, the right thing to do, which you'll see in Python code, is using a raw public field until you actually need extra logic, at which point you replace it with a property and nobody's code breaks.
But C# wasn't far enough removed from Java culturally so everyone writes boilerplate properties instead of boilerplate getters and setters. (I'm aware that in a compiled language like C# it makes sense to start with properties for classes in certain kinds of libraries but these make up a vanishingly small number of actual classes in the wild.)
This is a long way of saying that Scala's properties make a lot of sense given the audience they are targetting (Java programmers). Scala vars are automatically turned into properties (or getters and setters, if you prefer to think in terms of those). So even the most obstinate fan of boilerplate code has absolutely no reason to keep writing unnecessary getters and setters.
If you need to manually tweak your properties later, you can magically define a setter for "field" by naming a method "field_=". This seems a bit like a one-off hack rather than part of a well-designed system, but I can live with it. (Since parentheses are optional for a scala method taking no arguments, any no-argument method call is already syntactically indistiguishable from a raw field read.)
Scala doesn't know what it wants to be when it grows up, yet
Scala contains a lot of features from a lot of different influences, which means there's often competing styles to use; the young scala community hasn't yet decided which to emphasize. For instance, iteration vs traversal -- "for (item <- items)" vs "items.foreach" -- or even whether to leave out optional (inferred) type declarations.Perhaps this is merely a failure of one book trying too hard to make scala be all things to all readers.
Random thoughts
- Scala needs something like Python's enumerate function; if you want to loop each object in a collection but you need its index too, you have to do a manual for loop.
- Using parenthesis for collection access ("array(0); map("foo"))") makes it unnecessarily difficult to tell if you're looking at a method call or a collection access.
- The scala stdlib is not very google-able yet; if you don't know exactly the class you are looking for ahead of time, you probably won't find it. For example, when looking for a scala object that could iterate through lines in a file, I correctly guessed the scala.io package, but would never have bothered looking at Source until more googling turned it up in a blog entry.
Conclusion and disclaimer
This is long enough; I'll probably write more as I go through more of the book. Patterns and implicit conversions are particularly interesting.I was attracted to scala while looking for a sane alternative to Java on the JVM and it looks like scala might "drag Java programmers halfway to Python," to paraphrase Guy Steele. And I'm happy to be corrected on anything I've written here.
Comments
in a JVM without Jython, use
Rhino's JavaScript.
No other JVM scripting solution has the of the set of features that Rhino offers and none has a longer track record.
Also, JavaScript syntax is close enough to Java. So prototyping in JavaScript to deliver in Java can be profitable.
I'm pretty excited about ECMAScript 4.
io.Source.fromFile("foo.out").getLines.foreach(println)
is enough code.
I explained in the article why I'm counting code required to make a reusable program, not just code to experiment in the REPL.
This means that if you want the flexibility of changing your behaviour in the future, you are forced to insert all the get and set noise into your code.
import scala.io.Source._
object fileio extends Application {
fromFile("foo.out").getLines.foreach(print)
}
Using foreach(print) instead of foreach(println) gives me a better result. Though again an example where Scala hasn't quite settled on one approach for a common problem.
I'm using the Scala Eclipse plugin which compiles the file on save, hiding the extra compile step from me. I agree that its hardly a "true" scripting language without that tool.
About the enumerate method: Yeah, I was missing that, too. Good thing with Scala is that you've got good chances to ask for that an actualy see it in one of the next releases, which isn't too far away. And until then you can just add it yourself with implicit.
With posts like yours odds are quite good that Google will have more to find in the future.
jorn: thanks for the comment; I hope the eclipse plugin stabilizes soon.
You can try that:
scala hello.scala "arg1" "arg2"
with hello.scala:
println("hello")
args foreach {s:String => println(s)}
This will print:
hello
arg1
arg2
Is that what you're looking for?
Eric.
I'm really a Scala fan (being tired of Java as pretty much everyone else). Yet I haven't used it much for pure scripting stuff (only when scripting involves using existing java libraries). In that case I feel much more comfortable with Ruby.
Anyway your post is interesting and I would like to know how far we can push Scala to become a "total" scripting language.
> So even the most obstinate fan of boilerplate code has absolutely no reason to keep writing unnecessary getters and setters
You can also refer to case classes where you also have equality, hashcode and pattern matching for free.
>Scala needs something like Python's enumerate function; if you want to loop each object in a collection but you need its index too, you have to do a manual for loop.
You have the method List.zipWithIndex which can help you
>Using parenthesis for collection access ("array(0); map("foo"))") makes it unnecessarily difficult to tell if you're looking at a method call or a collection access.
This is indeed a method, the "apply" one (page 55 in the book)
What I would really like to have for 2008 is lightweight script environment with autocompletion (with a less than 2s startup time,...). I don't know how feasible this is but this would make Scala a very, very interesting scripting language over the dynamic ones.
Eric.
PS: "advertising" -> if you're interested, you can have a look to my scala project (http://code.google.com/p/specs). I'm very interested in getting as much as possible (constructive ;-)) feedback about it.
@eric
I can't wait to try out specs, I'm a long time rubyist and a heavy user of rspec. Thanks for making specs :)
Below is the Enumerable class and an implicity function. These allow me to write:
scala> var a = Array("hello", "from", "enumerate")
a: Array[java.lang.String] = [Ljava.lang.String;@23245e75
scala> a.enumerate { (s:String, i:Int) => println(s, i)}
(hello,0)
(from,1)
(enumerate,2)
Here is the implementation:
class Enumerable(val array: Array[String]) {
def enumerate(op: (String, Int) => Unit) {
var i = 0
for(e <- array) {
op(e, i)
i += 1
}
}
}
implicit def enumerableWrapper(a: Array[String]) =
new Enumerable(a)
}
val ls = List("a", "b", "c", "d")
ls.zipWithIndex.foreach(println)
i'd take a look at some of the groovy samples and some of the grails videos to see it in action. i think it would be much easier to adopt than scala, many people are wondering why it doesn't become java7 seeing as it has the features that people have been asking for (closures, type inference..).
on javascript, i disagree that javascript is much like java at all, their constructs can be very different. also, rhino is interpreted on the JVM whereas groovy is compiled to byte code so it enjoys good performance in most situations (with some well documented exceptions).
i'm primarily a java guy that would like to code more python, but we still have to deploy to a JVM and I find groovy a better way forward than any other option right now.