Live data from Hacker News

In defense of complicated programming languages

viralinstruction.com

211–220 of 379 posts

Re: In defense of complicated programming languages

#211
post #174
post #166

Earlier quoted context omitted.

Example from the article is a nice one. Now you want to make 100s of different dogs in your program and you want make them to bark at each other. You want to loop over all the dogs and feed them. You can make infinite loop that will check all the dogs and if one is hungry call Feed and if one is not then not. Learn what is the difference between Object and Class. You can create objects and let them live in your progr…

That's not very convincing. Why can't a "dog" be a perfectly ordinary data structure that you manipulate the usual way? while True: for dog in dogs: if dog["hungry"] == True: dog["lastfed"] = time() dog["hungry"] = False Okay, I hear you say, but the fact that a dog is an associative array is an implementation detail. Supposing I want to abstract that - don't I need objects then? No! Just define some functions: while…

If you don't have any imagination and you treat dogs as database entries then yes you might do just that. If you are only person writing it and using that code, the same.

You did not address interaction between dogs. Some other idea, how do you pass dogs to a playpen, how would they interact - maybe you want different playpens where you can send your dogs into, some playpens having food, some not having a food, different types of food. What if some other developer will have to write code to heal the dog? If function to dog.Heal() will be in some different module that you never heard of, how do you find it?

You don't want to make each playpen having "if species_of(pet)" code duplication, if pet alone can act on its own will.

Writing code in here seems not that useful here because you would really have to imagine possibilities and see how much code would go into wiring up such a world. Then seeing how having methods in object are helping organize code and in the end prevent whole classes of errors.

Building all of that as an example is just too much work for one off discussion. Just play with imagination of how much complexity you can add to a simple example and soon you will notice.

Re: In defense of complicated programming languages

#212
post #174
post #166

Earlier quoted context omitted.

Example from the article is a nice one. Now you want to make 100s of different dogs in your program and you want make them to bark at each other. You want to loop over all the dogs and feed them. You can make infinite loop that will check all the dogs and if one is hungry call Feed and if one is not then not. Learn what is the difference between Object and Class. You can create objects and let them live in your progr…

That's not very convincing. Why can't a "dog" be a perfectly ordinary data structure that you manipulate the usual way? while True: for dog in dogs: if dog["hungry"] == True: dog["lastfed"] = time() dog["hungry"] = False Okay, I hear you say, but the fact that a dog is an associative array is an implementation detail. Supposing I want to abstract that - don't I need objects then? No! Just define some functions: while…

> Why can't a "dog" be a perfectly ordinary data structure that you manipulate the usual way?

In statically typed languages, it's easier to read data out of a struct with fixed types, than a map[string]any and convert it to the expected type on each access.

> So you end up with an abstract type (dog) and a bunch of functions that operate on that abstract type.

C has no multiple dispatch and no classes. So libraries based around opaque objects (GTK and ALSA etc.) prefix each function name with its struct name, which is verbose and gets tedious to read or write after a while. Is multiple dispatch possible in a statically typed languages with compile-time nonvirtual function resolution? I haven't looked into it, it might be possible.

Re: In defense of complicated programming languages

#213
post #102

Earlier quoted context omitted.

Just try, my pretties, just try to understand how exception handling actually works without staring at a lot of assembly.

Ah, doesn’t it just fly over to the nearest “catch”? Btw, the worst misunderstandings I’ve seen were not lacking knowledge, they actively believed in some magic that isn’t there if you dig deeper. That’s why I still think that teaching at least basic assembler is necessary for professional programming. It can’t make you a low-level bare metal genius, but it clears many implicit misconceptions about how computers real…

Stack unrolling is a complicated process.

It's tempting to think of them as a kind of return value, but most languages do not represent them this way. (I believe it's a performance optimization.)

Flying to the nearest catch can also be complicated, as it's a block, that involves variable creation, and this possible stack changes. Again it's easier to model as a normal block break and then a jump, but that's not the usual implementation.

