2

I am currently working on the design of a controlled experiment where I hope to measure a benefit of dynamically typed programming languages compared to statically typed ones.

I am not looking for another "which one is better"- debate here, as there are enough discussions on this topic (e.g. Dynamic type languages versus static type languages or What do people find so appealing about dynamic languages?). I also asked the same question on LtU, which ended up in another discussion. :-)

All these discussions mention some good points, but nearly all are missing some concrete code(!)-examples which proves their point.

So my question is: Can anyone of you give me some example code which directly reveals some benefits of a dynamically typed language or shows a situation where a static type system is more an obstacle than a helpful tool?

Thanks in advance.

Community
  • 1
  • 1
Seb
  • 1,721
  • 1
  • 17
  • 30

2 Answers2

1

by the definition: duck typing. but you want more specific example so, let's say: building objects. in statically typed languages you need to declare type or use built in methods for runtime code generation. in dynamic languages you can just build objects ad hoc. for example to create a mock in groovy you can just write the one method you need to mock and pass it as an object: http://groovy.codehaus.org/Developer+Testing+using+Closures+instead+of+Mocks

in static languages people write big and complex libraries to make it easier. and still it's verbose and often has limitations

piotrek
  • 13,982
  • 13
  • 79
  • 165
0

There was a time, not long ago, where these were the kind of choices we had to make: Do I want it to be fast and easy to write the program, but sometimes there are more runtime bugs? Or do I want to be protected from more of those bugs at compiletime, but at the cost of having to waste more time writing more boilerplate?

That's over now. Dynamic languages were extremely exciting back when they were the only way to avoid adding a lot more bureaucracy to your code, but dynamic typing is now being obsoleted by type inference. So you're actually right -- dynamic typing doesn't add value anymore, now that more powerful strong type systems are catching on.

Huh? Where? How?

Languages like Haskell, the MLs, Scala, Rust, and some of the .NET family combine strong typing with type inference so you get the best of both: everything has a strong, enforced type, but you don't have to actually write it down unless the compiler can't figure it out, which it usually can.

Don't ignore them for being academic. Things have changed. Those kinds of languages with powerful typing systems have been steadily getting much more popular over the last few years. (2) And, I'm finding it more and more rare to hear about a brand new language these days that doesn't sport a combination of strong typing for safety with type inference for convenience, at least to some degree. Today's brand new esoteric languages are next decade's "enterprise standards" so I think everyone will be using this best-of-both-worlds approach eventually.

Even old man Java is moving slowly in that direction! (examples: diamond operator; inferring the functional interface for lambda expressions)

Learning dynamic languages for the first time now is too late, it's like if throughout the 1990s you were putting off replacing your tape deck with a CD player and then finally around 2002 you get around to buying a CD player.

EDIT: I reread your question. I sympathize with your desire for concrete code. Here's a Rosetta stone. A generic procedure to check whether a list is sorted or not, and code that calls it. The code that calls it does the right thing every day and the wrong thing on leap days, as an example of how compiletime errors win big over runtime errors when you have a bug in rarely-executed code. Code is untested, just a sketch. In particular, I'm still learning Haskell (hence the zeal of the newly converted... :P) and I haven't used Python as heavily as I used to for a couple years, so forgive

Traditional static typing:

// Java 7 - strong typing but no type inference
// Notice that you get safety, because the wrong usage is caught at compile time
// But you have to type a lot :-(
  static interface Comparable { boolean compare(Comparable other); }
  ...
  boolean isListSorted( List<T extends Comparable> xs ) {
    T prev = null; for( T x: xs ) {
        if( prev!=null && !prev.compare(xs) ) return false;
        prev = x; 
    } 
    return true;
  }
  ...
  public final class String implement Comparable { ... }
  public final class Animal /* definitely does not implement Comparable! :-) */ { ... }

  ...
  // proper usage
  List<String> names = Lists.newArrayListOf("Red", "Spinelli", "Ankh", "Morporkh", "Sam");
  boolean areTheNamesSorted = isListSorted(names);
  if(todayIsALeapDay()) {
     // bad usage -- the compiler catches it, so you don't have to worry about this happening 
     // in production when a user enters data that send your app down a rarely-touched codepath
     List<Animal> pets = Lists.newArrayListOf( Animal.getCat(), Animal.getDog(), Animal.getBird() );
     boolean areTheNamesSorted = isListSorted(pets);
  }

Dynamic typing:

class Animal:
   ...

# Python 2.6 -- dynamic typing
# notice how little keystrokes are needed
# but the bug is now
def isListSorted(xs):
  # to keep it more similar to the Java7 version, zip is avoied
  prev = None
  for x in xs:
    if prev is not None and not prev.compare(x): return False
    prev = x
  return True
...
# usage -- beautiful, isn't it?
names = ["Raph", "Argh", "Marge"]
areNamesSorted = isListSorted(names)

if isLeapDayToday():
   # ...but here comes trouble in paradise!
   animals = [Animal.getCat(), Animal.getDog()]
   # raises a runtime exception. I hope your unit tests catch it, but unlike type 
   # systems it's hard to make absolutely sure you'll be alerted if you forget a test
   # besides, then you've just traded the Evil of Having to Write Lots of Type Signatures
   # for the Evil of Having to Write Lots of Unit Tests. What kind of terrible deal is that?
   areAnimalsSorted = isListSorted(animals)

Powerful typing:

-- Haskell - full safety of strong typing, but easy on the fingers and eyes
class Comparable a where
  compare :: a -> a -> Bool
end
instance Comparable String where
   ...
end
data Animal = ...

isListSorted [] = True
isListSorted x:[] = True
isListSorted x1:x2:xs = (compare x1 x2) && (isListSorted xs)

names = ["Raplph", "Argh", "Blarge"]
areNamesSorted = isListSorted names



animals = [Cat, Dog, Parrot]

-- compile time error because [Animal] is not compatible with Comparable a => [a] since
-- Animal is not an instance of comparable

areAnimalsSorted = isListSorted animals

Verbose powerful typing:

-- Same Haskell program as before, but we explicitly write down the types 
-- Just for educational purposes. Like comments, you can omit them if you don't think
-- the reader needs them because it's obvious. Unlike comments, the compiler verifies their truth!


class Comparable a where
  compare :: a -> a -> Bool
end
instance Comparable String where
   ...
end
data Animal = Cat | Dog | Parrot


isListSorted :: Ord a => [a] -> Bool
isListSorted [] = True
isListSorted x:[] = True
isListSorted x1:x2:xs = (compare x1 x2) && (isListSorted xs)

names :: [String]
names = ["Raplph", "Argh", "Blarge"]

areNamesSorted = isListSorted names


-- compile time error because [Animal] is not compatible with Comparable a => [a] since
-- Animal is not an instance of comparable

animals :: [Animal]
animals = [Cat, Dog, Parrot]

areAnimalsSorted = isListSorted animals
Domingo Ignacio
  • 1,194
  • 7
  • 13