←back to thread

511 points mootrichard | 7 comments | | HN request time: 1.01s | source | bottom
Show context
setpatchaddress ◴[] No.23990944[source]
I'm really puzzled by the decision to use a separate file for this. The stated justification ("it doesn't require changing Ruby code") doesn't make sense, and my personal experience with languages with external type specifications is strongly negative. It's an unbelievable pain to keep multiple interface files in sync over time.

`.h` files are not something to emulate! External interfaces should be generated by tools where needed.

replies(5): >>23991001 #>>23991013 #>>23991258 #>>23991289 #>>23994203 #
heavenlyblue ◴[] No.23991013[source]
How do you even type local variables?
replies(2): >>23991291 #>>23991344 #
1. RangerScience ◴[] No.23991291[source]
Why would you need to?

Edit: Like, seriously. Either the local var is populated by something coming in externally (which is then typable) or, unless your code is too complex / large, it should be easy to see everywhere it's used, and then why would you need that additional typing info?

replies(4): >>23991692 #>>23991831 #>>23991884 #>>23992240 #
2. viraptor ◴[] No.23991692[source]
Could be needed if you have a factory returning various subclasses, but you're making a call which you know will create only one type.

Like `foo=open_database("mysql://...")`.

3. frewsxcv ◴[] No.23991831[source]
If something is untyped in Sorbet, you can give it a type with `T.let`. So if the return value of function `foo` is untyped, but you have a high degree of confidence that it will return a `String`, you can do `ret = T.let(foo, String)`
4. amw-zero ◴[] No.23991884[source]
Because when you see the benefit of type annotations (I’m not saying that’s objective, just if you do go that route) you want to add type information to as much as possible. Leaving them off because you want to is one thing. Not being able to is an unnecessary limitation.
replies(1): >>23993492 #
5. hombre_fatal ◴[] No.23992240[source]
One big use-case of types is the sanity-check that the value is what you think it is.

A classic example of where I might have an inline type annotation in Rust is when I'm doing a non-trivial chain of Future/Result combinators in the middle of a function. It doesn't take much code for your understanding to desync from reality. Annotating "Result<String, IOError>" inline both documents to others what this intermediate value is but also creates better, local errors as the chain is modified.

Complex stuff does generally get factored out into functions, but at the same time, it's nice when you're the one who decides when it makes sense to extract code rather than a limitation of the typing syntax. Those things don't always line up.

6. kgilpin ◴[] No.23993492[source]
The point is that the type of a local variable can almost always be inferred based on what it’s assigned to.
replies(1): >>24010078 #
7. amw-zero ◴[] No.24010078{3}[source]
While that’s true, that’s not what I’m talking about. I’m talking about the communicative benefit of type annotations. If you get the benefit from seeing the types, you don’t want them to be inferred. You use them as a reading tool.