In a functional language you are mostly passing around fairly pure concepts of data as lists and maps, and transforming and combining data between functions. This data is standalone, and serialisable, and so easy to understand; a REPL-oriented environment means that code gets implemented incrementally, building from some inputs to the required result interactively, so everything gets some testing as it is developed.
The static types of this pure data probably wouldn't be very interesting.
Compare with SQL - SQL lets you join and transform arbitrary tables using queries. SQL doesn't require you to create up-front static types to accommodate the shapes of the resultsets of queries that are include joins. The Clojure Way has a lot in common with SQL, I find.
[1] of course there are plenty of large real world systems written in Python etc.
You realize that DML/DQL is only one part of SQL? It also includes a DDL. All the types are right in there.
> resultsets of queries that are include joins.
I have never had to use DDL to declare the types of the results of a join. What database do you use where you do?
Static types != manifest types.
I was suggesting that the immutable part of FP (which is most of it) has a lot of similarity with relational querying, which is very successful in the real world.
Clojure is entirely different. When you write (f x) you know exactly how f is going to dispatch by looking what f is in f's namespace: either it is a simple function, a protocol method implemented by x (just like interfaces in Java) with the protocol defined in f's namespace, or a multimethod in f's namespace.
So in Clojure, you don't have dynamic dispatch at all other than Java-like polymorphism or multimethods whose implementations are confined to a single namespace.
Static languages are also usually faster, so I guess the tradeoff stands between raw performance and code size.
There are numerous succesfull projects using dynamic languages. Github, as far as I know, uses Ruby.
I agree completely when it comes to refactoring/modifying code though. This can become cumbersome, especially if you don't have unit tests.
Wrong.
> ... and to ensure this type safety, they need more information from you, the developer.
Wrong.
Anyway, correlation != causation. If I would claim that there are some projects which are successful, despite being untyped, I could pretty much use the same data points to make my claim.
What? Static languages doesn't ensure type safety? Or errors due to wrong use of types doesn't get uncovered in unit tests? Unit tests runs the code, so when it runs code where wrong types or names are a problem, the code will fail, thus uncovered... Doesn't help for code you don't have tests for though, which instead require manual testing.
The type system does need more information from the user to allow the same kind of flexibility in a type safe environment. Polymorphism either through interfaces or class inheritance is basically a way to tell the compiler that "Hey, i know these objects look different, but they do support the function/method I'm calling, so relax ok?".
When someone says they don't understand the use of dynamically typed languages in a real world setting, it makes sense to mention that a company like GitHub mainly uses a dynamically typed language in their product. Heck, even Facebook uses a dynamically typed language quite extensively in PHP. Yes, you could make the argument that alot of successfull projects use statically typed languages, and naturally they do. The point is that dynamically typed languages work just fine in a real world setting.
I disagree with your notion of equating types with tests. They are fundamentally different. Types provide substantially stronger guarantees without having to execute any code.
> The type system does need more information from the user to allow the same kind of flexibility in a type safe environment.
Did you have a look at Haskell? Or any other language with type inference? The connection you are trying to establish between "untyped == no need to specify types explicitly" and "typed == necessary to specify types explicitly" is patently wrong.
Having a helpful compiler doesn't mean that the language has to suck. I don't want to offend you, but your comments create the impression that you are lacking experience with a modern, statically typed language.
I'm not equating types with tests. I'm saying that type errors comes to light when a unit test for a given code is run, because you will get unexpected results and/or an exception is thrown.
> Did you have a look at Haskell? Or any other language with type inference? The connection you are trying to establish between "untyped == no need to specify types explicitly" and "typed == necessary to specify types explicitly" is patently wrong.
I started learning Haskell but stopped when I came to monads. I've also experience with other languages that provide type inference like Go and F#. Go requires you to define interfaces (something you don't need in a dynamic language like, say, javascript). Haskell also has features that require the developer declare something upfront (types and type derivation), as do F# (discriminated unions and/or types).
My actual example was regarding class inheritance and implementing interfaces. Polymorphisism through inheritance or interfaces is great in a statically typed language, but not required or even possible in certain dynamic languages.
> Having a helpful compiler doesn't mean that the language has to suck. I don't want to offend you, but your comments create the impression that you are lacking experience with a modern, statically typed language.
I never said statically typed languages suck. I've developed an app in C# which was a great experience, and at my day job I work in C++ (which IMHO is a sucky language, but not due to being statically typed). Haskell is also a great language, as is Go and C#.
What I did say is that statically typed languages often require more code, which (depending on who you talk to) slows down development compared to a dynamically typed language. Statically typed languages does however usually entail better performance and (sometimes) smaller memory footprint than dynamically typed languages. There is a tradeoff, but that doesn't make one more suited for real world applications than the other, which there exists numerous examples of.
Generally not. Type inference does that for you.
I don't see why there are static vs dynamic flamewars. From my experience, dynamic languages are good at doing more with less code, and getting somewhere faster. Stuff written in static languages tends to be more efficient and reliable. I'm happily using both.
And the line between static and dynamic languages is a bit blurry anyway.
[Disclaimer: I have never used core.typed.]