9 ms·
Every programming paradigm is a good idea if the respective trade-offs are acceptable to you. For example, one good reason why strong static types are a bad id
by ukj 5y ago
Every programming paradigm is a good idea if the respective trade-offs are acceptable to you.
For example, one good reason why strong static types are a bad idea... they prevent you from implementing dynamic dispatch.
Routers. You can't have routers.
- kortex 5y agoSure you can. You just need the right amount of indirection and abstraction. I think almost every language has some escape hatch which lets you implement dynamic dispatch.
- ukj 5y agoThis is a trivial and obvious implication of Turing completeness. Why do you even bother making the point? 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. https://en.wikipedia.org/wiki/First-class_citizen https://en.wikipedia.org/wiki/First-class_citizen
- kortex 5y agoI mean, GP said "you can't have routers" and maybe I'm being dense by interpreting that as "never or almost never," but even with a generous "too hard to be practical," I still don't think it's correct. 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. https://doc.rust-lang.org/1.8.0/book/trait-objects.html https://doc.rust-lang.org/1.8.0/book/trait-objects.html
- ukj 5y agoWhat C++, Haskell, Rust, Go etc. call "dynamic dispatch" is what a router calls "static routing". The defining characteristic is that the lookup table is pre-determined and immutable at runtime. 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.
- kortex 5y ago> 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. That's exactly what I mean by escape hatches. Rust has unsafe. You can write a WTF FastInverseSqrt in Rust. You shouldn't 99% of the time. But you can. Rust also has Box, Rc, Arc, and other tools. I'm not fluent enough in rust to know how to, but I'm quite confident and will eat my hat if you can't accomplish what is effectively a mutable vtable dispatch in Rust. But also...why? Yeeting a function call into the void without any type knowledge seems way more bug-prone than interface/trait-based dispatch, to what benefit? Save developer time? I've spent countless dev-days of my life I won't get back debugging exactly this kind of dynamic-dispatched, json-dsl, frankly loosey-goosey untyped bullshit. There's so many better ways.
- ukj 5y agoWell isn't that's precisely my point! "unsafe" turns off your compiler's guard rails. You CAN accomplish mutable vtable dispatch and in doing so you will undermine Rust's type-safety! Yeeting a function call into the void is what async network clients usually do. You will soon get a result. Maybe.
- dang 5y agoWould you please stop? Regardless of how right you are or feel you are, we don't want long, tedious flamewars like this and you did more than anyone else to prolong it. Dozens of comments is beyond excessive. https://news.ycombinator.com/newsguidelines.html https://news.ycombinator.com/newsguidelines.html
- dkersten 5y ago> Why do you even bother making the point? 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.
- ukj 5y agoEverything comes at a cost of something in computation! 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. https://en.wikipedia.org/wiki/Brainfuck https://en.wikipedia.org/wiki/Brainfuck
- dkersten 5y agoYes, and? How is that relevant here? You said "you can't", kortex said "you can" and then you moved the goal posts to "you can because of turing completeness, but its bad, Why do you even bother making the point?" to which I replied "because its a valid response to you're `you can't`" now you moved them again to "everything comes at a cost" (which... I also said?). Of course everything comes at a cost and yes, that's what "trade off" means. Dynamic languages come at a cost too (type checking is deferred to run time). So, this time, let me ask you: Why do you even bother making the point?
- ukj 5y ago
- mixedCase 5y agoDid you mean something other than "dynamic dispatch", or what do you mean by "first class support"? 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?
- ukj 5y ago>I do dynamic dispatch all the time in strongly typed languages. 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.
- Jtsummers 5y agoDynamic dispatch is literally a runtime feature of a language. That's why it's called "dynamic". GP can absolutely use dynamic dispatch "all the time" in the sense that they use it regularly in their program, perhaps in every or nearly every program they write. Your statement is verging on the nonsensical, like saying to someone "You don't use integers all the time, sometimes you use strings, they're different things." Well, duh? EDIT: Also, it's discouraged on this site in general to use all caps for emphasis. *phrase* produces an italicized/emphasized form with phrase.
- ukj 5y agoI am using a perfectly sensible notion of "dynamic" (e.g NOT static) when I am talking about "dynamic dispatch". Registering pointers to new implementations at runtime (adding entries to the dispatch table) Unregistering pointers to old implementations at runtime (removing entries from the dispatch table). If your dispatch table is immutable (e.g static!), there's nothing dynamic about your dispatch!
- mixedCase 5y ago
- ImprobableTruth 5y agoHuh? Could you give a specific example? Because e.g. C++ and Rust definitely have dynamic dispatch through their vtable mechanisms.
- ukj 5y agoDo you understand the difference between compile time and runtime? Neither C++ nor Rust give you static type safety AND dynamic dispatch because all of the safety checks for C++ and Rust happen at compile time. Not runtime.
- detaro 5y ago> Neither C++ nor Rust have dynamic dispatch You appear to be using some other definition of dynamic dispatch than the rest of the software industry...
- ukj 5y agoYou appear to be conflating compilers with runtimes. Dynamic dispatch happens at runtime. C++ and Rust are compile-time tools, not runtimes.
- BoiledCabbage 5y agoYou are wrong. C++ supports dynamic dispatch. Please read about it on Wikipedia https://en.m.wikipedia.org/wiki/Dynamic_dispatch https://en.m.wikipedia.org/wiki/Dynamic_dispatch And for the future to not litter HN with comments like these, next time 10 different people in thread are all explaining to you why you're mistaken, take a moment to try to listen and think through what they're saying instead of just digging deeper. Having an open mind to learning something new, not just arguing a point is a great approach to life.
- ukj 5y agoYou are wrong about me being wrong. C++ is just a compiler. It outputs a binary for a target platform. The compiler does nothing for you at runtime - certainly not "type safety". Sometimes the 10 people on HN are wrong. This is one of those times.
- justinpombrio 5y agoAre you sure you know what dynamic dispatch is? Java has dynamic dispatch, and it is a statically typed language. In Java, it's often called "runtime polymorphism". https://www.geeksforgeeks.org/dynamic-method-dispatch-runtime-polymorphism-java/ https://www.geeksforgeeks.org/dynamic-method-dispatch-runtim... And using it doesn't give up any of Java's type safety guarantees. The arguments and return type of the method you call (which will be invoked with dynamic dispatch) are type checked.
- ukj 5y agoAre you sure you know when type-checking and when dynamic dispatching happens? Compile time is not runtime. The Java compiler is not the JVM. The compiler does type checking. The JVM does the dynamic dispatching. Neither does both.
- justinpombrio 5y agoAll those statements are correct. The people downvoting you know that too. I don't think anyone has figured out what point you're trying to make, though. Could you spell it out in more detail? Consider addition. The compiler does type checking, and the JVM actually adds the numbers. Nonetheless, the addition is type checked, and does not represent a weakness of static type checking. How is dynamic dispatch different than this?
- ukj 5y agoThe point is trivial. You can’t have both static type safety AND dynamic dispatch at the same time and in the same context about the same data. Choose one. Give up the other. Make a conscious trade off. The language that you are using is making such trade offs for you - they are implicit in the language design. Best you know what they are because they are meaningful in principle and in practice.
- justinpombrio 5y agoJava has both static type safety AND dynamic dispatch at the same time and in the same context about the same data.