How often do you take advantage of dynamic typing in a way that really wouldn't be feasible in a statically typed language?
What I'm interested in is, how often these are used within real world (rather than demonstration) code?
How often do you take advantage of dynamic typing in a way that really wouldn't be feasible in a statically typed language?
What I'm interested in is, how often these are used within real world (rather than demonstration) code?
To be honest: Most benefits dynamic languages (note that I'm saying "dynamic language", not "dynamically-typed language") offer don't have anything to do with dynamic typing itself (and Python is my favourite language!). They only get so much attention because most statically-typed languages suck hard when it comes to flexiblity. Haskell is often pointed to when it comes to this topic - for a reason. In practice, I see little difference between what a static but expressive (e.g. inherently generic) and a dynamic type system can do.
The main benefit commonly associated with dynamic typing is extensive polymorphism/duck typing/generic programmming. E.g. most of my Python code works just as well if someone comes along and passes it something of a different type, as long as it has the fields/methods my code uses (provided those are roughly equivalent, too). Basically, it saves us the hassle of creating an interface which is as minimalistic as possible and explicitly implementing in every class we may want to pass to that particular function. The benefits should be self-evident.
As noted above, this is unrelated to static/dynamic typing (there's this structural typing thingy which imho boils down to duck typing with more extensive compilance checks at compiletime). However, in practice these two come hand in hand, as there is no statically-typed mainstream language with structural typing (ML/Ocaml/Haskell/... are anything but mainstream, and Go has still a long way to go) with the possible exception of C++ templates (which are infinite pain compared to e.g. Haskell).
In theory, you can essentially "simulate" dynamic typing inside most statically typed languages, by encoding values in some kind of tagged union and making all operations behave correctly based on the input "types" (actually the input values). Of course, you then have to introduce a bunch of runtime error behaviours that occur when you encounter nonsensical operations on these values.
Most of the things that it would be very, very difficult to do are things that are either risky or just incorrect. A lot of large-scale metaprogramming is much easier in a dynamically-typed language, due the more natural encoding of reflection, without needing to instantiate higher-order types.
However, to answer your question, I don't think there are any ways in which dynamic typing provides functionality that would be infeasible to do in a reasonable statically typed language.
IMHO, dynamic typing is "Meh" in the best case and leads to more errors in the worst case, when it comes to values. In other words, I don't find any benefits, with respect to values.
The real value comes with the metaprogramming potential offered by dynamically typed languages. Frameworks like Grails would not be possible without. An example of what grails does is: If you have a domain class, add a variable to it, then the frameworks automatically puts the method "findByYourVar" on the domain class for you, available at runtime. So all of the common persistence methods that are tedious to write in Java(or whatever) are given to you by the framework.
It's called "expressiveness". As simple as it seems, the benefits are reaped every single time it is not necessary to add further complexity to the code just to extend it.
Suppose some hypothetical JavaScript code looks like this:
function somefunction(options) {
// ...
}
someFunction({
a: 1,
b: 2,
})
And then a new key, e.g. c
becomes necessary for a new use case. With dynamic languages, such as JavaScript, all that needs to be done is something along the lines of:
function somefunction(options) {
// ...
doSomethingWith(options.c) // use the new key-value pair
}
someFunction({
a: 1,
b: 2,
c: 3, // add the new key-value pair
})
In a non-dynamic language, it would be necessary to also do further refactoring, e.g. changing an intermediate interface / protocol / struct to achieve the same results. So the benefit is in keeping the code lean, less verbose and straight to the point.
© 2022 - 2024 — McMap. All rights reserved.