Live data from Hacker News

Tests aren’t enough: Case study after adding type hints to urllib3

sethmlarson.dev

131–140 of 205 posts

Re: Tests aren’t enough: Case study after adding type hints to urllib3

#131
post #97

Earlier quoted context omitted.

Hm, growing somewhat experienced, I find myself adapating an old quote more and more: Sufficiently advanced static typing is indistinguishable from dynamic typing. Now, I know, it's not true. It's entirely possible to build weird things in python that are provably impossible to typecheck statically. But modern language servers and their type inference capabilities in rust, terraform, or even straight up python are ve…

Please write a type for the following function: def compose(start, *args): def helper(x): for func in reversed(args): x = func(x) return start(x) return helper There is no mainstream typed language which can write a fully general type for the vararg compose function. TypeScript is probably the one that comes closest, but last I checked it still was unable to write a sufficiently powerful array type. You can write a t…

> There is no mainstream typed language which can write a fully general type for the vararg compose function.

True. A more interesting question might be what level of static safety and performance benefits you'd be willing to sacrifice to be able to write functions like this.

Personally, I don't find the kind of code I can't fit into static types particularly appealing, but I find the code navigation, error checking, and optimizations of static types to be priceless.

Re: Tests aren’t enough: Case study after adding type hints to urllib3

#132
post #117
post #101

Earlier quoted context omitted.

I don't understand your argument. Could you please explain it?

Type systems simply have matured a lot. It's not too long ago that you either had very clumsy type systems - C, Java. These type systems were more of a chore than anything else. Especially the generic transition in java was just tedious, you had to type cast a lot of stuff, and the compiler would still yell at you, and things would still crash. Or you had very powerful and advanced type systems - Haskell and C++ with…

> a modern type inference engine can give you type prediction, accurate tab-completion and errro detection (emphasis mine)

"errros" are my nemesis in languages which automatically create a new symbol with every typo!

Re: Tests aren’t enough: Case study after adding type hints to urllib3

#133
post #97

Earlier quoted context omitted.

Hm, growing somewhat experienced, I find myself adapating an old quote more and more: Sufficiently advanced static typing is indistinguishable from dynamic typing. Now, I know, it's not true. It's entirely possible to build weird things in python that are provably impossible to typecheck statically. But modern language servers and their type inference capabilities in rust, terraform, or even straight up python are ve…

Please write a type for the following function: def compose(start, *args): def helper(x): for func in reversed(args): x = func(x) return start(x) return helper There is no mainstream typed language which can write a fully general type for the vararg compose function. TypeScript is probably the one that comes closest, but last I checked it still was unable to write a sufficiently powerful array type. You can write a t…

