Live data from Hacker News

Why static languages suffer from complexity

hirrolot.github.io

141–150 of 306 posts

Re: Why static languages suffer from complexity

#141

This article spends many words to say, “there is no silver bullet”. But dynamically typed languages produce at least the same amount of accidental complexity, just in different ways.

Indeed, the article has it backwards. The types are always there. Your program will fail at runtime if it's not correct. The type system merely surfaced that. Complexity in the types happens when the type system isn't expressive enough. Or when you're trying to do something that would make the compiler try to solve the halting problem. To that last point, this is why the PLT community has pushed in the direction that…

That's the hope, but saying there's something wrong is insufficient. The compile-time errors need to be understandable, or it's just going to be frustrating.

Maybe we should judge compile-time constraint systems by how easy it is for the library author to add good error messages for misuse?

Re: Why static languages suffer from complexity

#142

Fascination with type systems does not seem to be all that useful in practice. Go has a minimal type system, and is able to do much of Google's internal server side work. Most of the problems that cause non-trivial bugs come from invariant violations. At point A, there's some assumption, and way over there at point B, that assumption is violated. That's an invariant violation. Type systems prevent some invariant viol…

Rust contribution affect less than 1% of programmers. Most code written today do not require manual memory management or even explicit multithreading.

I think typescript with gradual and structural typing and similar like mypy or sorbet are making real difference.

Type systems provide multiple benefits, performance, self-documentation, better tooling and more explicit data model.

Re: Why static languages suffer from complexity

#143
post #12

> I cannot imagine a single language without the if operator, but only a few PLs accommodate full-fledged trait bounds, not to mention pattern matching. This is inconsistency . . . How? > Sometimes, software engineers find their languages too primitive to express their ideas even in dynamic code. But they do not give up . . . Is this a failure of the language, or a failure of the engineer? > If we make our languages…

> > I cannot imagine a single language without the if operator… Production languages (like prolog or make) don’t need an if statement or operator as selection is implicit when a production matches.

In Prolog :- is the if operator.

Re: Why static languages suffer from complexity

#145

Fascination with type systems does not seem to be all that useful in practice. Go has a minimal type system, and is able to do much of Google's internal server side work. Most of the problems that cause non-trivial bugs come from invariant violations. At point A, there's some assumption, and way over there at point B, that assumption is violated. That's an invariant violation. Type systems prevent some invariant viol…

> Fascination with type systems does not seem to be all that useful in practice.

And yet type theory is an excellent way to express all kinds of invariants. The more rich the type system the more you can express. If you get to dependent types you essentially have all of mathematics at your disposal. This is the basis of some of the most advance proof automation available.

What is super cool is that proofs are programs. You can write your programs and use the same language to prove theorems about them.

This is still fairly advanced stuff for most programming activities but the languages have been steadily getting better and the automation faster and I think the worlds will eventually collide in some area of industrial programming. We're already seeing it happen in security, privacy, and networking.

I don't think type systems suffer from complexity. They merely reveal the inherent complexity. You can use languages that hide it from you but you pay a price: errors only become obvious at run time when the program fails. For small programs that's easy enough to tolerate but for large ones? Ones where certain properties cannot fail? Not so much in my experience.

update: clarified wording of "proofs are programs"

Re: Why static languages suffer from complexity

#146

Having used Clojure for a while now, I will say having 90% of things be a primitive, map, or vector goes a long way in and of itself. A lot of types concocted in a more conventional language just don't need to exist, IMO, and they create so much baggage around themselves.

Hmm, how well does this scale though? you are passing around these giant maps of vectors of tuples and then you pass it to someone unfamiliar with the code, how the hell do they know what's in there? Is the order price the first element of the tuple or the second? What happens when I refactor things and now all the tuple elements shift over one? Surely you'll end up writing just as much in documentation as you would have to specify the types?

Currently working my way through some complex Python code written in that style and it's completely impossible to understand it. In fact, the only way I can actually do it is transforming all these ad hoc data structures into proper types so I can make sense of it.

