Reply to Randal on dynamic type systems

At first this I wrote this as a comment on my original post, but it grew a bit too long so I decided to post it like this instead.

@Randal, “Static typing is still effectively a syntax check, not a semantic check though.” Now, I think we might have a different understanding of the word “syntax”. I can guess at yours, but my understanding mirrors what’s on Foldoc, that is syntax determines what is a valid string in a program, in this case it determines where a type declaration/definition/statement goes, but not what type declaration/definition/statement is semantically valid in a particular position in a string. That “what” is very much part of the semantics in my mind, it tells the world (me, other users of my library, the compiler) a part of the intention of a function, it tells how something may be used. I gather you are mostly familiar with type systems like Java so what is clearer to you, this declaration:

int add(int i, int j);

or this declaration:

int add(i, j);

In the former the intent of the function is obvious, it adds integers. In the latter it isn’t, does it handle complex numbers? Does it handle matrices? In dynamic languages you’d have to document it somewhere, but there is no consistency check between code and documentation (maybe there are external tools for that though, but why not use the compiler to check?). You would also have to test that no caller of this function can be tricked into calling add with a non-integer.

Also, though your example of “semantic type checking” in the talk is interesting (I simply don’t know if there are any type systems that could deal with it) you completely skip all the cases where the type system can do the job and where it does save on testing and typing. In these cases you would have a proof relating to your use of types in the program, unit testing can never give that proof it can only show you haven’t disproved it yet :-)

If you remain unconvinced then I strongly urge you to read Tom Moertel’s post on providing safe strings, and the assurance you can achieve by using a strong type system in relation to information flow through your program. The same technique has been used in Darcs (watch the video, the bit relevant for this dicussion starts about 43 minutes in).

I urge you to read Kristian’s blog post (linked to in his comment).

If you want a podcast to listen to there’s episode 62 of Software Engineering Radio where Martin Odersky talks about Scala (a statically typed language built on the JVM).

I’d also like to clear one thing up, I don’t dislike dynamic languages and I don’t think that static languages are inherently better. What I do dislike about your talk is that it’s uninformed, presents very narrow arguments and then draws conclusions that are very general and simply don’t follow from the given arguments.

Finally, I really enjoy FLOSS Weekly. You and Leo are doing a fantastic job on it, but since it is where I first heard of your talk (I suspect Industry Misinterpretations might not get a lot of attention outside the Smalltalk community) I really think you should talk to someone from the FLOSS FP community. Get someone who can explain, much better than me, what a modern, advanced, strong, statically typed language will get you. I only have experience with OCaml and Haskell, and there are others, like Scala, all are FLOSS and hopefully it wouldn’t be too much work to find someone knowledgable who’d be willing to set you straight on the dynamic vs static typing issue. I’d be happy to do what I can to help you find someone, just let me know if you are insterested :-)

Share

