Linked by Thom Holwerda on Fri 2nd Dec 2005 11:04 UTC, submitted by anonymous
General Development Scala is a modern multi-paradigm programming language running on top of a Java VM or .NET runtime. Recently version 1.4.0.3 has been released. Scala smoothly integrates features of object-oriented and functional languages. In Scala, every value is an object and the language supports OOP for instance via subclassing , traits, and mixins. Scala is also a functional language in the sense that every function is a value. The language supports anonymous, higher-order and nested functions as well as currying. There is also integrated support for pattern matching, parametric polymorphism, etc.
Thread beginning with comment 68284
To view parent comment, click here.
To read all comments associated with this story, please click here.
BryanFeeney
Member since:
2005-07-06

I don't like dynamic typing: I think it introduces ambiguity and makes it easier to make subtle errors.

For example, in JavaScript, I wrote

var a = 0.95;
a = a + getCookieValue ("fontResize");

and was amazed to find that instead of getting 1.10 I got 0.9515. This is because JavaScript has polymorphic operators without any clear way of identifying the type. The correct way was

a = 0.95;
a = a + ParseFloat (getCookieValue ("fontResize"));

PHP is a bit better, as it doesn't use polymorphic operators (+ is addition and . is concatenation). However the whole type coercion thing is really messy. It means PHP has two equality operators:

== means has equal values
=== means has equal values of the same type

This all comes down to something that Anders Hejlsberg (one of the C# designers) called "simplexity". You add this cool feature, such as not having to declare a type, to make a language easier. However once you get down to doing some serious work, you start running into these weird errors, and then you realise that in fact there are different underlying types, and you have to do weird things (ParseFloat, ===, etc.) to get around this. Consequently, the method of making the language easy, while successful in the trivial "Hello, world" case, actually makes the language more complex in the real-world case.

In JavaScript, seeing as we already use "var", surely it wouldn't have been much harder to write

float a = 0.95
a = a + getCookieValue ("fontResize")

which would immediately trigger a syntax error with a nice message explaining what went wrong.


While this is the primary problem I have with dynamic languages, another problem I have is that when you don't have to declare variables, there is not way the compiler can detect a typo. For example this code will compile without an error

var myCrucialResizeAmount = 0.95
var a = ParseFloat (getCookieValue ("delta"));

c = a * myCrucialResizeAMount + b / q;

document.getElementById ('Text').style.fontSize = c;

The problem here is that because of my typo, the value will be b / q. However there is no obvious error that will alert me to that, and in a large piece of code, it can be hard to find the offending mistake.

The final problem with dynamic typing is that it makes it profoundly difficult for an IDE to identify a type, and thus provide an auto-complete feature. Given that any OOP language with its salt these days will come with a huge library, the inability of an IDE to help you out is a major dent to productivity.

This is why I like static typing: for very little extra work on the part of the programmer, you get a whole load of assistance and quality assurance from the compiler and the IDE. I'd rather a tiny bit of "hmmm boring stuff" then half a day trying to manually search for a typo. It is also why I like what I've seen of Scala so much.

Reply Parent Bookmark Score: 1

Member since:

Very well said, BryanFeeney.

Sure, static typing can be a bit annoying. But the gains in maintainability and readability and IDE/compiler assistance more than make up for the incovenience of static typing. Even in a dynamically typed language, you still have to know the types of the objects being used in the program if you want to get it to work how you expect.

Reply Parent Bookmark Score: 1

Member since:

Maintain 50k lines of Java source.
Maintain 50k lines of Python source.

Come back when you've realized that static typing offers you very little when you have unittests, which you should be writing anyways to verify that your code is correct.

Reply Parent Bookmark Score: 0

cdutton Member since:
2005-07-24

BryanFeeney, you're failing to take into account type inferencing. One need not write out type names to get static type checking if the language and compiler are smart enough.

You mention Anders Hejlsberg and C#. C# 3.0 will support type inferencing. It becomes especially important when you would otherwise have code like:

SomeReallyObnoxiousClassName foo = new SomeReallyObnoxiousClassName();

That could become:

val foo = new SomeReallyObnoxiousClassName();

And a sample of what type inferencing can do:

Prelude> let a = 0.95
Prelude> let b = a + "hello"

<interactive>:1:12:
Couldn't match `Double' against `[Char]'
Expected type: Double
Inferred type: [Char]
In the second argument of `(+)', namely `"hello"'
In the definition of `b': b = a + "hello"

Reply Parent Bookmark Score: 2

BryanFeeney Member since:
2005-07-06

With regard to your SomeReallyObnoxiousClassName example it has to be said, there isn't all that much extra typing involved between the two examples when you take into account copy and paste, or even auto-complete.

Also your prelude example is a bit scary: I'm a fan of forcing as many errors as possible to happen at compile time, as opposed to testing for them at run-time (though unit-testing does help in this latter regard).

I'm still not convinced by type-inferencing, I'd worry about what happens when someone changes the signature of a method: e.g., lets say you have

class ArcaneClassIDidNotWrite
{

float getDialogDelta();
{
// work and then
return result;
}

}


class VeryMuchRemovedFromAbove
{
void doSomethingInfrequent()
{
val a = new ArcaneClassIDidNotWrite();
val b = a.GetDialogDelta();

val scale = 2 / b
this.property *= scale;
}
}

All is well and good. However lets say in the future that the signature of getDialogDelta() is changed from a float to an int. Because of type-coercion, this will cause neither a compile time nor a run-time error. However it will cause significantly unexpected results, as the scale will now be zero for every value of getDialogDelta() greater than two, which will occur occasionally.

Thus, without any warning, you get an occasional, infrequent, run-time error; the kind that's really hard to track down.

Now of course, an expert would say I should have written 2.0 / a up there to prevent that happening, but that brings us back to my argument about simplexity. My opinion is that languages should avoid as much ambiguity and "magic" as possible, so as to make it as hard as possible for the average programmer to make mistakes. After all, any idiot can write a program that works some of the time, the hard work is in writing a program that works all of the time.

However, with all that said, I can live a lot easier with type-inference than I can with dynamic typing.

And you can just call me Bryan ;-)

Reply Parent Bookmark Score: 1