News for hackers. Stuff that matters.
Re:Learning Elm has gotten me confused about static vs. dyna... by hacker_9 on Tuesday June 14, 2016 @03:54PM (#11904826)
> The dynamic world lets us have inconsistent code that partially works

This is precisely why I have nightmares about refactoring dynamic codebases.

Re:Learning Elm has gotten me confused about static vs. dyna... by Touche on Tuesday June 14, 2016 @05:32PM (#11905482)
If it's tested, you shouldn't.
Re:Learning Elm has gotten me confused about static vs. dyna... by bunderbunder on Tuesday June 14, 2016 @06:38PM (#11905906)
Unit tests are essential, but they only cover the errors that the person writing the tests thought to write. Given that even the highest coverage code I've ever worked on could still be riddled with bugs, I submit that us humans can be pretty bad at thinking of all the tests we should write.

Static typing, by contrast, covers all type errors, which can take care of quite a bit if you know how to use the type system to your advantage. On top of that, if you don't rely on a refactoring tool (which I recommend avoiding for anything non-trivial) then the compiler will guide you to all the spots where that type is being used, which gives you an opportunity to re-evaluate the correctness of the code that uses it.

Is it more work? Yes. Is that a bad thing? Many would argue it's a good thing.

Re:Learning Elm has gotten me confused about static vs. dyna... by Touche on Tuesday June 14, 2016 @06:58PM (#11906033)
I get the benefit of static typing, my above comment was directed at the suggestion that refactoring dynamic code is something to be afraid of. You commonly hear this from people who primarily use static languages.

I personally don't feel that the benefits outweigh the cost; namely that I have to babysit a compiler and stop development while I fix compiler errors that are irrelevant to the thing I'm working (if I'm working on widget A and I broke widget B by changing a type, I don't want to fix widget B right now).

Re:Learning Elm has gotten me confused about static vs. dyna... by bunderbunder on Tuesday June 14, 2016 @07:24PM (#11906175)
There might be another cultural difference there: I've never worked in a place that used a dynamic language for the majority of the code base, but from what you're saying it sounds like simultaneously refactoring and adding features is something you'd consider to be a normal task. I'm used to that being considered a big no-no, because it makes code reviews and source control history harder to understand.
Re:Learning Elm has gotten me confused about static vs. dyna... by kazinator on Tuesday June 14, 2016 @08:34PM (#11906460)
You can can work on several things at once in your local repo and use "git commit --patch" to separate changes. Of course you never want unrelated changes (different "topics") in the same commit.

If a feature is better implemented after a certain refactoring, then you can do that at the same time locally but still separate it out into different commits.

Re:Learning Elm has gotten me confused about static vs. dyna... by dllthomas on Wednesday June 15, 2016 @02:18AM (#11907472)
Exactly this, in any language!
Re:Learning Elm has gotten me confused about static vs. dyna... by jdbernard on Wednesday June 15, 2016 @09:18AM (#11909112)
Generally I like refactoring. Essentially, it is the process of taking disjoint, complicated code and making simpler and logically consistent. I have never really though of refactoring as something to fear until I'd spent time working in a Node shop.

You don't want to stop and fix "unrelated" errors, but if B was broken by a type change in A then it is almost certain that B is affected by the changes in A. Right now, when you are making the changes in A, is the best time to address the fallout, because you have the reason for the change and all its subtleties in mind.

The vast majority of the bugs my team addressed after our last major refactor in our Node codebase were of this kind: either completely forgotten or unknown components affected, or fixes that were not fully aware of the changes made. Knowing at the time of the change all of the places that change affects is extremely powerful. Tests only get you this for the easy cases you've thought of. Static typing doesn't get you that entirely, but it gets you a lot closer than dynamic typing.

So I'd argue the opposite. Dynamic languages taught me to fear refactoring because they're is always the danger that you missed something buried somewhere that will come back to bite you in really subtle ways. I never get the satisfying feeling of unifying the code under a new logical consistency because there may still be these loose ends lurking around.

Re:Learning Elm has gotten me confused about static vs. dyna... by hinkley on Wednesday June 15, 2016 @10:31AM (#11909558)
Survivor bias. Only a special breed of developer gets a job working in a functional language, except for JavaScript.

Normal Devs write mediocre tests on a good day. You will find a significant percent that assert nothing or are tautological. Then when your requirements change or you are refactoring you will find that we have tested the implementation and made really unfortunate assumptions.

If you invite everyone to join you, a lot of the things you hold dear will get lost. It's super frustrating to have to trust people who can't be.

I worked with static languages for a long time, and I have been doing test automation for a long time (10 years). There are many things I understand about writing good tests, many of them counterintuitive things, including some big mistakes everyone seems to have to experience to believe.

I can't articulate it yet, I'm still processing, but recently some of the classes of error I'm finding in my and other's tests have convinced me that tests can't practically and efficiently verify everything important, and that maybe testing in this way and to this extent isn't the solution we need.

Often what makes a good test is contrary to how we write production code. Testing well is pretty damned hard for people. And I now despair of ever convincing the hoi polloi not to eagerly paint us into corners.

Re:Learning Elm has gotten me confused about static vs. dyna... by bunderbunder on Wednesday June 15, 2016 @06:48PM (#11912706)
I'm very curious to hear more of your thoughts on this. Might they ever show up on a blog at some point in the future?
Re:Learning Elm has gotten me confused about static vs. dyna... by jpindar on Wednesday June 15, 2016 @01:39AM (#11907351)
I love compiler errors - because I'm the only one who sees them.
Re:Learning Elm has gotten me confused about static vs. dyna... by hinkley on Wednesday June 15, 2016 @03:25AM (#11907686)
I prefer automatic tool followed by VCS "diff against head" myself. I get to replace a bunch of error prone typing with a small code review.
Re:Learning Elm has gotten me confused about static vs. dyna... by mkehrt on Tuesday June 14, 2016 @07:42PM (#11906269)
Luckily, my compiler writes large piles of tests for me. I call it the typechecker.
Re:Learning Elm has gotten me confused about static vs. dyna... by kazinator on Tuesday June 14, 2016 @08:03PM (#11906354)
These tests only cover the type space, which is trivial. And doesn't vary at run time. Even under dynamic typing, it's by large immutable: short of special tricks like change-class in Common Lisp, objects are immutable, and most data flow paths carry the same types all the time.

For instance, consider a function which calculates the GCD of two integers. Everything in that function is an integer. Your compiler tests it for you: nope, no strings or floats in there: nothing but integers, check!

It's basically one test, and it has nothing to do with whether that function calculates the GCD correctly. It will pass even if that function calculates the LCM due to misunderstood requirements.

Re:Learning Elm has gotten me confused about static vs. dyna... by pka on Wednesday June 15, 2016 @12:16AM (#11907143)
There [0]: the GCD m n d type proves that the greatest common divisor of m and n is d.

[0] http://www.cse.chalmers.se/~nad/repos/lib/src/Data/Nat/GCD.a...

Re:Learning Elm has gotten me confused about static vs. dyna... by willtim on Wednesday June 15, 2016 @02:25AM (#11907493)
This is a great example. I also recall seeing refinement types (Liquid Haskell) used to prove termination of Euclids GCD.
Re:Learning Elm has gotten me confused about static vs. dyna... by kazinator on Wednesday June 15, 2016 @02:10PM (#11910909)
For all I know, the GCD function buried in that gobbledygook could actually be calculating the LCM, and the proof could be of that.
Re:Learning Elm has gotten me confused about static vs. dyna... by pka on Thursday June 16, 2016 @11:55AM (#11916950)
For all I know

Agreed.

Re:Learning Elm has gotten me confused about static vs. dyna... by tome on Wednesday June 15, 2016 @03:23AM (#11907680)
> These tests only cover the type space, which is trivial.

Granted it's not enormous, but if you think it's trivial you'll probably be surprised by the range of things you can encode in the Haskell type system.

Re:Learning Elm has gotten me confused about static vs. dyna... by kazinator on Wednesday June 15, 2016 @03:39PM (#11911570)
That encoding requires you to be a type system expert, and write reams of additional code surrounding the actual code. That additional code has to be well thought out and designed; proofs don't just pop out of thin air, all ready to go and represented as type via Curry-Howard!

Ordinary code does not encode very interesting things about itself via its typing. Well typed usually just means "there is no trivial mistake here", on about the same level as a missing semicolon in a C struct declaration.

Re:Learning Elm has gotten me confused about static vs. dyna... by dllthomas on Wednesday June 15, 2016 @09:04PM (#11913308)
That's just not true.

I have some interest in types (mostly practical, some theoretical) but I have no graduate degree, I still regularly encounter both theory and type voodoo I don't understand, and I wouldn't consider myself a "type system expert".

On a recent project I was able to use the type checker to help me catch things including 1) passing a bid price where I meant an ask price, 2) using an index into the wrong array, 3) calling a function not permitted to run on the thread in question (because of data access or deliberate marking).

This wasn't Haskell - it was C.

Re:Learning Elm has gotten me confused about static vs. dyna... by willtim on Tuesday June 14, 2016 @05:53PM (#11905635)
Testing shows the presence, not the absence of bugs. Dijkstra (1969).
Re:Learning Elm has gotten me confused about static vs. dyna... by lucisferre on Tuesday June 14, 2016 @06:04PM (#11905697)
Same can be said of static type checking so what is your point? Are you suggesting that those working in static languages don't need to write tests?

Static type checking generally represents an even lower form of error detection than functional and unit testing does. Sure, it can be convenient to have it, but lately I see a lot of static language novices around here talking about their recent and limited experience with type checking as if they are suddenly experts in the tradeoffs between static and dynamic languages.

Re:Learning Elm has gotten me confused about static vs. dyna... by pka on Tuesday June 14, 2016 @06:12PM (#11905747)
But, as you surely know, types prove something about a piece of code. This means they can very well prove the absence of (certain) bugs.

So generally, the more invariants you manage to capture in your types, the more categories of bugs you can statically prove will never happen.

Re:Learning Elm has gotten me confused about static vs. dyna... by jw- on Tuesday June 14, 2016 @07:25PM (#11906181)
This is all true, but is it not a problem that most static languages don't let you (easily) specify the kind of invariants people include in unit-tests.
Re:Learning Elm has gotten me confused about static vs. dyna... by acjohnson55 on Tuesday June 14, 2016 @07:56PM (#11906329)
Sure. But you write unit tests for those.
Re:Learning Elm has gotten me confused about static vs. dyna... by willtim on Tuesday June 14, 2016 @06:19PM (#11905801)
> Same can be said of static type checking so what is your point?

That isn't true. Static typing offers machine checked proofs of the absence of a whole class of trivial errors; and potentially any invariants you've managed to teach it.

My point was that testing does not negate the need for static types, as implied by the previous poster.

Re:Learning Elm has gotten me confused about static vs. dyna... by kazinator on Tuesday June 14, 2016 @08:58PM (#11906531)
Although "class" sounds big, in fact there is only a countable number of places (nodes in the program's tree) where you can have a type error. The space in which any error whatsoever can occur is astronomical.
Re:Learning Elm has gotten me confused about static vs. dyna... by TheDong on Tuesday June 14, 2016 @11:31PM (#11907033)
Let me give an analogy:

Claim: "Getting vaccinated stops a whole class of diseases which might kill you"

Your rebuttal: Although "class" sounds big, in fact there are only a countable number of viruses that vaccines save you from. The number of ways in which you can die is astronomical.

In the above analogy, as in your original statement, you're completely missing the point that the class of errors / class of diseases is an important class and easily preventable, therefore you should do it.

In fact, I think what you've said is the reverse of true. Static typing means that there's a chance of an error at each node in the program's tree because a statically typed and statically compiled language ensures that the program can be rendered as an AST before you ship it to your user.

A dynamically typed interpreted language can have an error at literally any character in the entire thing, and you don't have "compile-time" to tell you it's not an error.

The class of errors that you're saving yourself from is "every single character of this program could be wrong in a way that results in it not even being representable as an AST; there are astronomically many ways that can occur".

In addition, it now goes wrong much later. You have to ensure that you've hit every path with testing before you can be even somewhat confident it's valid code, let alone logically correct and bug-free in other ways. A compiled statically-typed language you waste no more time than a compile-cycle to get that minimal assurance.

Re:Learning Elm has gotten me confused about static vs. dyna... by kazinator on Wednesday June 15, 2016 @11:26AM (#11909881)
Let me give an analogy:

Claim: "Using a plastic liner stops urine from getting into the mattress".

My rebuttal: "That's well and good, but I'm sure I didn't wet my bed past the age of three."

Re:Learning Elm has gotten me confused about static vs. dyna... by dllthomas on Wednesday June 15, 2016 @12:32PM (#11910303)
But then you find yourself sharing a bed with an infant.

Source: I'm typing this from a bed I'm sharing with an infant.

(I don't actually mean this to be an argument, just fun. "Other people will make type errors" is not the argument I'd make.)

Re:Learning Elm has gotten me confused about static vs. dyna... by dllthomas on Wednesday June 15, 2016 @02:33AM (#11907515)
"Compiled" and "dynamically typed" are not opposites.
Re:Learning Elm has gotten me confused about static vs. dyna... by dllthomas on Wednesday June 15, 2016 @02:29AM (#11907507)
It seems like the reasoning here is exactly the wrong way round.

The number of possible programs is astronomical (though still countable!). The number of possible programs with the correct type is substantially smaller. If we can construct our types and type checking such that the errors we are likely to make are likely to result in ill-typed programs, then we can substantially reduce the number of uncaught errors.

More generally, in your comparison you seem to be expecting that a unique error be detected in a unique place. There is no particular reason multiple (or manifold) errors should not be expected to produce an error in the same "nodes in the program's tree".

Re:Learning Elm has gotten me confused about static vs. dyna... by kazinator on Wednesday June 15, 2016 @11:35AM (#11909940)
I'm looking at it as a search problem. I don't care about the likelihood of a randomly generated program with correct syntax being correctly typed because people don't program that way. But rather this: let's take a correct program of size N (N nodes in the syntax tree) and insert a single error into it and give the modified program to someone to find the error (without giving them the original, of course). If it's a type error, it can be found by searching the space of N nodes. If it can be any defect whatsoever, the search space is the entire state space of the program emanating from all combinations of all possible inputs.
Re:Learning Elm has gotten me confused about static vs. dyna... by dllthomas on Wednesday June 15, 2016 @02:58PM (#11911244)
> I don't care about the likelihood of a randomly generated program with correct syntax being correctly typed because people don't program that way.

Agreed!

> But rather this: let's take a correct program of size N (N nodes in the syntax tree) and insert a single error into it and give the modified program to someone to find the error (without giving them the original, of course).

I think that's a good approximation. There is some additional structure it discards; I care most about errors that people are likely to make, and about surfacing changes required in likely refactoring. But I expect something that does well at the one is likely to do well enough at the other.

> If it's a type error, it can be found by searching the space of N nodes. If it can be any defect whatsoever, the search space is the entire state space of the program emanating from all combinations of all possible inputs.

Which is exactly why we want to make as many errors "type errors" as possible (modulo tradeoffs). We'd much, much rather search that smaller space.

Re:Learning Elm has gotten me confused about static vs. dyna... by jdmichal on Tuesday June 14, 2016 @06:22PM (#11905823)
> Are you suggesting that those working in static languages don't need to write tests?

You certainly don't need to write tests that Math.floor will return NaN when you pass it something that's not a number...

Re:Learning Elm has gotten me confused about static vs. dyna... by kazinator on Tuesday June 14, 2016 @10:15PM (#11906802)
What? NaN is actually a number in the sense of being in the domain of the floating-point type. You seem to be mixing up "not a number" (as in character string or list) versus "not a number" as in a special IEEE representation that has special uses in numeric code.

A floor function that returns NaN when given a string, instead of throwing a type mismatch exception, is crap design, and a strawman example of that type of checking. It's not an appropriate use of NaN!

Re:Learning Elm has gotten me confused about static vs. dyna... by jdmichal on Tuesday June 14, 2016 @11:19PM (#11906997)
I agree with you [0], but that's what JavaScript gives us to work with.

[0] https://news.ycombinator.com/item?id=11898046

Re:Learning Elm has gotten me confused about static vs. dyna... by gertef on Tuesday June 14, 2016 @06:42PM (#11905935)
When my typechecker writes most of my tests for me, I have time to write features.
Re:Learning Elm has gotten me confused about static vs. dyna... by Touche on Tuesday June 14, 2016 @06:49PM (#11905980)
If so, I'd say you were writing the wrong kinds of tests before. I work in JavaScript and almost never write type verification tests.
Re:Learning Elm has gotten me confused about static vs. dyna... by zeckalpha on Tuesday June 14, 2016 @07:51PM (#11906304)
Types in JavaScript aren't very expressive. When you encode your business logic in the type system, even business logic can be "tested" via the type checker.