With the right amount of indirection/abstraction you can implement everything in Assembly.
But you don't. Because you like all the heavy lifting the language does for you.
First Class citizens is what we are actually interested in when we talk about programming language paradigm-choices.
And I explicitly said "escape hatch" meaning language feature. You don't need that much indirection to get routers in Haskell, Rust, Go, C, C++... like I fail to see how implementing routers are a barrier in strict type system languages.
Is it easier in python or js? Sure. can't? hardly.
E: here's some vtable dispatch (unless that doesn't count as "dynamic dispatch") in Rust. Looks really straightforward.
What routers call "dynamic routing" is having the lookup table mutable at runtime.
There can be no equivalent to that in type-safe languages because when you mutate the dispatch table you lose type-safety.
No offense, but your claim sounds like you're confused to me, but maybe I am the one confused. AFAIK I do dynamic dispatch all the time in strongly typed languages. Can you show an example that a strongly typed language can't accomplish?
I believe semantics is getting in our way of communicating.
You don't do dynamic dispatch ___ALL___ the time. You only do it at runtime. And you only do static type safety at compile time. Those are different times.
You can't have both of those features at the __SAME TME__, therefore you can't have both features ALL the time. They are mutually exclusive.
Maybe because you said:
> they prevent you from implementing dynamic dispatch.
and
> Routers. You can't have routers.
Which just isn't true. You can implement dynamic dispatch and you can have routers, but they come at a cost (either of complex code or of giving up compile-time type safety, but in a dynamic language you don't have the latter anyway, so with a static language you can at least choose when you're willing to pay the price).
> First Class citizens is what we are actually interested in when we talk about programming language paradigm-choices.
But that's not what you said in your other comment. You just said you can't have these things, not they're not first class citizens. Besides, some static languages do have first class support for more dynamic features. C++ has tools like std::variant and std::any in its standard library for times you want some more dynamism and are willing to pay the tradeoffs. In Java you have Object. In other static languages, you have other built-in tools.
That is what “trade offs” means.
You can have any feature in any language once you undermine the default constraints of your language. You can implement Scala in Brainfuck. Turing completeness guarantees it!
But this is not the sort of discourse we care about in practice.