7 ms·
Hallelujah, that's always been my position. To the static typing folks: leave my dynamically typed languages alone and go coding with something that really suit
by pmontra 4mo ago
Hallelujah, that's always been my position. To the static typing folks: leave my dynamically typed languages alone and go coding with something that really suit your needs. If the answer is that Python, Ruby, JS, whatever are really much more pleasant to code with, my reply is that they are so precisely because we don't have to type type definitions. Tradeoffs.
- Tade0 4mo agoPersonally I like having my TypeScript cake and eating it. I also truly believe those who design type systems would benefit from taking a look what kind of code people programming in dynamically-typed languages produce.
- anamexis 4mo agoI do too, but I feel like TypeScript stands alone as an unusually effective and pleasant to use bolted-on type system. I've not seen any other approach come close. (My sample size is Python, Ruby and Elixir)
- dnautics 4mo agoyou don't think the elixir type system is effective? I've never seen a bolted-on type system get so much acceptance from the hardcore "you can add types into my dead hands" crowd
- jamesfinlayson 4mo agoI really like PHP's type hints (I think they were the first I used) though it's somewhat limited (can't type hint complex/nested structures last time I checked). Flow for Javascript was okay but Typescript I've found to be much nicer (last used flow years ago but occasionally I'd encounter bugs in Flow). Python's is okay but it feels clunky.
- junon 4mo agoI hate TS's tooling with a burning, deep passion. But its type system is actually pretty incredible for what it is. There are times that I yearn for TS's ability to do duck type reasoning in e.g. Rust (despite that not being feasible) when working with very large data types.
- joha4270 4mo agoCould you point me towards the kind of code people programming in dynamically-typed languages produce? I have lived in statically typed languages almost all of my life, and even when I don't, I pretend I do, just without having a typechecker. So I'm very curious about what I'm missing.
- pmontra 4mo agoAny Rails app. A random one: Redmine. You can look at this file and browse the rest of the repository. https://github.com/redmine/redmine/blob/master/app/controllers/issues_controller.rb https://github.com/redmine/redmine/blob/master/app/controlle...
- throwaway2037 4mo agoDoes Python needs its own TypeScript moment? Many times, while writing Python and deeply frustrated with its weak(er) type system, I have dreamed of something like TypeScript or VB/VBA from the early 2000s (where the type system was surprisingly strict!). However, there are so many Python libraries written in pure C, it is way harder to create a TypeScript equivalent.
- zokier 4mo agoI find it funnysad that python people coined the phrase duck typing and then ended up designing what they have now. Meanwhile TS manages to embody duck typing far better even though coming from very different background.
- cogman10 4mo agoIt's not an all or nothing thing. I think types are particularly valuable for libraries. A library author using copious types really helps the downstream user to know "Ok, this function returns a dict(Foo, Bar)". But after that, it's a matter of preference if you want to add those types to your own code or not. Having the types in the libraries makes it a lot easier for your tools/IDEs to give good suggestions and catch bugs that you might otherwise miss.
- deleted 4mo ago[deleted]
- eloisius 4mo agoYes, where would I be without the _RelationshipBackPopulatesArgument type of sqlalchemy.orm.relationship(argument: _RelationshipArgumentType[Any] | None = None, secondary: _RelationshipSecondaryArgument | None = None, *, uselist: bool | None = None, collection_class: Type[Collection[Any]] | Callable[[], Collection[Any]] | None = None, primaryjoin: _RelationshipJoinConditionArgument | None = None, secondaryjoin: _RelationshipJoinConditionArgument | None = None, back_populates: _RelationshipBackPopulatesArgument | None = None, order_by: _ORMOrderByArgument = False, backref: ORMBackrefArgument | None = None, overlaps: str | None = None, post_update: bool = False, cascade: str = 'save-update, merge', viewonly: bool = False, init: _NoArg | bool = _NoArg.NO_ARG, repr: _NoArg | bool = _NoArg.NO_ARG, default: _NoArg | _T = _NoArg.NO_ARG, default_factory: _NoArg | Callable[[], _T] = _NoArg.NO_ARG, compare: _NoArg | bool = _NoArg.NO_ARG, kw_only: _NoArg | bool = _NoArg.NO_ARG, hash: _NoArg | bool | None = _NoArg.NO_ARG, lazy: _LazyLoadArgumentType = 'select', passive_deletes: Literal['all'] | bool = False, passive_updates: bool = True, active_history: bool = False, enable_typechecks: bool = True, foreign_keys: _ORMColCollectionArgument | None = None, remote_side: _ORMColCollectionArgument | None = None, join_depth: int | None = None, comparator_factory: Type[RelationshipProperty.Comparator[Any]] | None = None, single_parent: bool = False, innerjoin: bool = False, distinct_target_key: bool | None = None, load_on_pending: bool = False, query_class: Type[Query[Any]] | None = None, info: _InfoType | None = None, omit_join: Literal[None, False] = None, sync_backref: bool | None = None, dataclass_metadata: _NoArg | Mapping[Any, Any] | None = _NoArg.NO_ARG, \*kw: Any) → _RelationshipDeclared[Any]*
- shevy-java 4mo agoI am totally with you and I am glad I am not the only one who is totally against those type-addictions leaking into languages that did not need them in the first place. Types in ruby are even worse than in python, because the type systems in use really make ruby turn very ugly. In python it is not as much as a huge problem with regards to syntax, as python has a stricter syntax (e. g. mandating foo.bar() whereas in ruby you can typically omit the (), among other syntax sugar examples). We need to keep the type people out of those languages. Many years ago, on IRC, on #haskell, they said they don't want everyone to use Haskell. Back then I did not understand it. After the type-addicted people emerged out of nowhere, I now begin to understand why Haskell is so snobbish. If you let every idea float, you end up ruining languages - and then those who wanted this, will retire and move away too. Ultimate damage factor caused as outcome here.
- kibwen 4mo ago> To the static typing folks: leave my dynamically typed languages alone Surely you understand that the push to add types to dynamically-typed languages comes from dynamic-typing folks, not from static-typing folks. People who are deeply into static typing have little incentive to consider e.g. Python, whose support for types is relatively weak, loosely-defined, and rarely-enforced compared to the statically-typed languages that exist today.
- kh_hk 4mo agoDoesn't it come from folks that are forced to work with dynamically-typed languages but can't be arsed to understand them?
- nazgul17 4mo agoCan you elaborate?
- kh_hk 4mo agoLet me paraphrase the summary of Eloquent Ruby by Russ Olsen: It’s easy to write correct Ruby code, but to gain the fluency needed to write great Ruby code, you must go beyond syntax and absorb the “Ruby way” of thinking and problem solving
- arjvik 4mo agounderstand? It's really easy to understand that everything is typed as Any/Object/whatever upper bound type your statically-typed language of choice uses. Desiring something better does not mean a lack of understanding of the status quo.
- wolvesechoes 4mo ago> People who are deeply into static typing have little incentive Except when their boss tell them to use Python, or they rely on one of Python libraries that their pet language couldn't provide via its powerful type system.
- Hizonner 4mo agoThe only reason I gave up resisting and started writing any significant code in Python at all was that it got some kind of type system, and thus became less unpleasant to code with. "Pleasant to code with" does not describe getting "AttributeError: 'NoneType' object has no attribute 'foo'" 25 levels deep in a stack trace already obfuscated by dynamic object-oriented nonsense. In production, because it's an unusual case and testing missed it. Not that test cases aren't way more work than types anyway.
- bborud 4mo agoWhat specifically makes them more pleasant? (not a rhetorical question, I want to know what's important to you)
- pmontra 4mo agoHistorically (80s/90s) I started using Perl because I didn't have to write all those malloc and free I spent years writing in C and I could perform string operations much more easily. Then in the mid 90s because of that wonderful CGI.pm Perl module. But the plus of all those languages, and Java, was managed memory. Then in the mid 2000 I learned Rails, and after Rails I learned Ruby. It was like Perl but much easier to understand and again no types to type. Basically what I did in Java but in a fraction of the time and in a fraction of the lines of code. Then a customer asked me to work with Python on a Django app so I learned Python. It looks like a Ruby designed by Klingons but it's OKish. All those bugs I constantly read about, they don't happen very often and are a good tradeoff. Maybe Rails and by Django are shielding me from some bug scenarios.
- bborud 4mo agoI'm not trying to be cute here, but it seems like you have mostly been using scripting languages without static typing. How do you know what it is like to develop in languages with strong typing that produce binaries and that these are unpleasant to use? And dabbling doesn't really count. It takes time to actually learn a language. Much longer than most people are willing to admit.
- thr1owaway9621 4mo agoI started using types with Python in 2018-ish, and I never looked back. I am not that good a programmer, so maybe I am wrong, but I just like being able to tell what the data is that's moving through the system. Typed function signatures, a little shift+k here and there, a warning that I am trying to add int and a string. I don't see what's the harm in having that? At the end of the day, if you don't want to use Python with types -- do not. Unless somebody at work is forcing you, and it feels like putting lipstick on a pig (especially with something like numpy that doesn't easily support types)? Then condolences.
- nonethewiser 4mo agoBut why does your appreciate of type systesm not lead you to something like Typescript? Which is a lot more robust? Or Rust? C#? I guess my speculation is that not every language is good at everything. Sure you might want a better type system with Rust. But for data science?
- thr1owaway9621 4mo agoIn practice, inertia is stopping me. For personal projects, I don't want to learn Rust just so I can do `def add(a: int, b: int) -> int`. For work, I don't really get a choice. I work on brownfield projects. We do use TypeScript, thankfully, for all the browser bits. But nobody is going to stop to refactor a 5 year old production code base from Python to Go just for better types. And -- pepega -- definitely not our codebase that's full of data sciency stuff (numpy/opencv/pandas). So we live with a not-as-good-as-it-could-have-been type system. Compromises, man %) One of the constants in life.
- J_Shelby_J 4mo agoMeh, the amount of effort required to keep up to date with the python ecosystem churn is around the same as learning rust. More so if you are starting from scratch. I quit python after realizing the amount of effort it required to just implement the tooling for a project… when all of that comes included with rust. I have spent maybe an hour in the last year thinking about tooling. Glorious. But yeah, I feel for you. It is an impossible sell when they pay off is impossible to understand without a Time Machine and the only thing known about the cost is that it’s high. But for new people and projects, I can’t imagine starting with python in 2026.
- throwawayffffas 4mo agoTotally agree. I hear a lot of rust makes it hard to write incorrect programs. In my experience it makes it hard to write programs in general.
- deleted 4mo ago[deleted]
- chocrates 4mo agoMy engineers write better code when we enforce types. It's easier to do this then retrain everyone on Go and rewrite all our code. New stuff is often in Go now, but prototyping quickly in Python and then enforcing types when we have to get it ready for production has been working decently
- zelphirkalt 4mo agoSo far I have been avoiding Pydantic as a huge-ass dependency. Instead I am relying on standard type annotations, lots of typed dicts and at service/program boundaries use a jsonschema. I like being able to specify the type of most functions, and get some hints, completions and so on, but I don't want to _have to_ specify every darn type. I also don't want to write a class for everything. Typing dicts is good and usually sufficient. If I wanted to write types for everything, then I could also just write Java or Rust or similar. Unfortunately, I think the kingdom of nouns faction has long invaded the Python world and I see more and more companies demanding Pydantic and similar things. They are dragging us all the way to Java land, it seems.
- strogonoff 4mo agoI tend to get triggered when TypeScript is painted as “JS with type hints”. Coming from Python background, TS and Python with type hints are just so different. With Python I can’t see myself type-annotating everything (or bringing in pydantic anymore for that matter, it is indeed becoming a blight), but with TypeScript my process is turned on its head: I find it natural and easy to start writing with types and have everything fully typed, and I find the fact that it simply won’t compile if anything is off (compared to Python where it’s more like “one of my N type checkers/linters failed, oh well it still runs though) a useful constraint that gives peace of mind.
- throwaway81523 4mo agoI've only used Mypy so maybe I should try some more typecheckers. But I've found Mypy and the annotations it uses don't get in the way much, and they make function signatures usable as documentation, so they're generally a win. But they do let a lot of incorrect code through that would have been caught by typechecking in e.g. Haskell. Thus the idea of using 5 typecheckers (not serious I hope, but I understand the sentiment). I hate JS and have wanted to try Typescript. Is it really JS with type hints? I had thought it was really a different language that compiles to JS, like a less hardcore answer to Purescript. I did like what I saw of Purescript but it never caught on. I feel like Python itself lost its way during the Python 3 transition and now seems declining like Ruby. IDK what to use instead for low-boilerplate projects though. So I still use Python.
- bitwize 4mo agoGod, I hope you never touch a production code base with real users. Strong, static typing has won. It is a must for serious software development. The time and money saved in stupid errors that are caught and avoided before the software even runs is enormous. For internal tools and one-off scripts, sure, go nuts with dynamic stuff, but there is no reason to use a dynamic language for code paths that actually make the business money. If you cannot specify precisely the type of every piece of data you touch and all the operations that can be performed on it, you're not doing software engineering, you're spitballing. And if you want to spitball, LLMs are here and they're great. You can type in a very loose description indeed and get properly typed Rust out the other end.
- OutOfHere 4mo agoIn fairness, Python code with good type annotations is quite maintainable, but well over 90% of Python programmers and managers are unprofessional enough to not care. That's where a statically typed language adds value. It is important to be able to understand the LLM generated code, often also to edit it by hand at times. Go lang has the middle ground whereby it's understandable with moderate effort while being statically typed with any necessary flexibility.
- adrian_b 4mo ago> because we don't have to type type definitions Typing "type definitions" makes you type less, not more, because you type the definition only once, instead of writing many tests wherever values of that type are used. In a decent programming language, one would frequently avoid the need to declare the type of a variable, whenever the type can be deduced from the value used to initialize the variable. Having types in a language has 2 purposes, one is to enable the compiler to check at compile time or at run type that all the subsequent uses of an identifier after its first occurrence are consistent. I cannot imagine which are the benefits for the programmers who are against this rule, i.e. who want to reuse the same identifier for multiple purposes in the same scope (N.B. reusing an identifier in the same scope has nothing to do with data types that are disjoint unions or virtual types, which can be used in any type-enforcing language, or with reusing the same identifier in different scopes). The second purpose of data types is that when the type of a variable or parameter is known at compile-time, that allows more efficient implementations, which are especially important for aggregated data, e.g. arrays. Again, I also do not understand why anyone would want to have inefficient data representations, to avoid the need of data types. There has been some argument that when a language does not use data types you might avoid having to rewrite some library functions if you want to change the parameter types at invocation. However this is a problem that has been better solved for more than a half of century, by providing various means to write generic functions that can be specialized at compile-time or by using disjoint union types or virtual types, for using the same function for many different data types, while still ensuring that other data types, whose use would be erroneous, are rejected. A language without data types saves writing effort only when the programmer omits the run-type checks for correct values, which would be needed to avoid bugs when such checks are not done automatically by the compiler. I agree that several very popular programming languages with type checking, including C and C++, are very poor examples about how a type system should be implemented, because they require the writing of a great amount of superfluous boilerplate that is completely unnecessary (e.g. writing headers with function declarations instead of extracting automatically the interfaces of a package a.k.a. module or writing explicit type names in a lot of places where they can be deduced automatically from the context). Such languages are strawmen in a discussion about whether a language must enforce type checking or not.
- Cpoll 4mo ago> my reply is that they are so precisely because we don't have to type type definitions. My reply is that no, that's not why they're pleasant. If that were the only criteria, we could conclude Python is only as pleasant as Forth.