Re: In defense of complicated programming languages

#214
post #193

One difficult thing to accept in programming language design is that what mathematically is simple, consistent, and straightforward is not simple, consistent, or straightforward to people. For example, a simple, consistent, and straightforward expression syntax would be RPN (Reverse Polish Notation). But humans dislike, and much prefer infix with its complicated operator precedences. The real trick to programming lan…

Rust has this problem with its module system. It has top-level "items" that can be functions, types, global variables, …or modules. The way modules are defined and imported is consistent with defining and importing of named structs and functions. But every new user is totally confused about this (I'm not even sure if my explanation above will be understood), because everyone expects modules to be a special case of im…

Rust has a mod declaration tree and a use import graph.

Re: In defense of complicated programming languages

#215
post #194

There's a distinct difference between complexity and complication, which I think is what the author is looking to convey. Complexity is just inherent to the system you are building. The only way to decrease complexity is to do less. Hiding it only moves it somewhere else. There's a whole school of thought around the idea of reduced functionality, and in fact it's baked into the UNIX ethos of "do one thing well". Comp…

I generally agree with you (with the addition of it being often referred to as essential (which is non-reduceable) and accidental complexity=complication in your words). May I ask you why do you think Java is an example of adding features it was not designed to have? In my opinion, even with the original warts of the language, it is one of the few long-running languages that managed to withstand adding every feature…

Generics were a necessary thing, but the type erasure is a huge problem, and unfortunately one that can't be fixed without a completely new bytecode format. Also, annotations, while a necessary thing to bring it up to speed with modern practices (such as nullability contracts), add to the bureaucracy of Java and make it more painful to work in.

Don't get me wrong; I do like Java, and have written hundreds of thousands of LOC in it over my career. But there's only so much it can do without breakage, and only so much that can be papered over and worked around. Even Kotlin suffers from the JVM it rests upon.

Re: In defense of complicated programming languages

#216

Earlier quoted context omitted.

> I understand this thought process, but in my opinion it's the wrong way to think about software concepts. You cannot really tell someone that the way their brain learns is the "wrong way". Different people's brains are wired differently and thus need to learn in different ways. > Understanding what a bridge is doesn't mean knowing how to build one, and in fact tying your understanding to a certain implementation of…

I like to understand the construction too, it's why I'm in engineering. I'm just saying it shouldn't be necessary in order to understand an idea. For me, it was a crutch I used for years before I grokked how to decouple interfaces from implementations because I naturally understand things better after I build them. But if you use an implementation to understand an idea, you couple implementation to interface in your…

> I'm just saying it shouldn't be necessary in order to understand an idea

Nobody said it is necessary. Some folk just said they find it easier learning this way.

> But if you use an implementation to understand an idea, you couple implementation to interface in your mind, and so it changes your understanding.

That's a risk either way. It's a risk that if you only learn the high level concept you miss the detail needed to use it correctly in a specific language too (OOP can differ quite significantly from one language to another). And it's also a risk that then when you learn that detail you might forget the high level abstract and still end up assuming the detail is universal. If we're getting worried about variables we cannot control then there's also a risk that you might just mishear the lecturer or read the source material incorrectly too. Heck, some days I'm just tired and nothing mentally sinks in regardless of how well it is explained.

There are an infinite ways you could teach something correctly and the student still misunderstand the topic. That's why practical exercises exist. Why course work exists. Why peer reviews exist. etc.

And just because you struggled to grasp abstract concepts one specific way it doesn't mean everyone else will struggle in that same way.

Re: In defense of complicated programming languages

#217
post #41
post #17

> In video game design there is a saying: Show locked doors before you show a key This is something I've tried putting into words many times. I'll try to solve a problem and get to know its challenges deeply. Then a tool is introduced that brings it all together. In these cases, I seem to quickly get a full grasp of the operation and essence of the tool. I wish education was based around this principle. A bit like wh…

That's because the use case for classes appears when the information needed to understand the program exceeds the programmer's working memory. At some point, you need some way to make something into a black box whose innards you do not need to understand when not working inside the black box. Languages which do this badly do not scale well. This is a hard problem. We have, at least, structs, classes, objects, traits,…

> At a higher level of grouping, we have more trouble. This is the level of DLLs, microservices, and remote APIs. We barely have language for talking about that. We have no word for that level of structure. I sometimes refer to that as the "big object" level. Attempts to formalize that level have led to nightmares such as CORBA, XML schemas, and JSON schemas, and a long history of mostly forgotten interface languages.

Here I would like to think TLA+ would help. But it seems it doesn't either.

Re: In defense of complicated programming languages

#218

Earlier quoted context omitted.

Is there really no demand? Or do those of us who like to learn that way just get used to researching these things ourselves so quietly get on with it. Many of the existing tutorials are at least a good starting point to teach engineers what topics they need to examine in more detail. Anecdotally, when I've mentored juniors engineers I've had no shortage of people ask me "why" when I've explain concepts at a high leve…

There’s a difference between understanding something and learning how and why it works the way it does. You can understand how a compilation pipeline works never working with any low-level code and never writing a compiler yourself. You can walk across a bridge and understand it connects point A with point B and don’t understand how a specific bridge has to be constructed. A concrete implementation is just an impleme…

> you’ll get tunnel-visioned instead of understanding the concept behind it

You might have gotten tunnel-visioned but it's not a problem I've suffered from when learning this way. And why do you think I cannot understand the concept behind the code after reading the code? If anything, I take the understanding I've grokked from that reference implementation and then compare it against other implementations. Compare usages. And then compare that back to the original docs. But usually I require reading the code before I understand what the docs are describing (maybe this is due my dyslexia?)

Remember when I said everyone's brain is wired differently? Well there's a lot of people today trying to tell me they understand how my brain works better than I understand it. Which is a little patronising tbh.

Re: In defense of complicated programming languages

#219
post #194

Earlier quoted context omitted.

I generally agree with you (with the addition of it being often referred to as essential (which is non-reduceable) and accidental complexity=complication in your words). May I ask you why do you think Java is an example of adding features it was not designed to have? In my opinion, even with the original warts of the language, it is one of the few long-running languages that managed to withstand adding every feature…

Generics were a necessary thing, but the type erasure is a huge problem, and unfortunately one that can't be fixed without a completely new bytecode format. Also, annotations, while a necessary thing to bring it up to speed with modern practices (such as nullability contracts), add to the bureaucracy of Java and make it more painful to work in. Don't get me wrong; I do like Java, and have written hundreds of thousand…

Why do you think type erasure is problematic? Haskell and basically every language absolutely gets away with type erasure so it really shouldn’t pose a serious problem, other than for reflection usages which are rare.

Re: In defense of complicated programming languages

#220
post #119
post #102

Earlier quoted context omitted.

Ah, doesn’t it just fly over to the nearest “catch”? Btw, the worst misunderstandings I’ve seen were not lacking knowledge, they actively believed in some magic that isn’t there if you dig deeper. That’s why I still think that teaching at least basic assembler is necessary for professional programming. It can’t make you a low-level bare metal genius, but it clears many implicit misconceptions about how computers real…

From the assembly one can learn what compilers do. But it cannot teach how modern CPU actually work. I.e. even with assembly reordering, branch prediction, register renames, cache interaction etc. are either hidden from code or exposed in a rather minimal way.

Right, in particular this is vital for Concurrency. In the 1990s my class about multi-tasking began by explaining that the computer can't really do more than one thing at a time. But in 2022 your computer almost certainly can do lots of things at the same time. And your puny human mind is likely not very well suited to properly understanding the consequences of that.

What's really going on is too much to incorporate into your day-to-day programming, and you'll want to live in the convenient fiction of Sequential Consistency almost all the time. But having some idea what's really going on behind that façade seems to me to be absolutely necessary if you care about performance characteristics.

Post reply on HN