11 Comments

  1. Your example of the dynamic definition is poor. That method would most likely be defined as: add(integer, otherInteger). In fact, I find such a definitions to generally be more readable than the static equivalent since you don’t have meaningless names like i and j.

    One area where I think statically typed languages do get a big readability benefit is the explicit definition of interfaces versus just relying on duck typing. That benefit can be reduced by defining a class to represent the interface, even if no other classes inherit from it. Unfortunately, in most of the code I’ve read it is not done.

  2. The example you give is trivial: add(int i, int j)

    More interesting would be how static typing helps or hinders tackling of more complex problems

  3. @Michael, you are right, the better way to document types of arguments in a dynamic language is through naming, but then you rely on everyone following that practice. That’s hard to achieve if you are interested in using 3rd-party libraries. Also, what do you name arguments in polymorphic functions, e.g. int in Python, int(convertableToInt)?

    @Robert, I chose that example because it is trivial. It’s something as central as a function call, something that shows up much more in programs than data types that require dynamic type checking like a date type. It is probably true that not all types can be automatically checked in a static language, but how can dynamic beat static if there is a need to manually check every function call in order to achieve the same assurance you get for free in a static language with a type system such as Java’s, not to mention Haskell or Scala?

  4. I’ll educate Randall on type systems if he likes. I’ve had to do it before based on similar mythologies but it was person to person/ However given the depth of his errors and the fact that I’d have to do it remotely, I think it would be difficult. I’ll give it a shot anyway — hopefully Randall is aware that perhaps he made a big mistake and will readily retract if need be — if only for his own learning purposes and make it easier to teach for me.

  5. I’d probably go with int(string_or_numeric). I wouldn’t go with convertableToInt unless I had defined a class/interface ConvertableToInt that implemented something like to_int or to_int_with_radix(integer), and int delegated to it.

    I tend to find that type safety doesn’t help me much in this situation. I’m much more likely to pass it an incorrectly formatted string than I am to make the mistake of calling int(employee_tuple) or int(customer_array).

  6. This piece would be much more persuasive were it not for the fact that so many people in the FP world (specifically the Haskell community) are guilty of exactly that which you now accuse Randal of: specifically, holding up a lesser example from another, competing paradigm as proof of your preferred paradigm’s superiority.

    Haskell bigots readily portray Python or Javascript (non-homoiconic languages) as prime examples of dynamic languages generally, even though they know full well of the existence of Lisp and Smalltalk. Even better, many of them persist in using Java or C# as examples of object-oriented languages. I have yet to see one pompous ass with a lambda symbol featured prominently on his blog write an intelligent, thoughtful critique of OOP that does not use C#/Java/Python/some-other-non-pure-OO-language in its examples, and instead uses Smalltalk or Self. The Haskell Wiki even has the gall to use C++! You would never take seriously someone who attempted to criticize FP using a non-pure language that had some support for functional programming, such as Perl or Python, and yet you fully expect me to do just that when you criticize OOP in the same fashion?

    Such hypocrisy and intellectual dishonestly is unbecoming of a community that prides itself on being more academic, better educated.

  7. @unconvinced, Besides that this post seems to have hit a nerve with you, you’re absolutely right, it isn’t acceptable anywhere. Please remember that communities are made up of individuals though.

    This post is about a talk on dynamic typing, not dynamic typing itself. It is also not a discussion on FP vs OOP, or any other paradigm for that matter.

    My reason for referring to Python rather than Lisp, Smalltalk, Perl, Ruby or any other dynamically typed language is simply that Python is the dynamic language I know best. I also don’t believe that the dynamic aspects of the type systems in those languages differ enough to be relevant in this discussion. Feel free to prove me wrong on that last bit though :-)

  8. There is a discussion on Reddit about this blog post.

    (OT: I wonder if I’m the only one who thinks that Reddit might do more harm than good in that thanks to it discussions don’t take place “at the source”.)

  9. There is one problem – the (int bla, int ble) does not allow anything else to be used at all. In Ruby for example, you do – or the object in question does – have the freedom to dynamically respond to whatever the OBJECT can, and act on that.

    In most situations this may not be needed, but having this very ability completely changes everything. It is like using your eyes, as opposed to using a spyglass:

    Spyglass is of not much use in the close distance, but it beats the eye easily for remote distances.

    Bot versions “int add(int i, int j); int add(i, j);” suck because they do require restricting systems ultimately (ints are used in both cases, why cant it simply be add(i,j) and it just works in the most logical way possible?). And let’s be honest – this was done to make the compiler happy, it was NOT done to make the human happy ….

    PS: I would love to see a scripting language that retains being dynamic AND learned from PROLOG. Now that would be a very interesting language to see – down strict logical, but also attempting to stay as agile as possible. Sounds like conflicting interest… but could be cool

  10. @mark, What do you mean by “this was done to make the compiler happy, it was NOT done to make the human happy”? In what sense wasn’t the “human” happy, and what “human” is that? Developer of the code in question, developer who uses the code as a 3rd party module, the end user?

    For all those cases of “humans” I know people who are happy with static typing, I also know people who aren’t happy with static typing.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>