Marijn has an elegant way of scaling his thoughts to the rhythm and measure of whatever medium he happens to be writing in, a quality which makes him consistently good to read.
His response to the workflow prompt is especially good. I'd like to reproduce it here as a way of flagging it for people who might not otherwise read the entire thing:
My approach to writing software is embarrassingly unstructured. I'm not sure I can claim to have something that merits the term 'workflow'. One thing that is very important for me, and that, had I figured it out earlier, would probably have saved some past projects from dying, is to never have a system in a half-refactored, non-functional state for longer than an hour or so. A lot of momentum and motivation comes from having a working program in front of me. This sometimes means I have to split up big changes in a number of more indirect, trivial steps, and resist the temptation to start hammering out my big change in one go (which, even when seems straightforward in my head, will always hit some complications during implementation).
Also, really learning git in depth has had a big influence on how I code. Once you really understand that changes (if you bother to commit often and with care) can be reverted and picked at will, and that branches are cheap and easy to create and maintain, you start to see a codebase differently. I often take multiple shots at making a tricky change — if it feels like my first approach is not working out, I simply commit it, back up, and start again, knowing that if the new approach doesn't work out, I can simply flip back to the old one again. Knowing that this is theoretically possible is not enough—you need to have actually done it, often, to start applying it properly.
I was interested in his response to the question, "What you dislike the most about Lisp?"
I must say that the lack of static typing really gets in the way on larger projects. Being able to confidently change datatypes and function signatures, knowing that the compiler will point out most inconsistencies that you introduce, is something that I've really come to appreciate after working with Rust and Haskell. Test coverage helps, of course, but I'm not a very diligent test writer, and tend to feel that type signatures are easier to maintain than an exhaustive test suite.
I've had the same experience. After working almost exclusively in dynamic languages for ten years I've been back to static typing in Scala, Java and C++ and in many ways its a welcome return. Dynamic languages are great for quickly hacking around small problems but I really appreciate the help of a good compiler and the kind of refactoring that modern IDEs can do in static languages.
Dart takes an interesting hybrid approach, making static typing optional but enforcing it rigidly wherever it is declared. (I'm not sure it originated with Dart, but that's where I encountered it.) This allows you to prototype things quickly without having to fuss about types. Later, when you're satisfied you've got the right idea, you go back and add static typing wherever having the guarantees that it provides would be useful.
I haven't had the chance to try this out yet. I'm sure some people like the fact that their programming language won't put up with fast-and-loose code -- you probably don't want your workout buddy to agree too eagerly to your suggestion that you skip the gym and grab a milkshake instead. But I think it might work for me. I'd be interested to hear about people's experiences, at any rate.
The google closure compiler does this. You can optionally annotate your javascript functions with type information (JavaDoc style) and the compiler will enforce it. For example:
Dylan does work in a similar way. One issue is that we don't go far enough yet, particularly with functions, so while you can specify a vector of integers, you can't (yet) specify a function that takes an integer parameter, just a function. We'd like to do something about that this year.
As far as I know, no. You can get SBCL to point out some intra-function inconsistencies through declarations (or, in fact, often even without declarations), but I haven't found a way to make it warn when, outside of function X, I'm calling it with types different from the types associated with the arguments through declarations.
I suppose you get at least some of the benefit. The other half of the advantage of a relatively simple statically typed language like Java is that IDEs can do really amazing structural transformations of your code. When I'm working in IntelliJ I'm constantly aggressively refactoring my code in ways I wouldn't dare in a language with less rigid syntax.
His response to the workflow prompt is especially good. I'd like to reproduce it here as a way of flagging it for people who might not otherwise read the entire thing:
My approach to writing software is embarrassingly unstructured. I'm not sure I can claim to have something that merits the term 'workflow'. One thing that is very important for me, and that, had I figured it out earlier, would probably have saved some past projects from dying, is to never have a system in a half-refactored, non-functional state for longer than an hour or so. A lot of momentum and motivation comes from having a working program in front of me. This sometimes means I have to split up big changes in a number of more indirect, trivial steps, and resist the temptation to start hammering out my big change in one go (which, even when seems straightforward in my head, will always hit some complications during implementation).
Also, really learning git in depth has had a big influence on how I code. Once you really understand that changes (if you bother to commit often and with care) can be reverted and picked at will, and that branches are cheap and easy to create and maintain, you start to see a codebase differently. I often take multiple shots at making a tricky change — if it feels like my first approach is not working out, I simply commit it, back up, and start again, knowing that if the new approach doesn't work out, I can simply flip back to the old one again. Knowing that this is theoretically possible is not enough—you need to have actually done it, often, to start applying it properly.