5 ms·
Python is also very dynamic, yet libraries rarely allow arguments to be number/string/list/dict/function at the same time. Yet in JavaScript I see this all the
by 323 4y ago
Python is also very dynamic, yet libraries rarely allow arguments to be number/string/list/dict/function at the same time.
Yet in JavaScript I see this all the time - pass a string URL, but we also accept a function which will return a string URL, or maybe an option object - { url: string, strict: boolean }
So I think it's more of a culture thing.
- nicoburns 4y agoLuckily these types are not complex at all to type in Typescript. You just enumerate all the options with a | character separating them.
- 323 4y agoRight, but people compose. They take this union and put it in another object, which also allows multiple types for some field, and then they take that object and put it in another one, and then you have a 10 line type declaration for 3 fields.
- isbvhodnvemrwvn 4y agoWhich is why you can have aliases for those types, each level of abstraction can be nicely wrapped up. It just describes the reality.
- deleted 4y ago[deleted]
- eyelidlessness 4y agoI’m mostly sitting this out, but I’ll interject here because this is wrong. Union types are often used as an XOR (a | b as “either a or b, but not both”), but they’re an inclusive OR (Partial<a> & Partial<b>, as “some parts of a or b, the parts they share guaranteed”) which is almost never what anyone wants when dealing with objects. The pain is that you can’t distinguish them without a narrowing factor, and if you can’t the types are horridly complex.
- colejohnson66 4y agoI mean, that makes sense. If types `A` and `B` both have a function `doStuff`, is it bad to be able to do `x.doStuff()` without narrowing? For example: every object’s prototype chain ends with `Object.prototype`, so all objects have a `toString` function. I shouldn’t be forced to narrow my `number|bigint|string` (for example) just to do `x.toString()`. If I was, we’d get this ugly and bloated mess: function callToString(x: number | bigint | string) { if (typeof x === "number") x.toString(); else if (typeof x === "bigint") x.toString(); else x.toString(); } Regardless, they’re just copying JavaScript’s duck typing feature. It’s not much different than languages like Java and C# that have interfaces. In C#, if my parameter is IClonable, I don’t care what it is, but know there’s a `Clone()` method attached to it.
- nerdponx 4y agoPython libraries kind of used to do this more, but seem to be doing it less now, in part because highly-polymorphic interfaces are a huge ugly pain in the butt with the Python type hinting system.
- int_19h 4y agoWhat's so painful about writing foo: int | str
- nerdponx 4y agoIt gets a lot more complicated than that. One of many, many examples: https://github.com/pandas-dev/pandas-stubs/blob/v1.4.3.220822/pandas-stubs/core/series.pyi#L118-L151 https://github.com/pandas-dev/pandas-stubs/blob/v1.4.3.22082... In general, if someone with experience in a domain is complaining that something is hard, it's safe to assume that the thing is actually at least kind of hard, and that they aren't just a crybaby about indentation and formatting.
- int_19h 4y agoI don't see what's complicated about this example. It adds overloads, but those aren't hard, either.
- nerdponx 4y agoFair, it's not "hard". But I stand by my assertion that it's a huge ugly pain in the butt. That doesn't mean it's not worth doing, but that doesn't make it less huge, ugly, or painful. I also assert that if NDFrame.loc were less polymorphic (e.g. if you had a separate accessor like NDFrame.mask for boolean subsetting) it would be easier to use, easier to reason about, easier to teach, easier to document, and easier to write type hints for. The worst situation is when you want to have multiple return types depending on the argument values, like Pandas' inplace=True. Putting aside the problem of dependent types, even supporting only literal True and False requires you to write out every single overload twice, creating a literal combinatorial explosion of overloads. And that's also ignoring the whole world of parametric polymorphism required for higher-order functions, factory functions etc. Maybe the situation is no better in something like C++, but I don't know enough C++ to have an opinion on it.