Posts Tagged ‘scala’

Re: [scala] The right tool — by Martin Odersky

May 19, 2010

In reply to this post by Erik Engbrecht
On Mon, May 17, 2010 at 10:49 PM, Erik Engbrecht <[hidden email]> wrote:

I think Scala is very large compared to languages like Python or Java, but smaller than C++.
By “large” I mean there are a lot of concepts in the language.  Just to list a few that aren’t in Java…
… I am always a bit uneasy when reading a list like this and arguing with it. Yes, Scala has a lot of features but it tries very hard to make them facets of a uniform core which is not that large. I realize that for a newcomer, in particular someone brought up in the C/Java tradition, Scala might look large. For instance, objects/companion objects which you mention. If you do an in-depth study of language specs, these are actually significantly simpler then Java’s static class members. But static class members are known whereas companion objects are less well known, so they look more complex for most people.

Here’s a discussion of the other features you mention, in comparison to Java.

  • Higher kinded types

Yes, that’s definitely beyond Java. This is the one feature where for a long time I was not sure whether it is worth the weight. I have been leaning recently more towards believing that it will probably turn out to be quite useful.

  • by-name method parameters
vs special treatment of ||, &&, assert.
  • companion objects
vs statics (see above).
  • case classes
vs enums (arguably at least as complicated in both syntax and type checking).
  • structural types
  • closures / first-class functions
Yes, until Java gets them, in which case Java’s will be more complex, due to throws clauses.
  • for comprehensions
vs extended for-loops, looks like pretty much the same thing to me.
  • mixin composition / multiple inheritence
vs extends/implements. Again, you might argure that traits simply drop some restrictions in interfaces.
  • self types
