Live data from Hacker News

In defense of complicated programming languages

viralinstruction.com

31–40 of 379 posts

Re: In defense of complicated programming languages

#31
I cut my programming teeth on Fortran, C, and Smalltalk, all semi coincidentally in my early formative years of programming (well there was also a pile of Lotus123 macros where I discovered that 640K was not enough (thanks a lot Gates) and invented something that years later I would realize was a swap space).

Fortran seemed easy, C was similar, but my mentor wanted to impress me using strtok() in the middle of already existing strings to cut them into words. And like the author, I had my “uh… what?!?!” moments climbing the Smalltalk curve.

Smalltalk was transformative for me. Unlike the author’s experience, I learned an object oriented philosophy in a pretty thoroughbred environment.

The best way to learn a second spoken language is to immerse yourself in it. Wanna learn Norwegian well? Go live in Norway for two years.

Unfortunately, while the hype around Smalltalk and some of its other peers rose, it forced others to “add/borrow” OOP into their philosophies.

Classes were not the heart of OO in the Smalltalk-verse. The root proto class in many implementations was called Behavior. The whole gig in Smalltalk was binding behavior to data. Figure out where a good cohesive boundary for data that glumps together well and dress it up with behavior. You then excited your objects to, well, uh, behave. Or in the lingua Franca, you sent messages to them and they always responded with something. And that was pretty much the whole schtick. I found it a very useful system for modeling things around for me. More than any language since, I found I anthroporhized these behaviors a lot. Algorithm design was often a sort of “if I assigned different people in a room to represent different pieces of state, what would they say to each other to get the job done.”

This is where my take deviates from the article. What was liberating about this, was that they kept it simple and stuck to this. In Smalltalk you might ask, well, what’s a class? It’s an object. But in most other OO systems, something happens here. Usualky, first class classes don’t exist. Or they do kinda. But often, it’s another area of the language you have to learn to specify behavior taxonomies. It’s like two different languages.

How do you create an instance of a class. In Smalltalk, you sent a message to it. Because that’s what you did. You sent friggin messages! But in just about every other OO system, you now get to learn about constructors. Are they like messages/functions? Kinda. But they’re different. Do you express and invoke them like messages? See “kinda.” Separate sub language count now equals three.

What about math? Gotta do that the way you learned how to do it in school. Precedence rules. But in Smalltalk, you sent a message.

Meta programming? Send more messages. Control flow? Send messages. Looping? Send messages. Functional style collection traversal? Send messages.

This isn’t meant to be a Smalltalk love fest. I moved on 10 years ago. But what frustrates me is that people refer to Algol derived languages as object oriented. Most of them aren’t. They’re object-additive. And functional-additive. They’re 10s of language ideas and syntaxes balled up in one, little bits of syntax competing for contextual disambiguation. They’re complicated for all the same reasons that while Spanglish is appealing to a wide body of English and Spanish speakers, you’d go nuts trying to put down a formal definition of how to speak it.

OO isn’t why languages are complicated.

Re: In defense of complicated programming languages

#32
The crucial crux of this is whether the complexity is worth its weight. Different programmers will disagree, not least of which because this is tightly bound to how you prefer to think about programming. Moreover, what seems complex to one person might seem entirely straightforward to another.

However, at the end of the day my personal worry is that the central thesis of the article is often inverted. A complicated programming language might not tame complexity within itself, rather it may instead breed even more complexity in its community and the code that is written in it. That complexity spirals ever more outward as new features grow that attempt to tame the complexity, but only add to the growing morass.

This is not necessarily true, but I've seen it happen often enough that I'm very wary of how new features in a programming language interact with each other.

Re: In defense of complicated programming languages

#33

A language with a short learning curve is like a toolbox that’s nearly empty. You quickly run out of ways it could help you. We should optimize for experts, because that’s where each of us is going to spend most of his career.

> A language with a short learning curve is like a toolbox that’s nearly empty. You quickly run out of ways it could help you.

Very quotable!

That's why I like it when languages allow you to start writing simple code and gradually make it more complex. Haskell for example is not like that. Python does better here. I think Scala is one of the best languages in that regard.

Re: In defense of complicated programming languages

#34

    def bark(dog_dict):
        print("WOOF!" if dog_dict["weight_kg"] > 25 else "Woof")

    rex = {"name": "Rex", "weight_kg": 35}
This code is actually better, but it would even be better with structs and traits

https://gist.github.com/rust-play/ceb5a292a22e55e27d56a83253...

We separate the concept of a Dog, the concept of something that barks, and the actual implementation in this case

We also don't immediately print it, but just return a slice so you can print it later or pass it to another function

It's a bit longer than the class example, but conceptually cleaner because multiple structs can implement the trait, some of them without a weight

and of course I'm only going to print things in my main, the interface only returns a slice which can be passed to other functions

Re: In defense of complicated programming languages

#35
post #4

Earlier quoted context omitted.