I took a stab at it, there's not enough information to figure out anything more specific:

  from typing import Callable, Any

  def compose(start: Callable[[Any], Any], *args: Callable[[Any], Any] -> Callable[[Any], Any]:
    def helper(x: Any) -> Any:
      for func in reversed(args):
        x = func(x)
      return start(x)
    return helper

Re: Tests aren’t enough: Case study after adding type hints to urllib3

#134
post #104

Earlier quoted context omitted.

I'm okay with "var = new FooBarBazThingyWithALongName()" because I don't need to see the type name twice there. In an IDE you can get the type annotation from the IDE over every inferred var type, but I don't like requiring an IDE to see that information and like it showing up in 'less' as well.

I agree it's redundant if the type name occurs twice in the same statement. However, further evolution of the code often causes the instantiation to be moved elsewhere, and I wouldn't have confidence that the one doing that change then also changes `var` back to the type name. Instead, it would be nice to have syntax avoiding the duplication in the fashion of `FooBarBazThingyWithALongName thingy = new(...constructor…

C# 9 now has "target-typed new expressions" https://www.thomasclaudiushuber.com/2020/09/08/c-9-0-target-...

Re: Tests aren’t enough: Case study after adding type hints to urllib3

#135
post #64
post #32

Earlier quoted context omitted.

How in the world does type checking lower the ceiling on excellence?

Tbh I'm conflating multiple things, I've heard a lot of good things about Haskell. But in C# for example, if the system was not designed with dependency injection and everything being an interface it's very hard to build a test harness since you can't mock anything. Which means everything has to be tested manually. (I haven't done any C# in a long time, maybe it's not the case anymore) So you have to create an interf…

https://docs.microsoft.com/en-us/visualstudio/test/isolating...

This and other libraries can supersede method modifiers.

Re: Tests aren’t enough: Case study after adding type hints to urllib3

#136
post #74
post #58

Earlier quoted context omitted.

The metaphor doesn't really works, as in software lots of high rise start as a little shed.

Quite the contrary, in my opinion. Lots of what makes various parts of the physical hard are in the infrastructure surrounding them. This is very similar to the complexity in software setups. Take game systems, as an example; far far more effort will be spent in the art and general asset management than is true for many business software setups. Which is why many of the business best practices haven't necessarily mov…

> Take game systems, as an example; far far more effort will be spent in the art and general asset management than is true for many business software setups. Which is why many of the business best practices haven't necessarily moved over to games.

You're right that game development involves a lot of asset stuff that other business software doesn't have to worry about as much. (And, conversely, a lot of business software has to worry about large mutable datasets much more than most games.)

But I don't think that has much bearing on why some business software practices haven't made their way to games. I think the reasons are mostly:

* Games are structurally different from business software, so the patterns that work for the latter aren't always great for the former. MVC makes sense when the "UI" is a relatively thin layer insulated from the "logic". In most games, the "UI" (rendering, animation, VFX, audio, etc.) is huge and more deeply coupled to the game state.

* A lot of enterprise software practices are about maximizing developer productivity in a single codebase over a very long period of time at the expense of runtime performance. Game codebases often have a shorter lifespan and can't afford to sacrifice runtime speed for developer speed.

* Game developers can be insular and are often either oblivious to what's going on outside of games or think it's beneath them and not applicable to their "real" code.

Re: Tests aren’t enough: Case study after adding type hints to urllib3

#137

Earlier quoted context omitted.

Please write a type for the following function: def compose(start, *args): def helper(x): for func in reversed(args): x = func(x) return start(x) return helper There is no mainstream typed language which can write a fully general type for the vararg compose function. TypeScript is probably the one that comes closest, but last I checked it still was unable to write a sufficiently powerful array type. You can write a t…

I took a stab at it, there's not enough information to figure out anything more specific: from typing import Callable, Any def compose(start: Callable[[Any], Any], *args: Callable[[Any], Any] -> Callable[[Any], Any]: def helper(x: Any) -> Any: for func in reversed(args): x = func(x) return start(x) return helper

Sure, that's probably as close as you can get, but ideally it would be possible to write a type which guarantees the input functions are compatible as well as knowing what the type is of the returned function.

Re: Tests aren’t enough: Case study after adding type hints to urllib3

#138
post #119

Earlier quoted context omitted.

Please write a type for the following function: def compose(start, *args): def helper(x): for func in reversed(args): x = func(x) return start(x) return helper There is no mainstream typed language which can write a fully general type for the vararg compose function. TypeScript is probably the one that comes closest, but last I checked it still was unable to write a sufficiently powerful array type. You can write a t…

As I said, there are infinite possible programs that cannot be type checked statically. This is derived from the halting theorem trivially - lambda(p) = if p.halts() then A() else B(). However, the intersection of programs I encounter in practice with the number of programs that can be statically checked is rather large.

You are probably thinking of Gödel's incompleteness theorems. I do not think that you can trivially derive it from the halting problem.

Re: Tests aren’t enough: Case study after adding type hints to urllib3

#139

Earlier quoted context omitted.

Please write a type for the following function: def compose(start, *args): def helper(x): for func in reversed(args): x = func(x) return start(x) return helper There is no mainstream typed language which can write a fully general type for the vararg compose function. TypeScript is probably the one that comes closest, but last I checked it still was unable to write a sufficiently powerful array type. You can write a t…

I think you can in rust as long as args is a slice. Rust doesn't have varargs except for c interop. A slice or Vec of function pointers is the idiomatic way to do the same thing. Something like: fn compose (start: Box X>, args: Vec T>>) -> Fn(T) -> X { move |x: X| { let mut x = x; for func in args.iter(). reversed() { x = func(x); } start(x) } }

This only works if all of the functions return the same type. However, you can write a compose macro which operates as expected.

Re: Tests aren’t enough: Case study after adding type hints to urllib3

#140
I think it's interesting that PEP 484 says ([1]): "the authors have no desire to ever make type hints mandatory, even by convention," while the opening of this article says "type hints have grown from a nice-to-have to an expectation for popular packages." Things don't always work out the way the PEP authors expect.

[1]: https://www.python.org/dev/peps/pep-0484/

Post reply on HN