yes, sort of. Again we simply drop a restriction in Java on the type of `this’.
  • type inference
Not sure that adds complexity per se. Java does it as well, but more clumsily. Have you looked at the
<> notation in Java 7? How is that simpler?
  • currying
You might say, we just drop a restriction that functions have only one parameter list…
OK I concede, it’s a yes.
  • pattern matching (and associated unapply etc support machinery)
vs switches, which are getting more complex, and I always forget to put a break at the end of a case.
  • loose syntax for some language constructs, e.g. dropping parenthesis
Yes, but Java programmers have to learn that it’s array.length, but string.length(). Not sure what is better.
  • specialization
That’s an annotation-driven optimization. I don’t think we should count that
  • operator overloading
Compared to the large number of synactically defined operators in Java I think that’s a net win.
  • multiple parameter lists for methods
That’s a duplicate of currying.
  • parameter lists that come before the method name (colon prefixed operators)
You mean colon-suffixed, right? yes.
  • implicits (parameters, conversions, values)
Yes, but they let us avoid a lot of special cases.
  • stable ids vs non-stable ids
Linked to abstract types, yes.
  • default arguments
  • lazy values
Vs special static member initialization, which also has lazy semantics.
  • added access qualifiers (e.g. private[this])
Vs dropping package level visibility.
  • XML as-a-language construct
Yes. That’s the second extension where in retrospect I am not sure it was a good thing overall. When we started out with Scala, XML was the showcase where functional programming could be clearly shown to be useful. At the time most people thought you could do everything with pure OOP. So we added XML.. Today, the case for FP is much stronger, and the case for XML has gotten weaker. So maybe the inclusion of XML in Scala was a historical accident. But anyway, it’s in, and will stay in.
  • …and I’m probably forgeting some…
So what does it drop from Java:
  • static members
  • field / method dichotomy
  • object / primitive dichotomy
I think you seriously underestimate the complexities in Java. Just some points, it’s far from an exhaustive list

– 4 namespaces (methods/fields/types/packages) instead of two.
– different name resolution rules for each namespace.
– enums
– annotations (yes Scala has them as well but they are much, much simpler than Java’s)
– some tricky syntactic corner cases to disambiguate between casts and expressions.
– nasty explicit parameterization. Does anyone even know how to pass a type parameter to a method in Java?
– over-reliance on wildcards, leading to very hard to diagnose type errors.
– restrictions on arrays with generics.
– raw types(!)
– restrictions that inner classes can only acces final members.
– super constructors.
– dataflow analyses for definite assigment and termination (these are actually useful, but burn about 20 pages in the spec).
– throws clauses and the rules governing them
– auto-boxing
– complicated rules what kind of casts are allowed where

A lot of these points look simple, but start to read up on their precise rules, they are anything but.

I don’t want to get into a feature to feature comparison between languages. My main point is, that, if you draw up a list of bullet points you can make any language look forbiddingly complex.

I certainly agree that if Java is your point of departure, then there is a lot of new stuff to learn in Scala. My argument is that there is also a lot of stuff in Java that people take more or less for granted but that is pretty complicated under the covers (and I argue from quite intimate experience here).

Some measures: The grammar of Scala is actually smaller than the grammar of Java. The typechecker of Scala is about the same length in lines of code as the type checker for Java, or the type checker for Haskell. Of course, every type checker is written in its own language, so you can draw an infinite number of conclusions form that, all of the form:

Scala’s type system is X-times more complicated than Java’s or Haskell’s, but code written in the language
is X-times more compact

where X ranges from 0 to infinity.


— Martin

Good! F# (May 2009) support tail recursion very well!

July 23, 2009

What’s the tail recursion?

In computer science, tail recursion (or tail-end recursion) is a special case of recursion in which the last operation of the function, the tail call, is a recursive call. Such recursions can be easily transformed to iterations. Replacing recursion with iteration, manually or automatically, can drastically decrease the amount of stack space used and improve efficiency. This technique is commonly used with functional programming languages, where the declarative approach and explicit handling of state promote the use of recursive functions that would otherwise rapidly fill the call stack. (from Wikipedia)

Still don’t understand? OK, let me show you the code.

int f(int n) {
    return f(n + 1);    // it's the last operation.

If you run f(0), you will get a StackOverFlowException.

How about F#?

let rec f n = f (n + 1)

The keyword “rec” tell compiler it’s a recursive function.

We use Reflector to see how it looks like as a C# code:

public static a f&lt;a&gt;(int n)
    while (true)

The magic the compiler done is called Tail Call Optimization. (see Adventures in F#–Tail Recursion in Three Languages)

Another case of tail recursion:

type t() =
member x.f1 n = x.f2 (n + 1)
member x.f2 n = x.f1 (n + 1)

This time, when you run t().f1 0, you will get the StackOverFlowException too.

Don’t worry. Just open the F# project properties dialog and the Build tab. Check the “Generate tail calls” on. Then the exception disappeared.

See what’s different of the IL code:

“Generate tail calls” unchecked

.method public instance !!a f1(int32 n) cil managed
.maxstack 5
L_0000: nop
L_0001: ldc.i4.s 0x2e
L_0003: call void [mscorlib]System.Console::Write(char)
L_0008: ldarg.0
L_0009: ldarg.1
L_000a: ldc.i4.1
L_000b: add
L_000c: call instance !!0 Program/t::f2(int32)
L_0011: ret

“Generate tail calls” checked

.method public instance !!a f1
(int32 n) cil managed
.maxstack 5
L_0000: nop
L_0001: ldc.i4.s 0x2e
L_0003: call void [mscorlib]System.Console::Write(char)
L_0008: ldarg.0
L_0009: ldarg.1
L_000a: ldc.i4.1
L_000b: add
L_000c: tail
L_000e: call instance !!0 Program/t::f2(int32)
L_0013: ret

One more case:

type t() =
member x.f3 n = x.f3 (n + 1)

No matter you check the “Generate tail calls” or not, the compiler will do the Tail Call Optimization.

The reflector will render it like this:

public a f3&amp;amp;lt;a&amp;amp;gt;(int n)
    while (true)
        this = this;

Scala compile will do the Tail Call Optimization too, but there’s no “tail” in JVM until now. So we need to wait for the Java 7.