What the OP takes to the extreme is a property of weak typing, not dynamic typing.
These properties are separate issues. A language is either statically typed or dynamically typed, and it is also either strongly typed or weakly typed.
In a statically typed language, types are attached to variables. In a dynamically typed language, types are attached to values. Do note that many languages don't fit 100% into either category. (Note that the blog post you linked to calls types attached to values classes, but that distinction often isn't made so clearly.)
A weakly typed language performs implicit type conversions as it deems necessary, while a strongly typed language does no implicit type conversions. Most languages don't fit 100% into either category. Usually languages that are considered to be strongly typed still allow you to add integers to floating point numbers, for example.
It is possible for a dynamically typed language to be so strongly typed that it won't do any implicit type conversion, ever. Such a language would not allow you to, say, add an integer and a floating point number without explicitly converting one to the other.
It is also possible for a statically typed language to be so weakly typed that it implicitly converts types everywhere. Such a language might do the exact same things the OP uses, like converting a function to a string of its source code when adding it to a string.
Ah, this was extremely well explained, thank you; I've encountered the strong / static (and weak / dynamic) dichotomy before but I didn't grok the difference until now.
> In a statically typed language, types are attached to variables.
More precisely, expressions may be typed. Of course, free variables are one particular of expression.
> In a dynamically typed language, types are attached to values.
More precisely, tags are attached to objects. An object is a “physical” entity that exists in space (computer memory) and time (from its construction to its destruction or garbage collection). A value is an abstract and atemporal entity that only exists in the language's semantics.
> Such a language would not allow you to, say, add an integer and a floating point number without explicitly converting one to the other.
But it does allow you to add integers and floating points! The result just happens to be an exception, which is a very well defined operation in the semantics of most high-level languages.
In a dynamic language, you have to wait until runtime to decide whether an operation is valid or not. Only then can you check an object's tag to see if it proclaims the right type. If it doesn't, non-local exit (of which the exception is the most popular form), is still the best you can do. So, cum grano salis, throwing an exception is a dynamic language's way of disallowing invalid operations.
Any memory-safe language? Say, Python. `[] / []` is a perfectly valid operation: its result is a raised exception misleadingly called `TypeError`. OTOH, in most typed languages, this is a genuinely invalid operation, and it can't happen at all.
These properties are separate issues. A language is either statically typed or dynamically typed, and it is also either strongly typed or weakly typed.
In a statically typed language, types are attached to variables. In a dynamically typed language, types are attached to values. Do note that many languages don't fit 100% into either category. (Note that the blog post you linked to calls types attached to values classes, but that distinction often isn't made so clearly.)
A weakly typed language performs implicit type conversions as it deems necessary, while a strongly typed language does no implicit type conversions. Most languages don't fit 100% into either category. Usually languages that are considered to be strongly typed still allow you to add integers to floating point numbers, for example.
It is possible for a dynamically typed language to be so strongly typed that it won't do any implicit type conversion, ever. Such a language would not allow you to, say, add an integer and a floating point number without explicitly converting one to the other.
It is also possible for a statically typed language to be so weakly typed that it implicitly converts types everywhere. Such a language might do the exact same things the OP uses, like converting a function to a string of its source code when adding it to a string.