News for hackers. Stuff that matters.
Re:38% of bugs at Airbnb could have been prevented by using ... by geowwy on Sunday February 10, 2019 @10:29PM (#19131839)
This is my question as well. I think about types even when I don't explicitly declare them.

"Function x will return a list of a"

"Function y will return an instance of b or null"

"Function z will return an instance of c or throw an error"

How much time am I losing by putting that information in the function declaration? I doubt it's more than the time I lose when a function returns or throws something it wasn't supposed to.

Re:38% of bugs at Airbnb could have been prevented by using ... by crumpets on Monday February 11, 2019 @12:06AM (#19132210)
Right, you’re treating the code as statically typed even when it’s not. In that case you never gain the advantage of dynamic languages.

Thinking so strictly about what types a function will receive rules out making use of things like decorators in python that operate on function arguments regardless of type.

Or generic validation utils that take many types and return the passed in type after performing internal validation logic relevant to the type.

Re:38% of bugs at Airbnb could have been prevented by using ... by DCoder on Monday February 11, 2019 @12:55AM (#19132367)
"Takes many types" ≠ "cannot be typed". TypeScript supports decorators, union types, and `any`/`unknown` types.

Those generic use cases are good examples of flexible types, but I have a hard time seeing how

* "I don't know whether the `getMyReplies()` function returns a list of items, an iterator, a non-rewindable generator whose results I need to cache, or a closure with/without memoization" and

* "I don't know whether the singular Reply entity has a field called pid, parent_id, parentId, ParentID, ParentGUID, or parent_message_identifier"

are advantageous to rendering a list of replies.

Re:38% of bugs at Airbnb could have been prevented by using ... by z3t4 on Monday February 11, 2019 @07:26AM (#19133891)
For code written in JavaScript you check the source code to see what arguments it takes and what it returns. If it's not written in JavaScript, for example a Browser API's or NodeJS built in module, you read the documentation and use console.log's. Then you rely of good naming, for example (nrA, nrB) => sum vs (a:Number, b:Number) => c:Number where the one without static types is more clear of what the function does and what it returns.
Re:38% of bugs at Airbnb could have been prevented by using ... by untog on Monday February 11, 2019 @10:05AM (#19134916)
Having to search through source for the argument types of a function is usually an example given in favour of strong typing, not against it.
Re:38% of bugs at Airbnb could have been prevented by using ... by z3t4 on Monday February 11, 2019 @10:31AM (#19135105)
There are not many reasons to read the code of your dependencies, you will learn a lot doing so. One issue when you work with the compiled code is that the type annotations have been removed, and that type annotations leads to more terse code as it would otherwise become too verbose eg. number:number tends to become n:number and when the type is removed it just becomes n, so you kinda become dependent of your tooling and can't easily just stop using it in favor of something better.
Re:38% of bugs at Airbnb could have been prevented by using ... by DCoder on Monday February 11, 2019 @12:59PM (#19136520)
Compiled code doesn't have to be unreadable.

Languages like C and C++ made it readable with debug symbols.

The web stack does the same with source maps. The TypeScript compiler also offers to emit .d.ts files with type information for reuse in other projects.

Re:38% of bugs at Airbnb could have been prevented by using ... by root_axis on Monday February 11, 2019 @01:11AM (#19132426)
> In that case you never gain the advantage of dynamic languages.

Treating the code as statically typed makes the code predictable, less prone to bugs, and easier to maintain. If a function's return type is determined by dynamic factors at run-time, it becomes a maintenance and debugging nightmare; the effect is compounded as more and more unpredictable dynamic functions are chained together.

> operate on function arguments regardless of type

parameterized types and other techniques allow you to describe this type of behavior in a type safe way.

> Or generic validation utils that take many types and return the passed in type after performing internal validation logic relevant to the type.

All these things are possible in typed languages.

Re:38% of bugs at Airbnb could have been prevented by using ... by geowwy on Monday February 11, 2019 @04:20AM (#19133067)
> Right, you’re treating the code as statically typed even when it’s not. In that case you never gain the advantage of dynamic languages.

Both the things you mention can be done in statically typed languages. The only difference is in dynamic languages you don't have to declare interfaces, subclasses, etc. I just wonder whether that really is as much of an advantage as people think.

I've spend years using both types of languages and I think I think the safety of statically typed languages is usually worth the slight amount of friction it adds.

Re:38% of bugs at Airbnb could have been prevented by using ... by Guthur on Sunday February 10, 2019 @10:55PM (#19131938)
You do this because that's how you have trained yourself to think about code. It's a little self centered too assume this for everyone else.
Re:38% of bugs at Airbnb could have been prevented by using ... by int_19h on Sunday February 10, 2019 @11:42PM (#19132124)
Thinking about data contracts for inputs and outputs is pretty basic stuff. If you don't do that, how do you know what your code actually does?
Re:38% of bugs at Airbnb could have been prevented by using ... by carlmr on Monday February 11, 2019 @03:36AM (#19132880)
They don't, but they're fast and fail often.
Re:38% of bugs at Airbnb could have been prevented by using ... by regularfry on Monday February 11, 2019 @10:26AM (#19135067)
There's a gap between things it might make sense to consider as data contracts, and things that can be expressed in practical type systems in common use.

One example: a function which, when given a single element, returns a single transform of that element. When passed a list of elements, returns a map of that transform over the list. You can argue as to whether that's a good idea or not, but I've seen JS functions that make sense in context which do that.

This might just be my lack of type system expressivity knowledge, but how would one annotate the type of that function? I get that you could use a union type on the param and the return value, but not how you link the two.

Re:38% of bugs at Airbnb could have been prevented by using ... by hombre_fatal on Monday February 11, 2019 @11:13AM (#19135503)
> how would one annotate the type of that function

Some languages support function overloads like Swift and Kotlin.

    fn foo(input: A, xform: A -> B) -> B
    fn foo(input: [A], xform: A -> B) -> [B]
Hmm, maybe we can generalize that into a Functor.
Re:38% of bugs at Airbnb could have been prevented by using ... by int_19h on Monday February 11, 2019 @03:41PM (#19138088)
Yes, this is very common in JS, and somewhat common in other popular dynamic languages. In TypeScript, for example, you'd implement this by defining several overloaded signatures. Note that this isn't C++ or Java, so you still have a single function implementing all of them - the various overloads just specify what happens depending on the arguments you pass.

https://www.typescriptlang.org/docs/handbook/functions.html#...

This is a limited approach, because the overloads aren't a part of a function type - i.e. you can't have an anonymous function value that is overload-typed, it must be a named function. In principle, a similar mechanism could be used for types as well, it just doesn't usually come up in that context (e.g. callbacks typically don't return different things), which is probably why they didn't do it.

Re:38% of bugs at Airbnb could have been prevented by using ... by cjs_2 on Monday February 11, 2019 @02:40AM (#19132680)
How could one think about functions differently than about what their input and output is?
Re:38% of bugs at Airbnb could have been prevented by using ... by zimablue on Monday February 11, 2019 @05:52AM (#19133504)
Your statement is just a tiny bit too general and that's where you're missing.

"What about their input and output is" => "what type their input/output is"

The next question is what does the type of the input/output actually tell you about the input/output? In the most popular languages (using interfaces), it basically tells you that the input/output might have a, b and c set (or they might be null), and it could also have anything else set.

So the actual information you have is that you might or might not have (a,b,c) and also might or might not have (anything). Not as foolproof as you think. The natural objection is that aha! I defined this class to require (a,b,c) in the constructor and do a nullity check, so I know much more than this! But this is back to having "types in your head", that constructor signature and nullity check isn't compiler enforced (as in if you change it, nothing will fail in the typesystem at the point of the function that we're checking, as long as those fields remain on the class). So the useful part of the static typing is actually living in your head either way.