10 ms·
The comeback of static typing
- deleted 14y ago[deleted]
- dons 14y ago> A few years back, one big lure of Python or Ruby used to be the functional constructs that they offered like higher order functions. This statement surprises me.
- steveklabnik 14y agoWhy's that, dons? They are playing a bit fast and loose with what 'higher order functions' means, but, for example, one of Ruby's best features is blocks. The details of higher order stuff in Ruby is certainly... messy, but blocks are a great introduction to the concept for people who haven't used them before. I've taught the concept to high school kids on their first day of programming, (mostly through a physical metaphor involving a list of chores on a piece of paper) and they picked it up easily enough.
- dons 14y agoFair enough. I'd say they provide more of a flavor of "higher orderness" rather than a true implementation, as the semantics are so limited and ad hoc in Ruby.
- steveklabnik 14y agoSeems fair. I highly respect your opinion on the topic, and that makes a lot of sense. There's a reason that I moonlight Haskell and Rust. :)
- sixbrx 14y agoI can't speak of Ruby (or for Dons :), but I'm not sure Python's use of hof's is a good example to learn from when it's lambda scoping rules produce such "interesting" results. >>> monomials = [lambda x: x(star)(star)i for i in [1,2,3]] #(not sure how to escape stars for exponentiation properly, whatever) OK, what will these functions evaluate to at the point 2.0? >>> monomials[0](2.0), monomials[1](2.0), monomials[2](2.0) (8.0, 8.0, 8.0) The i variable was captured as an address which all the lambdas share. For an integer. Ouch. You can do "lambda x,i=i: x(star)(star)i" and capture the value properly, but to me this is a landmine waiting to be stumbled upon every time I write a lambda. I for one will often forget to do this, at least so long as I also keep using other languages which can capture integers as values without hijinks.
- steveklabnik 14y agoYeah. Makes sense. Ruby also has a few of these kinds of weirdness, especially around the multiple kinds of hof, (lambdas, Procs, and blocks) and their limited utility compared to a truly functional language.
- east2west 14y agoI wonder if anyone knows why subtlety exists in Python. Is it because reference semantics and HOF are fundamentally incompatible, or could it have been avoided somehow but still retaining reference semantics. The most common complain about lambda in Python is that it is restricted to expressions, which is a conscious design decision that could have gone the opposite direction.
- halter73 14y agoThe subtlety sixbrx mentions used to be present in C#, but it has been mostly fixed by moving the declaration of the foreach loop variable inside of the loop [1]. Like Python, C# has reference semantics. I'm surprised that Guido van Rossum didn't make a similar change when he broke backwards compatibility in Python 3. [1]http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closi...
- Peaker 14y agoLexical scopes capturing variables is more powerful than capturing values. If you want to capture values, that's easy too, with: lambda x, i=i: ...
- plorkyeran 14y agoEvery language with mutable variables and closures that I've used works the same way (other than ones like C++ where you have to explicitly capture by either reference or value). The behavior can be a bit confusing, but it makes perfect sense once you realize that closures are capturing variables, not values.
- adrianmsmith 14y ago"Over time, not only have I learned to appreciate languages with good type systems, I actually now prefer them for solving certain classes of problems." I think that dynamic typing seems easier at first, but after a while you see how static typing would catch mistakes you make. While one programmer gains the experience necessary to appreciate static typing, a new programmer starts programming and doesn't have that experience yet, thus the static vs dynamic debate is always with us. I described it here: http://www.databasesandlife.com/the-cycle-of-programming-languages/ http://www.databasesandlife.com/the-cycle-of-programming-lan...
- andyidsinga 14y agothats very true it will always be with us. i started in C ..spent a lot of time there and felt crazily liberated in perl, php and javascript. - but i still love and use C, ( and recently objective-c ). this all boils down to skill with tools - cordless drills are amazing ..and so are floor drill presses
- viraptor 14y agoI agree with his view, but I could never find a static typed language that was useful in a long run. Haskell was amazing as long as try don't need to do much io. When I started spending more time fighting the constraints than being productive I stopped. Ocaml was also not bad. But their strict restrictions on what opetators can be used with what types is annoying when you do lots of calculations. Having to explicitly cast numbers all the time was not inviting either. Rust sounds great, but after a day of playing with it I saw it's really not ready yet. A couple of places needed wrapping in "unsafe" block to start working as expected. Some keywords and ideas were also going to change soon. I couldn't get used to the restrictions coming from not having exceptions or early function returns. It really adds some maintenance code. Scala was probably the best so far, but the heavy vm is annoying. So... still waiting for that perfect language.
- wiradikusuma 14y agoThen you should probably invest in Scala. The (J)VM is actually a blessing, Scala is standing on the shoulder of giants. I'm not talking about Oracle, but other languages that depend on JVM such as Clojure, etc, that will (hopefully) push the VM forward.
- viraptor 14y agoI don't like Scala being based on JVM/.NET for the following reasons (I know many people don't agree, this is all subjective): - inherited null (I love Option<> and Either<> pattern and exceptions, nullable stuff is a problem) - relying on foreign ecosystem (you end up with half functional, half "we have inherited all this mutable stuff, so let's use it" ugly mixture) - startup time (if you write things that are script-ish in nature, this is really annoying)
- wiradikusuma 14y agoThe first two are required for Java compatibility, the latest probably can be mitigated by compiling it to native using LLVM (http://greedy.github.com/scala-llvm/ http://greedy.github.com/scala-llvm/) (I haven't used it).
- mseepgood 14y agoThe title should have been "My personal comeback to static typing", because static typing was never gone.
- rschmitty 14y agowell if you read HN religiously you might have thought otherwise
- jmount 14y agoI have distilled my thoughts on this down to: if you think dynamic typing is the only effective way to do things you probably have never done any significant debugging or maintenance. Dynamic typing is a solution, but like all solutions it has limits. Here is my longer article on the topic before I distilled down to the above: http://www.win-vector.com/blog/2012/02/why-i-dont-like-dynamic-typing/ http://www.win-vector.com/blog/2012/02/why-i-dont-like-dynam... .
- randomfool 14y agoDisagree that static typing is important- it's all about static analysis. Static analysis has come a long ways for dynamic languages, see TypeScript or the Closure JS compiler for example.
- Sniffnoy 14y agoHm, this is an interesting point. One could say that once one has such general things as structural types, static typing essentially is just mandated static analysis.
- gnuvince 14y agoStatic analysis is a great tool, but the guarantees of a typing system can be much stronger (and as a result, can inform the static analyzer much better).
- randomfool 14y agoA typing system != static typing! Static typing means that the types cannot change. Dynamic languages can still declare types. It's just that they are allowed to morph. A good analyzer can track those changes and know when types are equivalent (TypeScript does this). Furthermore, typing is one mechanism to express contracts within your code- such as 'this method takes argument X which is of the form Y and will return something which looks like Z'. More complex analysis requires more and more annotations to specify the contracts of the methods. An example is a C function which takes a char* and an int. You want to annotate that the int indicates the length of the char* buffer, and have a static analyzer enforce that. I am all about code contracts and enforcement of those contracts. But this is not necessarily tied to a static language.
- Peaker 14y agoThere's just a different set of terms used here. In static typing context, "types" is a lexical construct of subexpressions. In this context, dynamically typed languages are "untyped" or "unityped" (one type for all expressions). In dynamic typing context, "types" are the runtime tags of data with rules about dispatch and what kinds of tags are allowed with what operations. I think for the benefit of communication, we should refer to the static, compile-time annotation on sub-expressions as "types", and the entity dynamic languages calls "types" as "tags". Your example: > More complex analysis requires more and more annotations to specify the contracts of the methods. An example is a C function which takes a char* and an int. You want to annotate that the int indicates the length of the char* buffer, and have a static analyzer enforce that This is of course certainly compatible with types. Something like: func : (n : Int) -> Ptr (Array n Char) -> ... This is the type of the contract you specified. Static types and static analysis are basically variants on the same idea. However, static types is part of the ordinary workflow, and static analysis is often treated as an "after-the-fact" feature. This will not work as well, since much of the power of types relates to techniques to structure our programs so that types cover as much as possible.
- cletus 14y agoI think static typing (10+ years ago) got a bad rap not because of static typing as such, but everything that came with it (and didn't necessarily need to). I'm talking about the languages of the time (C, C++, Java primarily). C is a bit of the one out here in that its static typing is a really thin veneer as you can cast things to whatever you want them to. Python and Ruby (in particular these two) more than anything else allowed you to write really terse, expressive code. The canonical Python example of this is defining a tree data structure: def tree(): return defaultdict(tree) or solving the N-queens problem in ~6 lines of code [1]. Java and C++ OTOH were (and are) much more verbose but only some of this has anything to do with static typing. All of this is one reason I'm incredibly bullish on the future of Go for such reasons as: - no interfaces. If an object implements the methods expected by a consumer then it compiles otherwise it doesn't; - incredibly simple OO system; - no exceptions as such (particularly checked exceptions in the case of Java, which IMHO are just horrible). Some consider this a minus. I tend to think that exceptions tend to get abused for flow control and aren't the panacea they're made out to be; - simple semantics for function returns and the ability to return multiple items; - opinionated formatting (I'm not one of those people who has almost religious zeal for the placement of curly braces and indenting so I'd rather just have a standard and stick to it, whatever it is); - compiles to a binary rather than running on a VM; - simple grammar with fast compilation. This last point is contrasted particularly well with C++; - coroutines (or rather goroutines) as a first-class language citizen for solving concurrency problems; - the "defer" mechanism for resource cleanup. I find this much easier to read than tortured try-finally semantics and nesting. Another way to put it is this: a lot of vim/emacs users judge IDEs as horrible based on having (often briefly) used Eclipse, which is a bit like judging the car by having once driven a 1975 Trabant. Don't judge static typing by Java or even C++. Judge it by Go. [1]: http://rosettacode.org/wiki/N-queens_problem#Python http://rosettacode.org/wiki/N-queens_problem#Python [2]: http://www.time.com/time/specials/2007/article/0,28804,1658545_1658533_1658030,00.html http://www.time.com/time/specials/2007/article/0,28804,16585...
- laureny 14y ago> - compiles to a binary rather than running on a VM; To me, this is one the many reasons why Go will fail.
- rcirka 14y agoOne of the points the author makes, is that static typing improves code maintainability and refactoring. I've used both static and dynamic languages. When I was younger I preferred dynamic typed because they were easier to start with and code, but now that I've grown more experienced and dealt with highly complex projects, I prefer static typed. Being able to debug, maintain, and refactor code is much easier and less risky in static typed languages.
- tikhonj 14y agoThe lack of popularity for static typing can be laid mostly at the feet of Java and C++. A language with a truly good type system like Haskell, OCaml or Scala gives you more advantages without many of the disadvantages of a Java-style system. Too bad too many people were too poisoned by Java et al to consider switching to one of the good statically typed languages; happily, their recent popularity (like this blog post :)) has gotten people to consider them.
- laureny 14y ago> The lack of popularity for static typing can be laid mostly at the feet of Java and C++. If anything, I'd argue that Java is the main reason for the rebirth of the popularity of static typing. Java is a C++ without the compiler getting in the way, so it exposed the power of what you can do with a type system (pretty weak one, but one anyway) when syntax is not tripping you every step of the way. By making static typing popular, Java kickstarted a whole new generation of improved languages such as C#, Scala and Kotlin which leveraged all the good concepts introduced by Java (such as no more separation between headers and implementation) while adding important missing features, such as type inference and traits.
- stephen 14y agoAgreed, it's easy to look back now and consider Java negatively, but 15+ years ago (which is a long time in our field) it caught on for a reason. It's not like Sun took a gun to everyone's head and said "use Java, damn it". I mean, Microsoft might try that :-), but Java succeeded almost despite Sun (e.g. on its own merits as a language), instead of because of them. And really it was Sun's bungling of the language evolution that led to Java's lack luster reputation today. In constract, Microsoft did a very admirable job with evolving C# to keep up with more modern syntax/semantic expectations.
- aaronblohowiak 14y ago15 years ago, Java was to C++ as Ruby is to Java: much slower, used by startups, touted for claims of programmer efficiency (garbage collection!)
- tewolde 14y agoFor the dev building the library static typing is a very convenient thing to have. All the ins and outs have very clear rules enforced at compile level. However, for the user of the library, it simply gets in the way. This may be avoided though if the library has been designed well enough that strange internal types are not exposed to the user unless absolutely necessary.
- tikhonj 14y agoActually, I find the opposite to be the case--static typing helps me use unknown libraries. The types immediately let me know exactly what a function expects and what I should expect from a function. They also prevent me from using things incorrectly most of the time. Essentially, the types are compiler-enforced documentation. They also make discovering functions easier--a type is a succinct summary of what a function does, so I can just browse by types to find what I want quickly. Augment this with great tooling like Hoogle (a type search engine) and you've got a truly awesome development system.
- berlinbrown 14y agoI am sure you don't care but Scala runs on the Java virtual machine.
- Chris_Newton 14y agoAs no-one else has mentioned it yet, here’s a link to a copy of Chris Smith’s excellent “What to know before debating type systems” article: http://blogs.perl.org/users/ovid/2010/08/what-to-know-before-debating-type-systems.html http://blogs.perl.org/users/ovid/2010/08/what-to-know-before... If you’re at all interested in the real strengths and weaknesses of different kinds of type system but don’t yet have much experience in the field, this is a solid and impressively neutral starting point.
- stephen 14y agoI think language evolution will always be cyclical like this--dynamic languages sprint ahead, and the static languages eventually catch up. The reason is that dynamic languages are so easy to build--they usually start out as hobbyist projects. Not to overly-trivial it, but these days most anyone can sit down with a compiler book and have an interpreted language up and going quickly. So dynamic languages evolve quickly--it's easy to try new things, see if they work, see if they don't. Static languages, on the other hand, are hard to build--you don't often see hobbyist language developers coming up with type systems in their spare time. Type systems are hard. And the tooling for static languages is hard too--dynamic language users live in emacs/vim/Sublime, but static language users are going to want an Eclipse IDE, refactoring, etc., etc. So, static languages evolve slower. But once someone has put the time and effort into a static language, and has the tool chain polished, I assert that most programmers (of course not all) that sprinted ahead to the dynamic languages will find themselves tempted to wander back. If the syntax is the same (once the static languages catch up), why wouldn't you want static typing, given that, even in dynamic language programs, 95%+ of the calls could be statically verified anyway? (Admittedly, how you deal with the remaining 5% (reflection, macros, XML, whatever) is left an exercise to the reader.) Great case in point: Groovy. The original creator, James Strachan, was a hobbyist, and I believe (admittedly putting words in his mouth), if not consciously, built Groovy as a dynamic language because it was easy. But now he prefers Scala, which is basically the same syntax, but with all of the extra infrastructure around typing/tooling/etc.
- qu4z-2 14y agoI disagree that static language users will want an IDE. I'm a static-typing advocate, but I much prefer vim over IDEs. Then again, I design static-type systems in my spare time, so maybe I'm not the target of your comment :)
- vorg 14y ago> But now [James Strachan] prefers Scala, which is basically the same syntax, but with all of the extra infrastructure around typing/tooling/etc. James has actually moved on from Scala to helping build statically-compiled language Kotlin!
- sokrates 14y agoI very much like Go's approach to static typing. Go allowed me to retain the flexibility and ease of development that Ruby and friends provide, even though the output is fully statically typed. It's great!
- Peaker 14y agoHM type systems have been providing this benefit (to a greater effect than Go) for ~40 years...
- pjmlp 14y agoThat is Go's PR on the move, presenting Go features as novelty. My personal one is how fast it compiles, given I was doing the same thing with Modula-2 and Turbo Pascal in the mid-80's.
- happy_dino 14y agoI wouldn't call something "fully statically typed" when most abstractions can only be implemented by casting from and to the top type. There is a reason why no one wants to use Java 1.4 anymore. Go's "static typing" is next to useless.
- Spykk 14y agoI think dynamically typed languages have become so popular because in simple examples they look great to novices. You don't need to know much syntax about defining variable types, you don't have to type as much, you don't have to figure out why adding an integer to the end of your string won't work, etc. Later, when they try to build something large enough to be useful they realize just how much they traded for that little bit of convenience. For example in PHP: $id = 1; $dbh = new PDO($connectionString, $user, $password); $sql = ' SELECT column'; $sql .= ' FROM table'; $sql .= ' WHERE id = :id'; $stmt = $dbh->prepare($sql); $stmt->bindParam(':id', $id); if($stmt->execute()) { // Do stuff } //This echos ID: 1 echo "ID: $id"; if($id === 1) { echo 'This should be true, we set $id = 1 at the top.'; } else { echo 'Instead we get here because PDO casually changed our variable into a string and "1" != 1.'; die('in a fire dynamic typing.'); }
- ScottBurson 14y ago> you don't have to figure out why adding an integer to the end of your string won't work You're confusing dynamic typing with weak typing. A language can be dynamically typed (types are checked at runtime) without doing things like automatically converting integers to strings, integers and strings to booleans, etc. etc. Conversely, a language can be statically typed and still do some of those conversions.