Is it possible to optimize too much for experts, and sacrifice learning curve too much?

C++ before 2011 springs to mind. From "Direction for ISO C++"[1]: "C++ is expert-friendly, but it cannot be just expert-friendly without losing important streams of new talent. This was the case before C++11 and C++11 reversed that negative trend." [1]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p200...

I do rather wish C++ 11 was a blank slate for that reason. Not really, as that'd kill C++, but there's so much good about C++ that is held back by its backwards compatibility with C and the dark ages of pre-11 C++. Data types and features are intended as best practice, but it's stuffed away in libraries since it can't replace the core of the language.

Re: In defense of complicated programming languages

#36
post #34

def bark(dog_dict): print("WOOF!" if dog_dict["weight_kg"] > 25 else "Woof") rex = {"name": "Rex", "weight_kg": 35} This code is actually better, but it would even be better with structs and traits https://gist.github.com/rust-play/ceb5a292a22e55e27d56a83253... We separate the concept of a Dog, the concept of something that barks, and the actual implementation in this case We also don't immediately print it, but just…

Missing the point.

If you read just a little farther, you get that extra apparatus has a purpose that is opaque to beginners, that just adds confusion.

Re: In defense of complicated programming languages

#37
I remember first encountering classes. I simply could not understand what they were from reading the documentation. Later, I picked op Bjarne's C++ book, read it, and could not figure out what classes were, either.

Finally, I obtained a copy of cfront, which translated C++ to C. I typed in some class code, compiled it, and looked at the emitted C code. There was the extra double-secret hidden 'this' parameter. Ding! The light finally went on.

Years later, Java appears. I couldn't figure that out, either. I thought those variables were value types. Finally, I realized that they were reference types, as they didn't need a *. I sure felt stupid.

Anyhow, I essentially have a hard time learning how languages work without looking at the assembler coming out of the compiler. I learn languages from the bottom up, but I've never seen tutorials written that way.

Re: In defense of complicated programming languages

#38
>>"Focus on debugging your application rather than debugging your programming language knowledge."

>Why would I want that? The entire point of modern language complexity is to reduce the amount of debugging needed for your application, because its complexity is properly managed by the language.

The difference is that applications are always particular and specific to a problem. Moving mechanisms from the application towards the language, which unless domain-specific, is a general purpose tool, does not guarantee reduction in complexity. If a language restricts me from writing a program, the language says "what you want to do is so bad, we must eliminate it for the entire userbase of the language!". This is a very tall order. Very few restrictions are so universal in their application that they apply any program a user would want to write.

The author posits the hypothetical that Zig's lack of manual memory management creates more runtime crashes, but it is just that, a hypothetical. It depends on the application and the use case, and the individual developers. And it comes for example at the cost of performance in a situation where the developer wants to manipulate memory manually and is willing to take the risk of introducing errors.

Strict language features restrict the ability of developers to deal with problems as they see fit. It's a form of top-down design that assumes that general solutions are effective at addressing particular problems. One can argue for example that syntax-heavy languages are much more clear and uniform but they are also restrictive. Lisps give developers directly much more power, but may come at the price of providing fewer guarantees.

Personally I'm not a fan of overbearing languages. Features and guarantees the languages provide have trade-offs. In some situations they may not be worth it and at the end of the day I have problems that a language designer cannot have anticipated because they're relevant to me, and I want the freedom to address them as I see fit. If a tool is inappropriately heavy-handed it turns from being useful into being restrictive, and it makes my job harder, not easier.

A practical example for me is program correctness. I much prefer an extensible tool like clojure.spec, which lets me add guarantees as needed, over a very harsh type system built into the language. If a type system eliminates valid programs that I deem appropriate, it adds complexity for me.

And a last point, I focus on restrictions in terms of 'complications' rather than features because one can always omit using a feature of a language, but has to abide by its restrictions.

Re: In defense of complicated programming languages

#39
post #36
post #34

def bark(dog_dict): print("WOOF!" if dog_dict["weight_kg"] > 25 else "Woof") rex = {"name": "Rex", "weight_kg": 35} This code is actually better, but it would even be better with structs and traits https://gist.github.com/rust-play/ceb5a292a22e55e27d56a83253... We separate the concept of a Dog, the concept of something that barks, and the actual implementation in this case We also don't immediately print it, but just…

Missing the point. If you read just a little farther, you get that extra apparatus has a purpose that is opaque to beginners, that just adds confusion.

I'm responding to

> And so they would have accidentally re-introduced classes, only this time the existence of classes would have been implicit in the code, and their behaviour ad hoc defined, their invariants spread all over the source files, and with no language-level tooling or introspection to help the programmer. Classes would still exist, but as implicit patterns.

You don't need to do this with classes, my design is better than the class design because it's more flexible

Re: In defense of complicated programming languages

#40
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 language design is finding those constructs that are simple, consistent, and straightforward for users.

Post reply on HN