This is made doubly painful by the incredibly obtuse error messages spat out by some compilers, like:
This expression has type ((int * int) * string * string * channel) list
but is here used with type ((int * int) * string * string * channel) list
or even more baroque and confusing monstrosities.Programming in OCaml made me feel like I'd need to take years of type theory classes in order to feel really comfortable in the language.
In comparison, programming in Lisp is a joy, and very easy.
But, in defense of the modern statically typed languages like OCaml and Haskell, I'll have to admit that once you've finished wrestling with the type system and actually gotten your program to compile, you've probably eliminated whole classes of bugs that might still exist in a similar dynamically typed language program. Not to mention that it will save you the writing a ton of unit tests.
error: conversion from std::_Rb_tree_const_iterator<std::pair<
const std::basic_string<char, std::char_traits<char>, std::allocator<char> >,
std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >
to non-scalar type std::_Rb_tree_iterator<std::pair<
const std::basic_string<char, std::char_traits<char>, std::allocator<char> >,
std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >
requestedAnyway just an aside
That would be Common Lisp.
There was such a version of Smalltalk called Strongtalk, but it never got a community behind it.
(Try comparing various languages here: http://shootout.alioth.debian.org/u32/benchmark.php?test=all... if you don't believe me)
Some dynamically typed languages can approach the speed of static languages, like Lisp, but they generally do that by introducing voluntary static typing hints, or having a JIT compiler introduce speculative code paths that guess the types coming in after some analysis.