Where do you benefit from dynamic typing?

Disclaimer: I don’t want this to become a flame war in the comments. I’m coming from a position of ignorance, and well aware of it. While I’d like this post to provoke thought, it’s not meant to be provocative in the common use of the term.

Chapter 14 of C# in Depth is about dynamic typing in C#. A couple of reviewers have justifiably said that I’m fairly keen on the mantra of "don’t use dynamic typing unless you need it" – and that possibly I’m doing dynamic typing a disservice by not pointing out more of its positive aspects. I completely agree, and I’d love to be more positive – but the problem is that I’m not (yet) convinced about why dynamic typing is something I would want to embrace.

Now I want to start off by making something clear: this is meant to be about dynamic typing. Often advocates for dynamically typed languages will mention:

  • REPL (read-eval-print-loop) abilities which allow for a very fast feedback loop while experimenting
  • Terseness – the lack of type names everywhere makes code shorter
  • Code evaluated at execution time (so config files can be scripts etc)

I don’t count any of these as benefits of dynamic typing per se. They’re benefits which often come alongside dynamic typing, but they’re not dependent on dynamic typing. The terseness argument is the one most closely tied to their dynamic nature, but various languages with powerful type inference show that being statically typed doesn’t mean having to specify type names everywhere. (C#’s var keyword is a very restricted form of type inference, compared with – say – that of F#.)

What I’m talking about is binding being performed at execution time and only at execution time. That allows for:

  • Duck typing
  • Dynamic reaction to previously undeclared messages
  • Other parts of dynamic typing I’m unaware of (how could there not be any?)

What I’m interested in is how often these are used within real world (rather than demonstration) code. It may well be that I’m suffering from Blub’s paradox – that I can’t see the valid uses of these features simply because I haven’t used them enough. Just to be clear, I’m not saying that I never encounter problems where I would welcome dynamic typing – but I don’t run into them every day, whereas I get help from the compiler every day.

Just as an indicator of how set in my statically typed ways I am, at the recent Stack Overflow DevDays event in London, Michael Sparks went through Peter Norvig’s spelling corrector. It’s a neat piece of code (and yes, I’ll finish that port some time) but I kept finding it hard to understand simply because the types weren’t spelled out. Terseness can certainly be beneficial, but in this case I would personally have found it simpler if the variable and method types had been explicitly declared.

So, for the dynamic typing fans (and I’m sure several readers will come into that category):

  • How often do you take advantage of dynamic typing in a way that really wouldn’t be feasible (or would be very clunky) in a statically typed language?
  • Is it usually the same single problem which crops up regularly, or do you find a wide variety of problems benefit from dynamic typing?
  • When you declare a variable (or first assign a value to a variable, if your language doesn’t use explicit declarations) how often do you really either not know its type or want to use some aspect of it which wouldn’t typically have been available in a statically typed environment?
  • What balance do you find in your use of duck typing (the same method/member/message has already been declared on multiple types, but there’s no common type or interface) vs truly dynamic reaction based on introspection of the message within code (e.g. building a query based on the name of the method, such as FindBooksByAuthor("Josh Bloch"))?
  • What aspects of dynamic typing do I appear to be completely unaware of?

Hopefully someone will be able to turn the light bulb on for me, so I can be more genuinely enthusiastic about dynamic typing, and perhaps even diversify from my comfort zone of C#…

57 thoughts on “Where do you benefit from dynamic typing?

  1. I think you’re mostly right: dynamic binding is largely for niche scenarios.

    There are some good uses, though. For instance, multiple dispatch (i.e., dynamic member overload resolution). With multiple dispatch you can implement patterns such as Visitor, for instance, very easily and without modifying the visited class.

    Another good use for dynamic typing is when you want very low coupling. For instance, take a look at the extensibility point described here (ICustomMemberProvider):

    http://www.linqpad.net/FAQ.aspx#extensibility

    Static typing is a no-go here because it would require consumers to create a dependency on the LINQPad executable. To avoid this in C# 3.0, LINQPad must access the members of this interface via reflection which is really clumsy. Dynamic typing in C# 4.0 will make such things much easier.

  2. Granted, I’m not the audience you’re hoping for responses from, not being that experienced using dynamic typing. That said…

    It seems to me that one obvious context is where you want to implement some interface-like behavior, but you’re dealing with classes that are already defined. I believe Joe’s comment about the Visitor pattern would be a subset of this more general category?

    An example different from implementing the Visitor pattern might be loading objects from files. Lots of types define a “Load(string)” method where the “string” is a file path. But there’s no interface that these types all implement with that method in it. If you’ve got a system where you want to be able to load a wide variety of object types based on their own implementations of the “Load(string)” method, it seems to me dynamic typing would be useful.

    In other words, situations where by convention, a variety of classes have implemented what is essentially an interface, but where no interface has been declared or implemented per se (and for whatever reason, it’s impractical to go back and add the interface).

    Now, _that_ said…

    In C#, dynamic typing is as I understand it mainly a concession to interop. As a language design choice, other languages may follow dynamic typing as the rule rather than the exception, for specific reasons related to the expected/intended use of that language. But clearly that’s not really the case for C#. And just as clearly, there is _significant_ overhead involved in any use of dynamic typing, both in terms of performance and in terms of code maintenance (all of the sudden, the compiler can’t catch things, including simple things that don’t immediately seem related to the dynamic nature of the call site).

    I would say that at least in the context of C#, dynamic typing really is one of those “use only when absolutely necessary” things. For COM interop, Office interop, etc. I’m sure it’s very useful. But as an everyday construct in C# code, I would be very much against it, because C# already provides a good, performant static type system.

  3. @Joe Albahari:
    For your linqpad comment, it is a failure by design, that the Interface is only availlable in the executable of linqpad. It should be exportet by an external dll, that both, linqpad and and the extensions can reference – no need for dynamic typing here.

  4. @beowulfof

    You would still be asking the developer to take an external dependency (it matters not whether it is a executable or dll) rather than just pasting a tiny interface definition in. I think Joe made the right call.

  5. beowulfof: regarding the LINQPad interface, if that type was moved into a separate assembly, the dependency would become smaller in terms of KB – but the essential problem of the dependency would remain.

    IOW, people wanting to implement that interface in their types would need to deploy the LINQPad interface assembly with their applications – even though that interface may only ever be used in development situations.

  6. I work in php for my day job (yes yes, make your jokes) and C# for my hobby projects at night.

    To me, dynamic typing ends up hurting me more than it helps a lot of times. A number get interpreted as a string when it shouldn’t or some other small bug that bites you in the butt at some point.

    I will have to agree with the Terseness part though as I quite often have code like this:

    // Code taken out of context purely for example
    if($options !== null)
    {
    if(is_object($options) &&
    method_exists(array($options, ‘toArray’))
    {
    $options = $options->toArray();
    } else {
    $options = array($options);
    }

    if(is_array($options)) {
    $this->setOptions($options);
    }
    }

    I can pass in an object with a toArray method, an array, or I can wrap it in an array. Php also has some basic type safety so I could say in the method that the argument must be an array otherwise crash the script.

    That could of course also be done in C# but you would have to write many more methods.

  7. I think that adding dynamic typing to C# in this limited capacity doesn’t hurt things but I think its usage is very restricted to COM interop. In other words I don’t really see dynamic typing solving problems (outside of COM interop) in normal day-to-day activities of C# developers.

    What I would have loved to see would have been some kind of structural typing (http://en.wikipedia.org/wiki/Structural_type_system) support in C# that would have been an interesting compromise between C#’s static type checking and the flexibility of dynamic typing. I just don’t see C#’s dynamic typing being used that much outside of interop (COM, Python, etc.) and as such I am somewhat disappointed at the narrow focus of the new language feature.

  8. I think we need some of the Linux Ruby-on-Rails type of folks here to answer these (brilliant) questions convincingly, but I’m not sure many of them read C#-oriented blogs (in my experience most of them like to pretend they don’t know what C# is).

  9. Testing legacy code. I’m not sure if this is dynamic or mixins. I write a lot of code that depends on legacy Java code that is impossible to mock out db access for example. What I do is using JRuby, create the object, and while I have the object in memory, swap out the method that accesses the database for one of my own choosing. Very useful.

  10. dynamic typing is not a niche feature. it is useful to simplify the language so that it can be used by inexperienced people. _thats_ why python and ruby are getting some attention these days. statically typed languages might be more productive but the concepts are much harder to understand.
    as most programmers are frankly idiots dynamic typing is not a niche feature. unfortunately.

  11. Also the fact that most people in the comments of this blog seem to agree that dynamic typing is generally inferior to static typing is a sign of quality for this blog. People who hang out here know what they are doing when they type in a program. congrats jon.

  12. I like what Erik Meijer said: “Static when possible; dynamic when necessary.”

    Some food for thought (you can draw your own conclusions):

    1. Some problems are inherently dynamic. E.g., web requests. You can’t compile the internet! MVC uses reflection for this today. I think that dynamic typing is a more expressive approach to the same problem.

    2. The expressivity I mentioned above is itself compelling: Reflection introduces a strong dependency on a mechanism. Dynamic invocation says, “Here’s my intention; please do this in the fastest way possible.”

    3. Higher order types with complex constraints can be intimidating to mere mortals. Read the Scala spec for an example. Even C# “pros” frequently don’t understand the subtleties of contravariance and covariance, and frankly C# gives you only the “easy” parts of higher-ordre typing. By contrast, dynamic typing “just works.” When it works, that is!

    4. Static vs. dynamic typing is not the be-all and end all of program correctness. They are part of a spectrum of tests over time which include, but are not limited to: Compiler checking, unit tests, assertions, static analysis, runtime verification, etc.

  13. @Joe Albahari
    >regarding the LINQPad interface, if that type was moved into a separate assembly, the dependency would become smaller in terms of KB – but the essential problem of the dependency would remain.
    Not Quite, but if the plugin references the executable you have a circular reference.

    >IOW, people wanting to implement that interface in their types would need to deploy the LINQPad interface assembly with their applications – even though that interface may only ever be used in development situations.
    Not really, they should reference the dll of the hosting app, but need not to deliver it with themselves.

    >You would still be asking the developer to take an external dependency (it matters not whether it is a executable or dll) rather than just pasting a tiny interface definition in. I think Joe made the right call.
    Sure the developer of a plugin would have the need to reference the interface dll, but self-implementing an Interface that has same properties and methods as the one in the executable does not make it the same interface!

  14. They are great for Object-Relational Mapping. Consider this bit of code:

    var customer = conn.CallProc.CustomerSelect(AccountKey:1234);
    Console.WriteLine(customer.FirstName, customer.LastName);

    I have a library that allows you to write code like that without any ORM mapping files. It understands that anything that follows “CallProc.” should be translated into a stored procedure of the same name. And then it returns dynamically typed objects containing the results.

    I feel comfortable using this because it is no more dangerous than what you would get if you were passing around DataTables and reading columns using string.

    The source code is quite simple, less than 700 lines for the whole ORM, and should be posted on InfoQ later this week.

  15. @Jonathan: Is that better than generating code from the database metadata, which would then give you intellisense and prevent typos? I’m not trying to be argumentative – I’m genuinely trying to understand the benefits.

    I can certainly see them for spiking – avoid all the roundtrip time of the code generation etc. But in a stable database where I don’t mind spending a little time upfront in code generation for the sake of long-term maintainability, is the dynamic approach better in some way that I’m missing?

  16. Appendix. A few more ideas I missed in my first post.

    5. Unit testing in dynamic languages is dead easy. Mocking frameworks? Don’t need ’em. Test frameworks? They’re icing on the cake, but not really a requirement.

    Relevant to dynamic types in .NET, but not really an advantage of dynamic typing per se, and not really relevant to C#:

    6. In the DLR, you can support type semantics foreign to .NET without introducing a parallel hierarchy. So if your language has immutable string references, you can have that on top of the standard System.String.

    Relevant to dynamic types in C#, but not really an advantage of dynamic typing per se:

    7. Interoperability with dynamic languages. Inter-language interoperability is one of the tenets of .NET. So you can run that Python spell-corrector if you need to, or (more likely) can allow user scripting in your app.

  17. Jon, regarding DBs and code generation, I agree, but there are schema-free DBs. Not surprisingly, they seem to be popular with the same folks who like schema-free source code. 🙂

  18. Personally, I see dynamic typing as primarily a workaround for lack of features in _existing_ statically-typed languages, and secondarily a way to improve _writability_ at the expense of _readability_ (which may be good for shell scripts, hacks, experimentation w/ REPL, etc., but bad for building large, robust, reusable systems).

    But I could also be suffering from Blub’s Paradox.

  19. Personally, I feel that I tend to have much less time dealing with inheritance hierarchies in dynamically typed languages. I have spend much less time moving methods between interfaces and casting and whatnot. So perhaps a reason to use dynamic typing is to simplify classes that would otherwise have a lot of interfaces or require a lot of needless casting?

    Secondly, there are some syntactical benefits of dynamic typing. For example, in Python, you can generate an XML-RPC client that would work like this:

    xmlclient.some_method(some_arg=’foo’)

    Lastly, I’d like to point out that you’re kind of stacking the deck against dynamic typing. It shouldn’t be reduced to “don’t use dynamic typing unless you need it” any more than it should be reduced to “don’t use static typing unless you need it”.

    This is about choosing the best tool for the job. Does static typing simplify your code and make it more maintainable? Use it. Does dynamic typing simplify your code and make it more maintainable? Use it instead. Trying to choose a “default” is going to make you choose static typing in cases where dynamic typing is

  20. My company has a product in which a ‘type system’ in terms of properties and values are pulled dynamically at runtime from a dll that provides description information.

    Currently, we have a complex TypeProvider implementation that allows WPF to see these dynamic properties as regular properties with respect to databinding, however, the rest of the code must work with the raw dictionaries and cannot treat these items as properties.

    Our spikes with VS 2010 and the dynamic keyword have allowed us to create a much simpler model for the creation of the properties and the rest of our code can treat these dynamic elements as properties.

  21. @Al Tenhunfeld: I hadn’t, but ironically it’s very similar to the example I’ve used in C# in Depth (down to the very idea of the XML containing books and authors!).

    Of course, it won’t work with XML namespaces, but yet, it’s kinda neat. I’m not sure that much of the *real world* code I write that deals with XML would benefit much, but maybe…

  22. @Jason: Why do you have a lot of casting anyway? I don’t find I need much.

    For the XML RPC side of things – if a service doesn’t publish a schema of some description letting you create a statically typed proxy, dynamic typing does indeed help. However, that kind of thing doesn’t fill me with confidence in the first place.

    Finally, in terms of “stacking the deck” – there are obvious benefits to static code: better tooling support, problems are found earlier, and performance. To me, that suggests that dynamic typing needs to show a benefit which outweighs those ones. I’m certainly amenable to the idea of using dynamic typing *if* it simplifies my code and makes it more maintainable – which is why I’m asking where that comes up in the real world.

  23. @Steven: That’s an excellent example, thanks. I think it’s fair to say that in many/most of the cases where you’re *already* working dynamically (using reflection etc) the dynamic typing in C# 4 is likely to be a good fit.

    I’m just struggling to understand why something I personally find useful so rarely is worth abandoning the benefits of static typing for *throughout the language*. I feel I must be missing out on why dynamic typing would be useful *every day*.

  24. @Alan: I don’t see much in there about dynamic typing specifically. (I’m also somewhat bemused by the line “You’d never see a Java program that was configured by writing Java code” – someone hasn’t used Guice…)

    It seems mostly to be about trying to avoid writing Ruby with a Java accent, which is all very well but it doesn’t give me much idea of why dynamic typing is a good thing.

  25. I see C#’s dynamic keyword as so much more than just dynamic (duck) typing. There’s a whole world of fun stuff to do with DynamicObject.

    For instance, someone asked about an equivalent to HLSL swizzles in C#. Now, these don’t use duck typing, infact it’s very clear at compile time by examination of the code exactly what types are being thrown around (even though the compiler can’t because it’s using the dynamic keyword)

    For an explanation of the code I wrote and some usage, you can see http://matt.scharley.me/portfolio/project/view/swizzle or for direct download of the code, http://matt.scharley.me/links/links/goto/24

  26. @Matthew: dynamic is only to do with dynamic typing, but there’s more to dynamic typing than duck typing. I’ll have a look at the swizzle stuff later on 🙂

  27. I have been waiting for dynamic for some time to fill the IDispatch void.

    I am building .net components on a c++ plugin framework and some of the event driven subscriptions fail due to lack of IDispatch support.

    with .Net 4.0 I should be able to easily register a derived dynamicobject type.

  28. (1) It is easier to write higher-order code with dynamic types. For example, I have a set of operations that each use different subsets of the methods on interface A. If I just want to use one operation on my new type, I have to implement all methods on A even though it’s not necessary. With dynamic types, you just use the operation and hope it works.

    (2) In rapid prototyping, one can make changes quickly without having to update type signatures everywhere. Type inference reduces this burden in ML, but C#/Java is still a pain.

    Dynamic types are too dangerous, but C# is too verbose. The right balance is static typeing with type inference.

  29. @skeet – Yeah, but you’re Jon Skeet. 🙂

    In all seriousness though, I’m a bit of a newb when it comes to typing in Java/C# and I seem to have issues with typing in C#. Although I’m sure I can get around this issue with some experience, that at least makes dynamic typing more approachable.

    I suppose what it ultimately boils down to is reduced complexity. Interfaces? Don’t need ’em. XML schemas for XML-RPC calls? Don’ t need ’em. True, none of these add a huge amount of complexity, but my experience is that programming is ultimately more a game of hiding a bunch of little details more than it is about fighting huge complexity issues.

    The biggest benefit is that with dynamic typing, I don’t usually think about types. If I name something people, then I think of it as representing people. Type inferencing is a two-edged sword for this problem. The majority of the time, I don’t have problems. But when I do something wrong, it can be difficult to figure out exactly what went wrong because all of the type information is obscured. With dynamic typing I can at least hit it with a debugger when I get typing issues.

    Lastly, I don’t disagree with you regarding the benefits of static typing. The difference is that now you’re thinking in terms of pros and cons of *both* static and dynamic typing. By reading just the blog post, it comes off as though you’re only thinking about the pros and cons of dynamic typing. It’s difficult to do a comparison when you’re only thinking about one side of the story. 🙂

  30. “A number get interpreted as a string when it shouldn’t”
    Those sorts of things are more a failure of PHP than of dynamic typing. PHP does very odd things and likes to interpret too many things as strings.

    Whilst not strictly relevant, http://www.pphsg.org/cdsmith/types.html is an interesting read.

    To me the benefit of dynamic in C# is that it provides a uniform way of doing what we already do a dozen different ways — communicate with IronPython, XML, JSON, web services etc.

  31. “Those sorts of things are more a failure of PHP than of dynamic typing”

    But is the concept *truly* separable from the language? In the end, we’re talking about the way that the compiler (or interpreter) handles the code. By some standards, VB.NET supports “dynamic typing” with Option Strict off. Clearly its reflective late binding is…um…less than performant, but the concept of not having a clear inheritance hierarchy (that’s visible at that point in the code, anyway) to prove or disprove the existence of a type member is still there.

  32. To me dynamic typing is useful when the domain you are dealing with is itself untyped in nature. As have been pointed out several times in the comments XML (XML-RPC, etc.) is such a domain. If you are dealing with such a domain you need to cast all the time which means that you are practically using dynamic typing because your code can fail at runtime if you did not made the right assumptions when casting.

    It seems that especially in web programming people tend to use many untyped representations of the data like XML, HTML, JSON. This is why I believe that JavaScript is so well suited for the web and DOM manipulation in C# (without dynamic) will be much more painful. Also it seems that UI code tends to be untyped. HTML is one example but you can look at WPF or even Win Forms. Usually you have a tree of controls, you don’t know the exact type of the control and you need to cast. What is more UI code does not need to be strongly typed that much because usually nothing depends on it so a bug in it will not propagate to any other layers in the application and you are not likely to have unexpected branches of the code.

    On the other hand the backend needs to use static typing. It will help with the performance and it will help track all the dependencies when you make a change. Also static typing should not serve as an excuse not to have unit tests (as it happens in my projects 🙂 ) and if you have unit tests why bother with type safety. To me the biggest benefit of static typing is BRUTAL intellisense and refactoring capabilities.

  33. @Stilgar: Thanks for that comment, it’s very interesting. I agree with you about untyped environments, although not so much about the UI side of things – even if you don’t have *total* type knowledge, you still often know that you have “a control” which will have certain properties etc.

    I also disagree about: “If you have unit tests why bother with type safety” – to me the answer is “because it makes it easier to be correct about how I use a component”. If that component is written using dynamic typing, I have to pore over the documentation and unit tests to know what I can expect to pass in and what it should mean. Static typing gives me that information in a much more efficient form, IME.

    Also, “having unit tests” isn’t a binary condition – I’ve often seen suggestions that dynamic environments require *more* unit tests than static environments. Thus type safety (not quite the same as static typing, of course) reduces the testing burden. You still need unit tests, but potentially fewer.

  34. “If that component is written using dynamic typing, I have to pore over the documentation and unit tests to know what I can expect to pass in and what it should mean. Static typing gives me that information in a much more efficient form, IME.”

    This is one of the things I had in mind when I pointed out BRUTAL intellisense. I believe it can save enough time to compensate for the additional code you write when using static typing.

    I am not really sure whether dynamic typing requires more unit test. I can see it allowing more branches => the need for more tests but I am not sure if this is what happens in practice. My experience with unit testing is limited and I’m ashamed of that 🙁

  35. As an example, i need (really often) to have Mix-Ins or multiple inheritance.

    For instance, i have a class that describes how my page (or user control) should be rendered. I want it to be extensible.

    public class HowToRenderControlA {
    public bool ShowThis {get;set;}
    public bool ShowThat {get;set;}
    }

    Then i want to show how to Control B. I create another class.

    Then i have a control C, that has lot in common with A and B, and it would be great if i could have those classes all together and their properties accessible.

    Or just add a custom something to A or B in some cases.

    It’s easy implementable in Python, Ruby, Scala, but takes reflection (or Lin-fu, Castle) in c#. And, btw, if i even dared to use lin-fu, i need to call my methods / access properties not thorugh .CallMethod(), but through (“CallMethod”, object[] {}). You know what i mean? 🙂

  36. I’d like to stress the importance of duck typing when doing rapid development (eg prototyping): strict type hierarchies are something you don’t want to bother with when using a bottom-up approach.

    This can be achieved in a statically typed language with a structural type system where there’s no need for explicit interface declaration: if a class has all the methods required for an interface, it is automatically of the apropriate type.

    A consequence of this is the possibility for decoupling of functionality from class definitions: Eg in JavaScript, you can use the generic array methods with any array-like objects (basically anything which has a numeric length property): Call them explicitly via `Array.prototype.slice.call(foo, 13, 42)` or just assign the method to the object (ie `foo.slice = Array.prototype.slice; foo.slice(13, 42);`).

    One of the main features of Google Go is such a type system; this isn’t really something new as some functional languages (I might be wrong here, but I think OCaml and Dylan; might even date back to ML) have supported this for ages.

  37. @Joe and Paul: I’m with beowulfof on this one. The reason is simple: You have a dependency nevertheless. Extracting the interface into an own DLL makes this dependency explicit such that it is clear. With duck-typing in place, you have to trust that the interface doesn’t change and there’s nowhere a clear note or whatever about the importance of the original interface to remain unchanged.

    To dynamic typing I second the opinion that it depends on the context. So, for example in production code I’m a strong opponent of it as it opens up the box for a whole lot of errors and hard-to-reproduce bugs. But still, dynamic typing is good in a lot of scenarios such as tests, where duck typing can be used etc. Please note that I wrote ‘tests’ and not ‘unit tests’ because tests are so much more. You need integration tests etc., which are often tightly integrated into a whole environment with shell scripts etc. and dynamic typing is a godsend there.

  38. There is the classic interview with the BDFL here http://www.artima.com/intv/strongweakP.html.

    Bottomline for me is: static typing won’t support you anyway the whole way down when describing allowed values for variables, so why start bothering at all. That’s true at least for business applications, e.g. how many business app developers really understand C++ templates or covariance, what’s the canonical solution in C++/C#/Java for nulls and how many validation libraries do you find for each of these languages? Typing a variable and being able to compile with that type is fine, but you’ll still get NPEs and have to check values.

    Admitting that, a dynamically typed language helps you to start quickly – especially if you’re used to prototype in a REPL – and part of the time saved can be used for interface documentation, unit testing, and more thorough runtime type checks.

    The last decades I went back and force between Perl, C++, Java, Python, and C#. I still use Python when I’m prototyping in code since then Python’s shortcuts pay off immensely, but C# shifts me more and more back to the static camp, because newer versions don’t add too much ceremony. And intellisense is a nice thing to have. If only the otherwise brilliant Anders would have avoided “The Billion Dollar Mistake”…

  39. @Frank,

    “static typing won’t support you anyway the whole way down…so why start bothering at all”

    That’s like saying “A seat belt doesn’t guarantee that I won’t die in a car wreck, so I won’t bother wearing one.” Just because a type system can’t statically prevent every possible type of run time error doesn’t mean that it isn’t very useful.

    Do people really save a ton of time using a dynamic language for “prototyping”? You still have to deal with type problems in prototype code, and in my experience the actual percentage of the code I write that is dedicated to satisfying the type system is extraordinarily low.

  40. @David

    First, that was my summary when reading Guido’s post at that time, and was/is not necessarily my position. At the time reading this, I was a very pedantic private/final/const coder. But nevertheless Guido’s thoughts were and are very convincing for me. Mostly working on business apps, the code ratio dedicated to satisfy the type system is confessedly often low, but the code ratio to check for correct values and handle validation errors is frustratingly high: All these nice types and I still can’t make compile-time sure that my pH value is just between 0 and 14 (as I could in PASCAL decades ago), my string is between 1 and 10 characters, and I still have to maintain code which starts with 10 lines of null-checking.

    Sure, writing ‘var’ instead of ‘string’ doesn’t save a lot of time, but prototyping in python with ‘*args’ and ‘**kw’ arguments without having to overload a dozen methods or simply defining a ‘names’ argument without bothering about covariance or list/array conversion can – not for saving a few keystrokes but for being able to braindump your mental model without getting lost in details.

    On the other hand, once the model becomes more firm and more code uses the model, types checked by the compiler could save time. But now that won’t work in Python, but as I’ve learned, it quite often works in C# with type inference and optional dynamic typing.

    Jon was asking for the pro’s of dynamic typing – I know and stated some and I wanted to share the exhilarating effect of Guido’s article. Funnily I still feel this flame war inside me, after all these years, so why not also share that with you 😉

  41. @Frank

    I am not trying to start a flame war. I am just looking for an answer to the same question that Jon has asked. I still haven’t seen any practical pro’s of dynamic typing listed, nor does Guido’s interview present any compelling arguments for me. He makes a lot of unfounded assertions and basically takes it for granted that dynamic type systems are somehow “easier” to program in, without offering any evidence of that.

  42. I’d say the most prominent places where dynamic typing is useful are in interop, use of dynamic language runtimes, and for very loosely bound service interfaces. The combination of loosely bound services could be interesting… Pass your request and frobber/filter to the service… the service does an overlying pass based on the request, and runs it through a frobber or filter than is passed as a dynamic language for execution, then sending back the results. The last point would probably be best limited to trusted resources for the request though. There are many times where internal business units have to communicate and control different application, or data domains. The use of dynamically typed relations allow for data structures to grow/change in one system without breaking others.

  43. I think dynamic typing could be usefull for attached properties. A Canvas would like to set the Canvas.X and Canvas.Y property on anything that can be draw, where as a grid would probably want to set the Grid.Column an Grid.Row.

  44. Regarding XML, it could allow for a dynamic object that takes a CLR XML data type, and wraps it into a selector class that supports E4X or similar notation. That could be done pretty easily.

  45. Dynamic typing doesn’t give you anything if you are approaching it from a static typing mindset. You should get out of C# and Java and write a non-trivial app in Ruby or Python to really understand the benefits.

    In other words, the benefits are more about what the language enables you to do. Change the language, change the type system, change your approach.

  46. @Mike: I realise that throwing myself into the deep end would be the best way of understanding the benefits… but I tend to be loathe to do that unless those who *do* understand the benefits can at least explain them in a fairly appealing way beforehand.

    This post was an attempt to get those explanations – if there’s really no way of appreciating why it’s worth having dynamic typing “on” all the time when programming (instead of only in specific situations) without investing a huge chunk of time to it, I’ll be somewhat disappointed 🙁

  47. The problem is that the typing system is just one aspect of a larger picture. If you don’t have dynamic dispatch (like you do in Ruby but don’t in C#), then dynamic typing is the same as passing everything as an object and casting it to the desired type in your methods. If your language doesn’t make it easy to inspect or reflect on your objects, then dynamic typing is more likely to cause you more ceremonious pain than syntactic gain.

    Ruby emphasizes behavior at runtime. C# emphasizes behavior at compile time. Turning dynamic typing “on” in C# is not the same as taking full advantage of a dynamically typed language like Ruby. The differences in the languages are so much larger than their respective syntax. I don’t think you can truly learn and understand dynamic typing in a statically typed bubble.

  48. Generally, I believe that many of the things you can do with dynamic typing can also be achieved with well-designed strongly-typed code. However, there are a few areas where dynamic typing can add a level of expressiveness that strongly-typed languages lose. For example:

    1. Creating Domain-Specific Languages. I’ve seen a few elegant examples of this in languages like Ruby and Python; and while you can certainly do this in a strongly typed language (the MS DSL framework is actually quite nice), dynamic typing helps you fit the syntax and structure of your DSL to better fit your domain. Also, when creating DSLs a common task is to transform the constructs and expressions in the DSL into equivalent forms in another representation (C#, SQL, etc.). Untyped languages allow you to treat all expressions homogeneously. Take a look at http://www.artima.com/rubycs/articles/ruby_as_dsl.html.

    2. Configuration Management. Many systems today use high-level, strongly typed languages like C# or Java for their implementation, and then rely on flimsy XML or KVP (key-value pair) models for configuration. I have two major “beefs” with using XML/KVP for configuration: a) the structure and syntax of XML/KVP is obtuse, and lends itself to a lot of repetition/redundancy, and b) XML/KVP is entirely declarative and generally doesn’t provide a way to intermix imperative statements. For example, try creating a web.config file that scales the number of worker threads in your ASP.NET thread pool to be equal to the number of CPU cores times 3. You can’t. Or try dividing a single configuration file into manageable modules that get “dynamically included” as needed. Not generally possible. But if you use a language like Ruby or PHP to define your configuration, you can easily mix declarative and imperative constructs as you need to; you can also dynamically assemble them from multiple fragments.

    3. Meta-Programming. Strongly-typed languages can make it hard (or impossible) to do generative programming or construct type-agnostic higher-order functions. For example, writing a code in C# that takes an arbitrary function (with any number of parameters/return value), a list of parameters, and then “mapping” it onto some set of data or an iterable collection is not possible. Languages like F# take the approach of performing sophisticated type inference based on the definitions of functions to ensure type-safety. Languages like Ruby/PHP go the other direction and essentially ignore the types involved in the expression, assuming that the programmer will ensure that all types are compatible/coercible. I don’t know which approach is ultimately better, but I can say that when I’ve needed to write generative meta-code I find it easier in Ruby than in F# (Full disclosure: I’ve only tried it twice in F# and given up each time because my limited brain wasn’t able to grok the intermediate or end result).

  49. @Leo: Thanks, that’s exactly the sort of thing I was looking for. (You might want to look at Guice for the second option, btw. I don’t know if any of the .NET IoC containers work in a similar way.)

  50. Er, somewhat late.

    I work in both Delphi and Python. Delphi is strongly statically-typed; Python is strongly dynamically typed. My understanding of how to work in each differs according to the following point-of-view substitution:

    1) When in Delphi, my typical thought is, “When I am inside a method with arguments, what feature set (fields, properties, methods) does each argument support?”

    2) When in Python, my typical thought is, “When I am calling this method with arguments, what features (fields, properties, methods) must be available within the arguments I provide?”

    Now admittedly, this is as much about duck-typing as it is about dynamic typing (how could it not be?), but the essence of the difference is the massively increased scope for polymorphism in Python compared to Delphi.

    Given something like

    def foo(arg)
    arg.method()

    it should become clear that anything passed into foo that has a “.method()” in it will work. There is a huge difference between this, and setting the type of the argument to be some ancestor class from which it is required that all objects needing to be passed to “foo” must be descended.

    In these situations, duck-typing, and as a consequence dynamic typing, sidestep the problems relating to multiple inheritance that tend to become problematic in statically-typed languages (subjective, agreed, but my opinion).

    I struggled with this a great deal initially, because I found it very difficult to grok Python code because I never knew what was being passed into functions; how then to know what the arguments support?

    The resolution to this problem lies in learning new habits in reading code: what defines the argument to a function (in a dynamically-typed language) is what gets *done* to it in that function, not what it *is* outside the context of that function. Again, this is about duck-typing, but dynamic typing is required for this to work. In python, a “valid” argument to a function means something (anything!) that will provide the functionality that that function requires. In a sense, one must temporarily suspend one’s normal thought process that would apply when reading statically-typed code. The “type” is set by what the argument is required to be able to do, not by external declaration.

    I can shift between Delphi and Python quite easily, and the difference in typing mechanisms is not a big deal (given the shift in understanding described above). Code reuse is obviously greater in python, because functions are agnostic w.r.t. types, and therefore somewhat more atomic. I get to be lazier in Delphi because the IDE and the static typing require less planning upfront, but I am generally more productive in python because the standard library is so good, and I can write functions to operate on my classes before the classes are even defined. In this respect, I constantly rely on dynamic typing in python as a language feature.

    My experience with respect to safety (or danger, depending on how full your glass is) is that for both Delphi and Python, the prevalence of bugs is about equally likely and has nothing to do with static or dynamic typing, although every so often my Python code surprises me by running correctly on the first try.

  51. @cjrh: So when you’re *calling* a method, how do you know whether a method will be valid or not? Does the documentation always specify everything that will be called on that argument, and what it expects those calls to do?

    To me, static typing is a way of providing that information in a single word… and with interfaces, the lack of multiple inheritance doesn’t get in my way much anyway.

    The downside is situations where various types *do* have the method I need, but they have no common interface. That’s where duck typing would really shine – but I don’t find I come across it that often. Is it regularly a problem for you when you’re coding in Delphi?

  52. @skeet:

    For knowing what can be passed to a function, it seems that conventionally you either:
    a) follow documentation (if it exists)
    b) get documentation from the docstring of the function at the REPL prompt, e.g. “>>> print help(foo)”. (this usually exists)
    c) read the source. (this always exists)

    It is often the case that a python library will say something like “this function should be passed a file-like object” (cf. Django), which means that you can pass actual file-like objects, but also anything else that contains .read() and .write(), and perhaps a few other members that might be explicitly mentioned in the docs. In practice, it is not that bad once you fully internalize the fact that the argument type doesn’t matter, only the operations performed on it. On the other hand, every now and then I see recipes for performing explicit type-checking on the arguments to functions, which seems IMO completely misguided (they should rather check for the existing of required methods/members on the arguments).

    Lack of multiple inheritance…perhaps I wasn’t clear earlier: I tried to explain that duck-typing gives you, among several other things, basically unlimited polymorphism, which feeds greater code-reuse. That has pros and cons. One can always live without it (one can get by with very little, I have used FORTRAN somewhat) as you said, but that is IMO a significant benefit of dynamic typing. ymmv and all that. The relative weights of the pros and cons vary for different use cases, different projects, different individuals. You’re a smart guy, and you’ve heard all the arguments before. If you’ve already tinkered with something like python yourself, and found it came up wanting, well then that’s that; but if not, there is something else remaining to do: see for yourself. The tutorial included in the python install takes about 2 hours to get through, and gets you about 80% effective to write programs.

    I find this discussion similar to how the introduction of subversion as a version control system caused much angst (myself included) because it removed file-locking (Oh No, everything will be clobbered!). But once you get used to the extra freedom, and deal with exceptional cases as required, you wouldn’t want to go back. Of course now we see a similar trend regarding the DVCS backlash with many people clutching at the safety of their SVN. But in a few years, DVCS will be completely dominant and we’ll be asking ourselves however did we get anything done without it.

    The fact that static typing still produces the benefit of fast-running code remains a very compelling point for a large number of use-cases. Were dynamic languages to close the performance gap more substantially than has been the case so far, I would expect to see a much greater shift in that direction. The claim that static typing is “safer” than dynamic typing is often made, but it has consistently been my experience that there is no difference in the nature and number of bugs between my delphi code and python code. It just takes me longer to produce them in Delphi. Oh, and I pretty much never get off-by-one errors in python, because almost everything is directly iterable; but this has nothing to do with dynamic typing.

    Regarding feature frustration, I don’t code in Delphi the same way I code in python, so in Delphi I don’t even think in these terms, therefore the lack of duck-typing is not problematic. I guess in a sense you just resign yourself to duplicating code for different types as needed. You do your best to abstract, but only so far and no further, and then deal with it. It is not something that I think about often. Idiomatic Delphi is very far from idiomatic python. It is sometimes frustrating to have to declare so much upfront in Delphi, and lack of multi-line strings really suck, but regarding object patterns I stick to the tried and tested, straight and narrow simple object inheritance with minimal polymorphism sprinkled throughout; and this works reliably and well. It’s kinda like asking if I miss LINQ in Delphi, or asking a FORTRAN programmer if they miss Delphi classes: the question itself seems odd, because idiomatic use of each language implementation accomplishes similar objectives in different ways. This isn’t only a language issue, because the specific implementation, including the provided libraries make a big difference. The most powerful syntax in the world is no match for a single library call that does everything you need, for example.

    I will say that the more complex the problem to solve, all else being equal, the more I will be looking towards Python rather than Delphi, and I think the dynamic nature of python plays a huge part in that, especially when the problem domain isn’t even fully revealed before you start writing code. In contrast, the simpler projects, especially GUI-based stuff would be done in Delphi.

  53. @cjrh: Thanks for all the detail. I find your last comment particularly interesting – I would have expected an approach of “quick and dirty, one off code is fine in Python – for large enterprise systems I’d use Delphi.” It’s interesting to hear it working the other way round…

    It does sound like I’m not going to appreciate the benefits of dynamic typing without diving in for a significant project – which is a pain, as I haven’t got time to do that at the moment 🙁

Comments are closed.