Re: Why static languages suffer from complexity

#147

So whenever I have to study someone else's 'dynamic' python I encounter this sort of thing: def foo(bar, baz): bar(baz) ... What the heck is 'bar' and 'baz'? I deduce no more than 'bar' can be called with a single 'baz'. I can't use my editor/IDE to "go to definition" of bar/baz to figure out what is going on because everything is dynamically determined at runtime, and even grep -ri '\(foo\|bar\|baz\)' --include \*.p…

The real power of dynamic languages is being able to do: const foo = JSON.parse(arbitraryJsonString); and not having to worry about the structure up front.

In Nim you can even convert JSON to static types! https://nim-lang.org/docs/json.html#to%2CJsonNode%2Ctypedesc...

Now you get type checking on JSON at compile time :)

Re: Why static languages suffer from complexity

#148
post #44

So whenever I have to study someone else's 'dynamic' python I encounter this sort of thing: def foo(bar, baz): bar(baz) ... What the heck is 'bar' and 'baz'? I deduce no more than 'bar' can be called with a single 'baz'. I can't use my editor/IDE to "go to definition" of bar/baz to figure out what is going on because everything is dynamically determined at runtime, and even grep -ri '\(foo\|bar\|baz\)' --include \*.p…

What the heck is 'bar' and 'baz'? So there's no docstring? And the actual variables are that random and indecipherable? Sounds like the problem is that you're tasked with looking at code written by someone who is either inexperienced or fundamentally careless. When dealing with reasonably maintained codebases, this kind of situation would seem pretty rare. In modern python we now have type hints of course, which have…

I do not want to argument against Python. This is more like off topic / side note.

What I like about Rust is that it even checks code in your 'docstring'. So it is easier to keep it maintained.

Re: Why static languages suffer from complexity

#149
The problem I find with static typing is that it so easily leads you over-specifying the requirements / constraints. In fact, it makes such a virtue out of that over-specification that many people would consider it a best practice to do so.

For example, perhaps my `calculate_price` function only depends on 2 attributes of the order which has 65 attributes. Am I creating a 2-element data type for that function to process? no! I'm specifying that it processes an Order data type, with all its 65 elements. But implicitly then I'm saying the function has 65 input parameters of all these specific types and nobody can call it now without providing them all. What a pain! Huge amount of extra code, refactoring, unit testing, because of this.

So either you end up with a cambrian explosion of micro-types or you have these way overspecified interfaces everywhere.

Compare with dynamic languages (or structural typing, Go etc) that only care that things "quack like a duck". The calculate_price function doesn't care what object you give it, as long as it has the two attributes it needs. Now I can unit test `calculate_price` with a 2-element object rather than needlessly creating the 23 irrelevant required elements of a valid Order.

I think a lot could be solved with culture shift. Where data types are really known and locked in, use the crap out of them. As soon as things get ambiguous or flexible, go right ahead and specify that your function takes a Map. If a useful concrete interface emerges at some point factor it out then. The problem is that this is really frowned upon in a lot of places.

Re: Why static languages suffer from complexity

#150

Earlier quoted context omitted.

Expressiveness is not an unambiguous net good -- more expressiveness is not a priori better. Expressiveness carries costs of comprehension and coherence that need to be appropriately weighed in the contexts where the language will be applied. Programming languages are not theoretical things. They're concrete, practical tools that _enable_ other stuff. Engineering, not science.

How would you define expressiveness (as its commonly used, so a definition where Turing complete languages can have different expressiveness) if not as how much something can be simplified and thus aiding comprehension, rather than detracting from it? >Programming languages are not theoretical things. They're concrete, practical tools that _enable_ other stuff. Engineering, not science. You can't escape theory, engin…

Increasing expressiveness of a language necessarily increases its complexity. Comprehension is important but it's a function of "the whole stack" -- language and program both.

> engineering is applied science.

Absolutely. But the metrics are different.

Post reply on HN