If you’ve been a programmer sometime in the last fourteen billion years you’ve noticed that there’s this conversation about type systems, specifically about comparing static type systems to dynamic type systems.
Dynamic typing doesn’t mean you can change the type of a thing (even though you sometimes can) it means you can change the shape of types themselves at run time. It means that you can tell a variable to write itself some new, strange, dynamic behavior, but you don’t tell it what to write, you tell it how to decide what to write. And you can eliminate a lot of duplication this way.
But static type systems don’t give you that ability. You have to define the shape and behavior of a type at compile time.
I know what you’re thinking: that really stinks! I want the ability to muck about with my variables, and have them run my code against their own internals and have them write new methods for themselves, and decide how they handle calls against methods that don’t exist, and even crazier things.
The static type system folks can do something that’s really powerful. They can use the type system itself as a global registry.
You see this in a lot of the C# written today, especially the stuff that makes heavy use of an IOC tool and generics. They’ll ask the system to get all the types that implement some interface, or for the types that close some interface and another type. Then they take these types and instantiate one instance of each of them, and use those instances in some way. Each instance runs in a chain or pipeline, or to apply a series of filtering functions to a data set.
The type system becomes a big dispatch table, with type names as global keys, but it’s more like a dispatch tree, because of polymorphism and generic type parameters and all that.
It’s freakin’ cool, once you start doing it – it’s elegant and easy compared to the old stodgy way of programming. And the IOC tools they use keep getting more interesting features that let them query the type-system-as-dispatch-tree in novel ways.
The dynamic type system folks will shrug and suggest implementing dispatch table with a hash like they’ve been doing in Perl for 15 years.
The static type system folks keep losing because their arguments are bad – Compile Time Checking and Tooling just aren’t cutting it. But they may be onto something if they could articulate the benefits of this global registry better than I can.
Pingback: The Morning Brew - Chris Alcock » The Morning Brew #743
I don’t think it’s about static versus dynamic. Tools and compile time type checking can be an advantage, or not. I’ll link to this post in my comments, since I think it adds a very valuable argument to our discussion over there.
Hey Matt,
Interesting perspective… but dynamic type systems can do the same thing with very little code. You mention the use of IoC containers as a way to store which classes implement an interface, and then retrieve all instances that implement it.
ok. here’s how i would do that in ruby, in a very naive way…just store the types of the classes that i’m concerned with… the ones that conform to a specific API (interface) that i define in a module:
of course, this is a very naive example… but it is the core of what you are describing in the post, if i understand your post correctly. note that i don’t need an explicit interface construct or a static type system, though. ruby is a typed language and i can do things with types in a manner that is similar to what you describe.
am i missing your point, though? i wonder if i’m looking too much into your statements about IoC containers (which are unnecessary in dynamic languages) and missing what you’re really trying to say.
oops… forgot to post the output of running this:
# ruby registry.rb
I can do something! and I’m a Bar
I can do something! and I’m a Foo
The types stored are:
Foo
Bar
Yes, I think you’re missing my point, reading too much into IOC tools, but, again, the point’s not very well articulated.
one last note… a dynamic language can still find all types and instantiate them based on specific API needs. it’s basically the same as doing it in C#… iterate over all known types, look for the API you need (an interface in C#, or method signatures or modules in Ruby) and instantiate the class.
in order to avoid the performance hit of doing this, though, an IoC container in C# will cache the found items in a hash (dictionary) so that the reflection code doesn’t have to be run every time you want something.
so, while the dynamic type people may shrug and use a hash table, a c# person is going to do the same thing for the same reasons – performance optimizations.
But the criteria to query aren’t available because the metadata isn’t available. Generic type parameters and interfaces. I was thinking specifically about
IHandler<T>consumed byConnectImplementationsToTypesClosing<T>, and the many and varied derivations of that technique I see and use.On the other hand – maybe these are fancy tricks only required in static languages because dynamic languages are so low ceremony. What do I know?
I would like to say, Derick, with all love and respect, that I dislike the overwrought example code you submitted. I don’t believe you would ever write that or anything like it. =D It serves to best demonstrate why you don’t need IOC tools in Ruby!
yeah, it’s a lousy example and has all kinds of problems in reality
it was more of an exploratory “i think this will work” in a very naive way… it produced a basic idea of how i might handle similar needs to what you were saying, i think, which is why i decided to post it.
i’ve heard some people say that IHandler is not necessary in dynamic languages and that there are easier ways of figuring out what handler to use… the code i posted might have some implications along those lines, but i’ve never really done my homework on that front in ruby because i haven’t needed it yet. i’m not writing anything that needs the equivalent of an IHandler, yet… though i suspect i will at some point.
by the way: i do think there are some distinct advantages that a static type system provides – i’m just trying to explore all the various avenues and opinions that i’m running into so that i can formulate a better opinion based on better information.