4 ms·
Yep. Being able to work fast and dirty is a huge boon when testing ideas and figuring out the initial design, and it is deeply annoying that so many typed langu
by hhas01 7y ago
Yep. Being able to work fast and dirty is a huge boon when testing ideas and figuring out the initial design, and it is deeply annoying that so many typed languages refuse to permit this. The faster you can write code, the faster you can throw it away again; and arriving at good code almost invariably requires† writing lots of bad code first. If writing bad code is made expensive (another example of Premature Optimization), authors may be reluctant to try different ideas or throw anything away.
Ideally, you want a language that starts out completely untyped, efficient for that initial “sketching in code” phase. Then, as your program takes shape, it can start running type inference with warnings only, to flag obvious bug/coverage issues without being overly nitpicky. Then finally, as you refine your implementation and type-annotate your public APIs (which does double-duty in documenting them too), it can be switched to reporting type issues as errors.
Unfortunately, a lot of typed languages behave like martinets, and absolutely refuse to permit any such flexibility, dragging the entire process of development down their level of pedantry and generally making early development an almighty ballache. Conversely, untyped languages provide sod all assistance when tightening up implementation correctness and sharpening performance during late-stage development; it’s pure pants-down programming right to the bitter end.
Mind you, I think this says a lot more about programmers (particularly ones who make programming languages) than it does about languages themselves.
--
† (Unless, like, you’re Donald Knuth.)
- brabel 7y agoIf you think it helps to quickly write some code without types (I don't really agree with that in general, maybe in some specific cases), but you want to, when you're happy with the design, just add the types, there are many languages that support that! On the top of my head: * Dart (just don't give a type and the variable is dynamic) * Groovy (add @CompileStatic or @TypeChecked when you're ready) * Racket (start using typed-racket)
- hhas01 7y agoYeah, it’s not a new idea; but I’d say “some” languages rather than “many”. Dylan’s another case; great pity it didn’t fare better. (I’d much rather be using it than Swift.) Also, none of them are in the mainstream, which creates general challenges to adoption. Fortune favors the entrenched. ... Another thing worth considering IMO is structural rather than nominal typing, which fits more with the “if a value looks right, it is” philosophy that untyped language aficionados enjoy without going for full-on pants-down duck-typing. ML favors this, IIRC (I really must learn it sometime). I find nominal typing can get a bit excessively OCD, demanding so much additional annotation as to obscure the code as much as clarify (“Hi, Swift stdlib!”). I also wouldn’t mind being able to define sets of permitted type mappings in advance, and letting the compiler figure out where in the code to insert (implicit) casts. For instance, if I’m passing a variable typed as integer where a float/string is expected, it really wouldn’t kill it to promote it automatically; most are perfectly happy to promote integer literals where a float is required after all. (And if I do want to know about it, which I usually don’t, I can always turn warnings/errors on.)
- mpweiher 7y ago* Objective-C
- hhas01 7y agoTBH, I think that’s as much accidental as by design. ObjC didn’t do generics until just recently, so the standard collection classes (NSArray, NSDictionary, etc) couldn’t specify element types so had no choice but to leave those APIs typed as `id` (effectively `void`). Also, being a C, you still have to declare* all the types, even when only `id`, which is tedious AF. Also-also being a C (which doesn’t so much have a type system as a loose set of compiler directives for allocating memory on the stack), it’s not as if declaring exact types does much to improve program correctness. You can still stick any old object into an `NSString*` at runtime; it just dumps stack when you try to send it an NSString-specific message is all. Oh, and one more: the ObjC compiler can have trouble recognizing selectors (method calls) when the receiver’s type is `id`. Being a C, obviously you have to import all the headers just to use them at all, but if in searching those headers it finds two method definitions with the same name but different parameters then its superficially Smalltalk facade quickly breaks down. (I’ve run into this, it’s very annoying.)
- shrimp_emoji 7y agoLook at this C++ code: std::vector<Pair<std::string, MyInt>> s; s.push_back(Pair<std::string, MyInt>("a", MyInt(1))); s.push_back(Pair<std::string, MyInt>("b", MyInt(2))); s.push_back(Pair<std::string, MyInt>("c", MyInt(3))); Gross. I'm being punished. Look at this Rust code: let mut s = Vec::new(); s.push(Pair::new("a", 1)); s.push(Pair::new("b", 2)); s.push(Pair::new("c", 3)); Both are statically typed, but one uses inference. It practically feels like Python everywhere except where type declarations matter most to me -- function signatures: fn foo(x: f64, y: f64) -> Point {...} In Python, those aren't very helpful. def foo(x, y): ... :c
- woud420 7y agoYou mean this C++ code? std::vector<std::pair<std::string, int>> s; s.push_back({"a", 1}); s.push_back({"b", 2}); s.push_back({"c", 3}); I mean let's compare apples to apples here.
- shrimp_emoji 7y agoDamn, I forgot about uniform initialization. D: That IS better than Rust since it migrates the type from n container members to just the 1 container. It doesn't seem possible to replicate that in Rust[0]. My Rust evangelism IS hurt by this. But its HP bar is big[1]. 0: https://news.ycombinator.com/item?id=10891892 https://news.ycombinator.com/item?id=10891892 1: https://www.reddit.com/r/rust/comments/bya8k6/programming_with_rust_vs_c_c/eqfcu0s?utm_source=share&utm_medium=web2x https://www.reddit.com/r/rust/comments/bya8k6/programming_wi...
- hhas01 7y ago“Look at this C++ code” YOU BASTARD NOW I’M BLIND! (In practice I’m pretty sure you’d typedef that, as much for maintainability as readability. Do agree though that type inferencing kicks the tar out of manifest types, at least up to the point the type inferencer gets lost.)
- IggleSniggle 7y agoThis is why TypeScript is so popular. JavaScript is very loose, but you can progressively enhance it using TypeScript with stricter and stricter types, many of which can be inferred, and since 3.7 can be derived by runtime assertions, and the strictness of which can be controlled with compiler flags. Additionally, it is fairly typical in js to use functional programming styles, making type inference a breeze / provable / not introducing much boilerplate by adding types.
- neilparikh 7y agoStatically typed languages can, and do permitted “fast and dirty” code. For example, in Haskell: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#deferring-type-errors-to-runtime https://downloads.haskell.org/~ghc/latest/docs/html/users_gu...