Live data from Hacker News

Why static languages suffer from complexity

hirrolot.github.io

61–70 of 306 posts

Re: Why static languages suffer from complexity

#61

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…

Static languages unfortunately don't save you from that. You find automatically inferred types, or types that refer to some abstract interface or template-class-mess but you have no idea where the actual implementation lives until you compile with RTTI and run it under a debugger... and as tfa posits, people working with the limitations of static languages often end up reinventing a dynamic structure. Is this somehow…

> to some abstract interface or template-class-mess

And traits! "Oh look, this functionality is implemented in a trait implemented by a trait implemented by a trait implemented by what you're looking at. Maybe"

Re: Why static languages suffer from complexity

#62

Earlier quoted context omitted.

Static languages unfortunately don't save you from that. You find automatically inferred types, or types that refer to some abstract interface or template-class-mess but you have no idea where the actual implementation lives until you compile with RTTI and run it under a debugger... and as tfa posits, people working with the limitations of static languages often end up reinventing a dynamic structure. Is this somehow…

> Static languages unfortunately don't save you from that. You find automatically inferred types, Oh yes, they do. Even inferred, the types are there and pretty easy to locate, even if you're not using an IDE.

The types are there.. but you don't know which one it is that your program is dealing with. You could have dozens of implementations for any given abstract interface. One gets picked up at run time.

Re: Why static languages suffer from complexity

#63
post #37

Earlier quoted context omitted.

Yup, I find this completely insane behavior to think that you somehow benefit from types not being there. You just make it way harder for people to understand your code and contribute to it.

Oh yeah the easiest code in the world to read is some contorted type system and function signatures that look like hieroglyphics that you need a PHd in CS to comprehend. Python is easy to grok, and if you have programmers writing code like bar(foo,baz) then the problem is not Python. You can write crap in any language. Unit tests do much of what typing checks anyway ... and here's the thing ... you NEED unit tests no…

> Python is easy to grok

It’s what you’re used to. I personally find Python horrible to read because I used to a whole different class of programming languages. But I’m sure some of my code might be hard to read by others who aren’t used to that particular programming language too.

> Unit tests do much of what typing checks anyway ... and here's the thing ... you NEED unit tests no matter what.

Some, not all. Strictly typed languages are handy when it comes to refactoring and unit tests can sometimes fail there if the design is being changed enough that the unit tests need rewriting too.

> No typing system can tell you that you wrote > when you should have written Not technically true. Some languages with a richer set of types and operator overloading could have code written to detect that sort of thing. But I do get your point that unit tests are import too.

I’ve been programming for > 30 years and in dozens of different languages. In that time I’ve felt strictly typed languages make larger and more mature code based slightly easier to maintain. While loosely typed languages are easier for smaller and/or younger code based. But largely it boils more down to personal preference than anything.

I will caveat that by saying the fact that Python supports type annotations should be telling that even dynamic languages benefit from a stricter approach to typing.

Re: Why static languages suffer from complexity

#64
post #33

Yeah, the current problem is that Idris code is far less efficient than Rust code, because Idris boxes everything and erases all types, and also Idris's support for borrowing seems less powerful than Rust (it lacks first-class mutable borrows as far as I can tell). It seems that fixing this is a research problem, which would lead to the holy grail of programming languages, i.e. an ultimate language that is as express…

> an ultimate language that is as expressive as Idris and as efficient as Rust, and is thus essentially perfect.

Are both Idris's expressiveness and Rust's efficiency (given stronger guarantees) perfect? Aren't theese languages really complex both to learn and to write? There are poblems without a solution, perfect and unique to all of them.

Re: Why static languages suffer from complexity

#65
post #60
post #44

Earlier quoted context omitted.

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…

Coming from any statically typed language to Python or JavaScript codebases this plagues me. Virtually every project I have seen suffers from this. Function names and doc comments describe behavior, not argument and return types.

Not argument and return types.

When conventions are followed they do exactly that, actually. And unless the code is a complete trainwreck, it's pretty easy to tell what the return type is, even without explicit annotation in the docstring.

Re: Why static languages suffer from complexity

#66

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.

That’s not a capability unique to dynamic languages

Re: Why static languages suffer from complexity

#67
post #37

Earlier quoted context omitted.

Yup, I find this completely insane behavior to think that you somehow benefit from types not being there. You just make it way harder for people to understand your code and contribute to it.

