6 ms·
I often see people say static typing slows them down and I'd really like to know why that is because for me it's the exact opposite, I really don't like not kno
by byhemechi 3y ago
I often see people say static typing slows them down and I'd really like to know why that is because for me it's the exact opposite, I really don't like not knowing what format data is in. I'd much rather have to write slightly more verbose code and have a vast number of possible errors caught at compile time instead of having things go wrong in production when someone inputs something a bit weird with nothing so much as an error.
- mib32 3y agoYeah but it doesn’t matter - if someone inputs something weird you will anyhow fail with TypeError
- weatherlight 3y agobecause of unification/pattern-matching you have a pretty good idea, just looking at function name + args what the shape of the data is going to be.
- artdigital 3y agoAs someone who worked with Elixir for the past couple years, and maintains multiple libraries in Elixir - nah not really. Static typing is the thing I'm missing with Elixir. No matter how much pattern matching you do, and how many typespecs you add to get a better understanding of what's behind a variable, you'll still run into issues at runtime frequently that could have been avoided if it was statically typed. Dialyzer is great but typespecs and pattern matching only get you so far. You'll always run into situations where the shape of data is not clear, and you have to open a REPL to do an IO.inspect somewhere
- h0l0cube 3y ago> You'll always run into situations where the shape of data is not clear If you're using typespecs, then I think the deficiency is with tooling. I think the language servers (like ElixirLS) were quite buggy for a while, but it's getting better at code completion and inspection. But if the type has no spec then you're in the same situation as any gradually typed language.
- 59nadir 3y agoIf by "defiency is with tooling" you mean that `dialyzer` is bad, then yes. The current type checking facilities that it provides are too lax and also sometimes demonstrably actually incorrect even in the face of the simplest examples.
- h0l0cube 3y ago> incorrect even in the face of the simplest examples I haven't found this in my experience. Most issues arise from a lack of typespeccing. If one were to rely on type inference, then, yes, it's not going to catch much. Specifying types is a requirement of a strictly-typed language, so to make a claim of deficiency with Dialyzer's type checking, you'd be comparing code that's fully specced with that of a strictly typed language. The unavoidable problem is when using libraries that aren't properly typespecced, but that the same story as any gradually typed language (e.g., Typescript). The only solution here is to make a PR or a feature request to the product owners.
- 59nadir 3y agoI've used dialyzer since 2015, it's not a question of "holding it wrong". I have an example of this that I literally demonstrated live in a talk online. It's very likely you haven't used dialyzer enough if you think it's actually correct 100% of the time even with type specs. Dialyzer is an exceedingly poor implementation of static type checking and not sufficient with any level of use.
- h0l0cube 3y agoI thought Dialyzer never raised false positives at the expense of false negatives, though perhaps your example is a false negative? I’ve only used it in the last 4 years. Is it possible the bugs have been fixed by now? Or is this just an inherent to this kind of type checking?
- 59nadir 3y ago
- kimi 3y agoI miss static typing for two separate and quite opposite cases: * trivial errors, that still cause a crash and waste my time ("foo(:yo, 7)" but was "foo(7, :yo)") - sometimes spotted by Dyalizer * complex nested structures. In Java I never have surprises as to what foo.bar.baz is and I can use autocomplete reliably. Expressing the same invariant in Elixir is something less straightforward
- hosh 3y agoThe fact that you _can_ open a REPL in production and inspect the data at runtime is huge. Although few people use hotloading in code before, shapes of data can change from deployment to deployment.
- weatherlight 3y agoThat’s okay. I’d rather do that once in a while to keep all of elixir’s dynamic traits. The fact that you can open a REPL, and open one in prod, do language introspection, inspect data, query DBs with ecto, do hot code swapping is amazing. Until we have something like Set Theoretical Types, I think this is the best of both worlds.
- ryanjshaw 3y agoI'm building a static analyzer for Solidity in F# and the data shape of Solidity AST nodes overlaps frequently enough that explicitly specifying types is necessary just to get things to compile. I can't imagine building something like this in a dynamically typed language. The way I see it, static typing is like writing inline unit tests to save yourself many, many headaches later.
- weatherlight 3y agotypes aren't a substitute for tests. let add : int -> int -> int = fun a b -> Random.self_init (); Random.int 100
- deleted 3y ago[deleted]
- whalesalad 3y agostatic typing is a means to an end. if you can achieve the same end without static typing, good right? that is the goal of spec. the creator of the language has a fantastic talk on this https://youtu.be/giYbq4HmfGA?si=LgSHZupSuR-kMXmj https://youtu.be/giYbq4HmfGA?si=LgSHZupSuR-kMXmj
- magicalhippo 3y agoFor me, a huge part of it is that I find static typing to make the code a lot more self-documenting. I can easily see what is passes or returned, and if I'm unsure about the details of the type the answer is a click away, or a short web search away at worst. Significantly reduces my mental load, allowing me to be vastly more productive.
- passion__desire 3y agoDoes the code really need to be verbose? Scala does a pretty good job. Infer once at first declaration and enforce throughout.
- jb1991 3y agoAs does swift.
- rishav_sharan 3y agoI just moved from typescript to javascript and for me it was just that I own the database, i own the api surfaces and as such I don't need to enforce any kind of type checking as the api schemas are sufficient for my case. I would definitely use type safety if I had a lot of external data sources. or if there are lots of people working with me. Otherwise, I am beginning to go back to dynamic languages at least for web dev.
- MrJohz 3y agoThat's an interesting decision, because it's the reverse of one of the big complaints about Typescript: that it only works up to the API boundary, and doesn't include external data sources (unless you use libraries like Zod to combine runtime and static type checking). For me, Typescript is more useful, the more of the codebase I "own", because it means I can be more confident that all the types reflect the true types of the runtime data, which means I can change things more confidently and quickly. Do you find that you're refactoring and changing things less with dynamic languages? For me, I think that's the number one magic feature that I miss when I use languages without explicit type systems.
- hosh 3y agoI'm currently working on a data engineering team, unborking some things on a team where all the original developers of the codebase had left. Up until then, I wrote Ruby for over 10 years, and Elixir for 3. I didn't have an opinion about JS or Typescript before this project. Typescript does not solve the fundamental problems of JS. I'm not convinced it really solved the issues related to ingesting data from many different data sources. The data quality issues were still there. If I were rewriting the whole thing, I'd rewrite it with Elixir (of course), if only to have a sane way of handling errors.
- aerhardt 3y ago> I'm not convinced it really solved the issues related to ingesting data from many different data sources That sounds like external data validation and I don't think a type system can really solve that. Even if you're using C#, Java, Scala, or what-have-you, you're going to have that issue. If that's what you expected from TypeScript, then yea, I can see how you'd be sorely disappointed... Like many others, the advantage of type systems for me is in how they reduce cognitive load thanks to their explicitness, even in solo projects. I literally have a hard time remembering the types returned by a function I wrote a mere few hours ago... I have come to believe that there are two broad types of dynamic typing programmers: those who don't know better, and those who have a superior working memory, or cognitive ability, such that types hinder them rather than help them.
- mijamo 3y agoI think it vastly depends what you're writing. Any kind of function that does not have a fixed input and output gets a lot more complex with static types. And by extension any code that depends on that also gets more complex. I tried at some point to use Rust for an API but then I depended on making calls to a very complex API. In JavaScript I would have just gotten back a complex object where I can then pick whatever I want progressively through object access methods. In Rust I ended up with more than 500 lines of type definition for the API and it still wasn't enough so I gave up. It is a bit extreme but when you work with an API from an ERP for instance you can get very very complex and extensive types that are not in your control and not very well specified. Another good example is how complex all ORM internal code get once they try to add static typing. The typing in the ORMs code feels like black magic because they would really really need types as code but don't have it so have to rely on a bunch of crazy generic combinators.
- olivermuty 3y agoElixir dev here, just to put the context in place first hehe. Couldn’t that thing be typed as the web format? A nested set of string props with either string or number types in the leaves. Then use those types to traverse and pull into «real» types? I like to put structured data into structs in elixir too and the above is essentially what I would do in Elixir. I don’t know rust well enough to see if I am missing some nuance
- miroljub 3y agoYou can do that in every language, even in Java 1.0, by just using a hash maps of objects, and cast those objects to whatever you like at runtime before accessing them. But then, you are basically throwing out your static type checks and just using it as a dynamic language, but with much more verbosity, cruft and additional ways to should yourself in the foot.
- josephg 3y agoYep. It’s awkward. The language fights you every step of the way and it becomes hard to read and write your code. x.foo = 6 becomes x.set(String(“foo”), Num(6));. When you read that value back you’ll need to unwrap the type you expect before you can do anything with it. It would be utterly miserable. You’d be much better off just using Python, JavaScript or Ruby. You also lose all of the performance benefits typing brings, and gain nothing in return. In JavaScript land, V8 moves heaven and earth to guess what your types are and optimistically compile your code behind the scenes assuming its type annotations are correct. Then it dynamically deoptimises and reoptimises at runtime with that new information, while your program runs. As well as being ugly, the equivalent “dynamically typed” rust program would have none of V8’s smarts. It would run dog slow compared to normal rust and still way slower than the (much cleaner) JavaScript equivalent. Like wood, programming languages all have a grain. If you program in harmony with the language’s design, everything will seem easy. Compiler errors make sense. The standard library will seem useful and well designed. Program against the language’s design and you’ll hate every minute of it.
- jwells89 3y agoIn my experience, static typing takes a different way of thinking that can take a while to get the hang of, and during that adjustment period a lot of people are going to significantly slower. I definitely felt it coming into Swift, being used to Objective-C and to a lesser extent Ruby. Having grown accustomed to static typing, not encountering errors until runtime, or worse having errors manifest as type-related misbehavior and potentially not be immediately apparent is much more frustrating than it used to be.
- realusername 3y agoElixir is a bit in the middle, with the massive amount of very specific pattern matching for each function and the fact that modules are just plain collection of functions and not objects I would say it's the most static of dynamic languages. They are working on typing it now from the blog posts I've seen and they will probably be successful because the language is well suited for that in my opinion
- csan_gonzo 3y agoI've been using Elixir for over a year now and the only thing that's missing for me is a static type system, really looking forward to this: https://elixir-lang.org/blog/2023/09/20/strong-arrows-gradual-typing/ https://elixir-lang.org/blog/2023/09/20/strong-arrows-gradua... Also keeping an eye on Gleam: https://gleam.run/ https://gleam.run/ .
- threatofrain 3y agoI think static typing (without escape hatches) slow you down when you're a library or framework author, or you're doing something high performance. The reason being that there are many trivial and non-trivial propositions which the field has ironed over but the core language/compiler team hasn't caught up yet. I've seen a lot of authors do crazy type things to get around the type system (like typing out recursion to the n-th level by hand), and I think many open source projects are slowed down by the lack of a type wizard on their team.
- curtisblaine 3y agoIn my experience, static typing greatly slows you down when you're prototyping, at least for a short time, then it moderately speeds you up when you're productionizing and maintaining.
- wofo 3y agoLack of proper types is what killed the joy of programming in Elixir for me (I lasted 6 months, hoping I would somehow adapt, but the experience was so miserable that I decided to move on). I simply can't understand how anyone can be productive in a big codebase without the rigor of static typing, but those people exist, so I guess there must be something about our brains that divides us in the dynamic vs static typing camps.
- josephg 3y agoI’ve swapped back and forth between static and dynamic types a few times in my career. Java and C/C++ to JavaScript (and coffeescript) to typescript and rust. The entire time (30 years at this point) I’ve felt like whatever I was doing at the time was obviously the one true way to program. I feel that now - that what I’ve been doing lately (static typing) is clearly superior. Even for throwaway JavaScript based projects at the moment the first thing I do is install typescript. I’m spitballing on the reason - I don’t know why it’s like this. But maybe it’s because static typing encourages you to write & plan your types first. When you know the data types, all the functions kind of flow around your types and everything feels like it obviously flows from that. With dynamic typing, it’s the reverse. I find myself writing my functions first (top down or bottom up) and then backfilling what arguments and data everything needs to pass around. I run my code a lot more as I develop it to stop bugs creeping in. And because I can run my code at any time. There’s no type checker stopping me from trying things out.
- IggleSniggle 3y agoI've recently found a great middle ground for this, using esbuild to drive code as I'm writing it, while my IDE may meanwhile be complaining that all my types are broken. Getting comfortable having "broken" types while something is still in development is a nice middle ground, helping you come back to the hot spots whenever you're ready, and acting as a forcing function prior to commit or push.
- ra 3y ago> I guess there must be something about our brains that divides us in the dynamic vs static typing camps. I've wondered if that's a thing. It seems to be.
- jddj 3y agoBetter type inference is faster than more ceremony, but more ceremony is faster than nothing at all, in moderately complex projects.
- peoplefromibiza 3y ago> I really don't like not knowing what format data is in. Which is orthogonal to what the type is The shape of the data is much simpler to handle in Elixir than in, to name one, Java. > a vast number of possible errors caught at compile time if it's a vast number, usually it's because either: - you're not familiar with the code base (and you'll make a vast number of other kinds of errors) - you're making a huge refactory and you're used to rely on a compile-driven workflow, but there are so many alternative ways to handle them > things go wrong in production the usual wisdom applies here: static typing does not replace input validation, be it user provided data or function parameters
- solidninja 3y agoStatic typing can replace input validation though - if you make illegal states unrepresentable. That way you bake validation into your types e.g. using refined types: https://blog.rockthejvm.com/refined-types/ https://blog.rockthejvm.com/refined-types/ in Scala
- Dowwie 3y agoThe lack of types is hard to defend. Yet, the failed pattern match triggered at runtime becomes immediately obvious from the stack trace. You fix the pattern and move on. The cost of this mild inconvenience is still far less than the cost of satisfying types. This aside, I want typed elixir.
- bradrn 3y ago> This aside, I want typed elixir. It’s happening: https://elixir-lang.org/blog/2023/06/22/type-system-updates-research-dev/ https://elixir-lang.org/blog/2023/06/22/type-system-updates-...
- Dowwie 3y agoThey're taking baby steps with the roll-out. It's not going mainstream any time soon.
- epiccoleman 3y agoI love elixir, but I would also love it more with a sort of laissez-faire type system akin to TS. Glad to see they're working in that direction. One of the best features of type systems is they make editor completions and navigation work better. Elixir's LS is pretty good, but editor support just isn't nearly as good as what you can have in a good (read: Jetbrains) IDE with a strongly typed lang like C# or Java.
- andrewstuart 3y agoIt slowed me down until I had enough experience then it sped me up.
- gampleman 3y agoAn important thing to realise is that "static typing" isn't just one thing. The details matter. For instance, type inference is a huge deal in making static typing not painful. Local type inference is something that pretty much all modern languages have adopted, since it makes writing out function bodies much less painful. But I think a lot of static typings bad rep comes from older languages that required lengthy annotations everywhere. Then you of course have global inference, where you can write code as tersely as in a dynamic language, but still benefit from type checking and add annotations later as a form of documentation for readers. It also changes the way you code. The best experiences from static typing come IMO from doing type-driven development, where you sketch out your problem first at the type level, then fill out the implementation at the value level. In dynamic languages, you can't program like that. So if you use the same mindset you will find the language limiting.
- hahn-kev 3y agoI actually think it's pretty similar to different automated testing camps. Some people say they build faster with TDD, and others say it slows them down.
- jacquesm 3y agoUsually it is because people have a short term view of software, but in practice software lives for much longer than most people can imagine at the time of writing and that initial burst of productivity when working on a new system is even more present in a type-free and test-free environment. But once that honeymoon phase is over you usually realize that types and tests were invented for a reason and beyond a certain level of complexity they are absolute must-haves if you want to have high confidence it all works as advertised and to be able to effectively refactor your code.
- mstipetic 3y agoEvery time an elixir discussion starts a vocal segment of people just starts complaining about types. Ok we get it you like types, can you leave the rest of us in peace
- sph 3y agoIt's just a hype phase. Types are cool, but in the past few years they seem to be the panacea for all problems, by inexperienced engineers that have got their first taste of Rust and Typescript. As if writing in Typescript would produce less buggy, more stable or more maintainable applications than using Elixir. I'll say types are cool again before I get routed by angry static typing zealots.
- kelipso 3y agoFrankly, we really need to instill the "types are cool" concept into inexperienced engineers. That insanely long phase in software engineering where people said dynamic types are cool was a huge mistake and ruined a lot of newbie minds.
- sph 3y ago"Think of the chil^H^H^H^Hinexperienced engineers! We must save them from PHP and Python!" Enough pearl clutching. No one's mind was "ruined".
- kaashif 3y ago> As if writing in Typescript would produce less buggy, more stable or more maintainable applications than using Elixir. I have news for you. A lot of people, including me, do know that catching an entire class of bugs at compile time makes your code less buggy. The trade-off as usually stated is that more things are possible with more dynamic code, and statically typed code is slower to develop with. Elixir has much more interesting features that have nothing to do with the types/no types discussion and I 100% agree it would be more interesting to discuss those instead.
- 3y ago
- dartos 3y agoStatic vs dynamic types are whatever. Weak typing is what causes all sorts of issues. With dynamic strong types, you can still have a tool like dialyzer figure out potential type issues before shipping, but weak typing means anything goes.
- prophesi 3y agoDoes José need to write up an elixir-lang.org blog post every other week on the status of their type system project for HN's collective memory to know it's in the works?
- keep_reading 3y agoWhile you're waiting for official support in the language, just properly document functions with @spec and change them to @spec! after adding TypeCheck to your project and viola, you get powerful type checking at runtime with almost no performance impact. The error messages it produces are so beautiful. https://github.com/Qqwy/elixir-type_check https://github.com/Qqwy/elixir-type_check
- conradfr 3y agoIn a functional language where you're writing a lot of functions it's a bore and feel very dated. Especially as you have to write the function name so copy/paste from other @spec doesn't really at least speed it up. It is what it is I guess.
- keep_reading 3y agowell, you can avoid this if you try to limit the number of public functions so you don't have to do this as often. make as many defp functions as possible, really.
- satvikpendem 3y ago> and viola Nice to see you are a musical aficionado too. More seriously, how does this compare to other type checking alternatives for Elixir/BEAM were I to start a new project, including Gleam and Witchcraft (which at least seems to be unmaintained for now)?
- pleoxy 3y agoIt does slow some of us down. It's not really about terseness. I can write code that works on all primitives that might be sent down pretty easily. That code, sometimes is longer than limiting the inputs by types would be. I can also write code such that it only runs if the structure of the data is as required for that code to run, allowing for nulls or missing nested objects. These two patterns allow you to write most code, type free, that gracefully handles anything you throw at it while always doing the right thing. Making changes to such a system is easy and friction free. Not many type advocates speak of the downsides of type systems, always pitching the net win and ignoring the actual cons. When you refactor, make a change, or try to add new functionality, and end up fighting the type checker. That's friction to change you are experiencing and that experience is optional. I get that having discipline in code patterns and the required robustness is a difficult ask at some organizations and some devs. In that circumstance it's better to have a minder in a type system that enforces base the conventions for everyone.
- Munksgaard 3y ago> When you refactor, make a change, or try to add new functionality, and end up fighting the type checker. That's friction to change you are experiencing and that experience is optional. I'm not sure exactly what you're saying. If your language is strongly typed, you'll get type errors no matter what. The only difference is whether the type errors happen at compile time or run time. Let's take a hypothetical example: Let's say I have a programming language called Foo. There are two ways to run programs written in Foo, using the interpreters A and B. A and B are identical, except for that fact that on startup, A will check that the given program is well-typed (static type checking), while B defers such checks to runtime (dynamic type checking). Given a well-typed program X, I can run X with A or B without ever encountering a type error. Now, I make some changes, like you suggest, and I attempt to run it again. If the resulting code is not well-typed, I will immediately know when trying to run it with A, but with B I have to be lucky enough to hit the specific case that isn't well-typed. If I understand you correctly, you're saying that you can easily make changes in a dynamic language without _ever_ causing run-time type errors. If that's the case, you would have _exactly_ the same experience whether you ran your code using A or B.
- 3y ago
- liampulles 3y agoI think loose typing helps to prototype faster, while static typing helps you write the correct/safe version faster. But part of doing the correct version is clarifying spec, and prototyping can help with that - so it is a weakly held opinion.
- mrcwinn 3y agoI could not disagree with this more. You are aided in prototyping by forming an early opinion on your data models. I would argue there's nothing more important in conceiving of something new than understanding the shape and relationships in your data. Typing does that. And nothing slows a developer down more than accruing technical debt as they build. It's like having tar stuck to your shoes. You will work the fastest when you have nothing to pay back because your mental model of the application is aligned with the intention of your program. (That said, I don't think you necessarily need a strong static type system to achieve these aims.)
- EarthLaunch 3y agoMaybe it depends on what you're prototyping. In web dev I see what you mean. But in game dev I'm often prototyping something to see if it works at all, or to check its performance. Ignoring types is faster when spending 1-2 hours/days quickly hammering out something that just barely works. On version 2 or 3, add typings. Maybe it also depends on the timeframe of the prototyping project. After a few days it can become tech debt. (Though I still suspect there are some long term advantages to untyped.)
- camgunz 3y agoIt's really hard to prototype w/ static typing. It's not really about mechanics; annotating parameters or return types, that stuff's easy. The problem is that in prototyping you're changing a lot of stuff because you don't necessarily know what the structure or types will look like, and every time you change something or rethink your taxonomy you have tons of type updates to do.
- deleted 3y ago[deleted]