Oh yeah the easiest code in the world to read is some contorted type system and function signatures that look like hieroglyphics that you need a PHd in CS to comprehend. Python is easy to grok, and if you have programmers writing code like bar(foo,baz) then the problem is not Python. You can write crap in any language. Unit tests do much of what typing checks anyway ... and here's the thing ... you NEED unit tests no…

> Oh yeah the easiest code in the world to read is some contorted type system and function signatures that look like hieroglyphics that you need a PHd in CS to comprehend.

People who just learn programming probably think the same about whatever language they are learning.

> No typing system can tell you that you wrote > when you should have written The more the compiler can figure out for you, the quicker problems can be identified and fixed. I stopped using python altogether, because it was just infuriating to have the tiniest mistakes blowing up in spectacular and inscrutable ways. Mixing up values of complex types often does not fail at the actual site of the error, but much, much later. Sometimes literally later in time, as in hours, days, or months until you get an obscure "FooType does not Bar" error, and how the thing in question ever became a FooType is inscrutable at that point. If the result even is a runtime error at all! (Bonus points if your production database is now full of junk as well.[1])

The unit test did not catch it because it did not test the offending composition of classes and functions. Meanwhile, a compiler would have caught it immediately: "The thing you're doing here leads to your data structures being nested wrong."

When I started using async/await in python, at first it was just over, since in plain python that introduces another layer of typing without any assistance whatsoever. Then I discovered mypy which actually lets me do some amount of static typing in python, and it was very enjoyable and now python is back on the table for smaller projects.

There is a reason Haskell has the reputation of "if it compiles, it works". There is a reason why system programmers that work on critical systems are jealously eyeing Rust if their shop still does C.

By the way, dependent type systems absolutely can tell you if you wrote > instead of [1] Yes sqlite, I'm looking at you. The decision to make database column dynamically typed, and hence have for example an INTEGER column silently accept data that is very much not an INTEGER at all, caused me some grief on a widely deployed system once.

Re: Why static languages suffer from complexity

#68

I dislike the phrase 'dynamic language' and especially dislike the phrase 'static language'. We should say 'dynamically typed' or 'statically typed', because 'static' languages are the site of major dynamism.

I think 'dynamic language' is appropriate here, since it's not only talking about types; it's largely talking about macros, pre-processors, reflection, etc. too.

Also, the main argument is that separating features into those used at compile-time (AKA static) and run-time (AKA dynamic) is necessarily creating separate languages (i.e. a "static language", which may involve types, macros, preprocessors, etc.; and a "dynamic language", which may involve memory allocation, branching, I/O, etc.)

Re: Why static languages suffer from complexity

#69

Earlier quoted context omitted.

When that JSON payload changes (intentionally or not), you will run into a mysterious problem in some unrelated area of your code. It will be significantly more expensive to fix than failing fast at the point of parsing.

But depending on the situation, that problem may never happen. I'm not a big fan of introducing complexity to guard against code screwups in the same codebase.

The hardest bugs are the rare bugs. Common and frequent problems are easy bugs to fix. These subtle or rare changes are those which should be feared. If you model only that which you support, finding the source of the problem becomes much easier.

Re: Why static languages suffer from complexity

#70
post #37

Earlier quoted context omitted.

Yup, I find this completely insane behavior to think that you somehow benefit from types not being there. You just make it way harder for people to understand your code and contribute to it.

Oh yeah the easiest code in the world to read is some contorted type system and function signatures that look like hieroglyphics that you need a PHd in CS to comprehend. Python is easy to grok, and if you have programmers writing code like bar(foo,baz) then the problem is not Python. You can write crap in any language. Unit tests do much of what typing checks anyway ... and here's the thing ... you NEED unit tests no…

Typing allows you to specify the expected behavior in terms of input/output structure of algorithms in such a way that they can be statically verified without writing unit tests or manual checking code in the source, allowing your unit tests to check behavior by value rather than by value and structure. The equivalent of type checking is not unit testing, but fuzzing.

Python is not easy to grok at all, when you consider you have to grok implementations to understand what they are supposed to do, and require extensive runtime debugging to figure out if it is behaving as expected before you can even write unit tests.

Compare to decent statically typed languages, which have quicker write/debug cycles since checking type definitions is faster than checking code behavior, and the structural unit testing is covered automatically by the compiler.

It's like getting more than 50% of your programs' test coverage, for free!

Post reply on HN