Live data from Hacker News

Simplistic programming is underrated

lemire.me

51–60 of 93 posts

Re: Simplistic programming is underrated

#51
post #7

I agree that overcomplicating code is bad, but then again, what is "simplistic"? Let's talk Python. To me, using comprehensions is way simpler than loops. Using for i, item in enumerate(my_list): # do some stuff with i and item is way simpler than for i in range(len(my_list)): # do some stuff with i and my_list[i] And still, I bet that most C/Java folks will look at these things with disdain. Also, higher-order funct…

You probably want to use the conceptually simplest construct your language / standard library offers. In Python that's enumerate. In C, that'd be the standard for loop. In Java that'd be the enhanced for loop. People reading your code, familiar with the language, should have to learn as little as possible to understand it.

I could make an awful enumerate implementation in C:

    #define enumerate(item, array) for (int i = 0; i 
...But then everyone reading it would have to go read my enumerate definition, whereas they'd understand the regular for loop immediately.

I think higher-order functions are a great tool when they're used to remove complexity. The tricky part is that your reader needs to already understand how they work. If adding the definition of a higher-order function would make your code longer than simply not using it, I think it's a bad case to use it.

Re: Simplistic programming is underrated

#53
post #18

Earlier quoted context omitted.

> Except the over head of that loop is orders of magnitude higher than the reduction. Except that it's not. Read the SO answer I linked. > The nooks for bugs in your "simple" loop are so profound that, in a language with expressive maps, I wouldn't accept that code in a review. Yep, I've definitely worked with people like you. With all due respect, I just think you're fundamentally wrong. Off-by-1 errors will happen…

Off by one errors can't happen in the functional version. There's no reason to take a fatalist stance here. Just saying "well those programmers should write more tests" is silly when you could say, well why not tests and write code that is naturally hardened against foot guns. I was referring to mental overhead; though in a more modern language like rust the performance implications would be far less profound than th…

> Off by one errors can't happen in the functional version.

No? Not only can they happen, but I'd argue that it's easier for them to occur when using `reduce`, because you have to remember the initializer. Omitting it has no effect in the given example, but the given example is contrived. It's not rare to be dealing with something more complex than a list of numbers, so let's try that instead.

Let's say your items are a list of nodes. You want to sum their payloads to determine their aggregate cost. And, like kgwxd[1], you see `map` as superfluous. You've got this. You write:

    nodes.reduce((sum, x) => sum + x.value)
Uh-oh. Now the fact that there is no initializer does affect the result.

1. https://news.ycombinator.com/item?id=15867033

Re: Simplistic programming is underrated

#54
I don't think it's underrated; it's that it's hard to write.

You almost go full-circle. You start off writing highly procedural code (with too much branching), join the GOF-all-the-things religion and eventually revert to highly procedural code (more specifically "algorithmic code" or "functional code").

As an example, many years ago I wrote a dependency resolver. It needed to find cycles (as we had some rules that could resolve those cycles) in order to make changes in the correct order. At the time I was a junior developer in that problem space. My solution consisted of an O(scary) algorithm; consisting of classes, patterns and all the good things that make your code "simple" and "understandable" (it was not). Customers eventually threw graphs with a few million edges at it and we needed a new solution. I have no idea how I happened upon Tarjan's Strongly Connected Components Algorithm but some hundreds of lines of code was replaced with dozens. Minutes turned into milliseconds.

Here's the thing about simplicity: even though the code was simple, even I (as the author) didn't understand it at the time - I trusted the guy with the PHD. Many years later I finally understand how it works. It is an incredible masterwork of simplicity but as it turns out something that is simple is not always understandable.

Simplicity probably has a simple definition in the dictionary, but in practice it can be quite complex to make something simple. So you can't just say "make your code simple" because it's really hard to do that.

Re: Simplistic programming is underrated

#55
post #50

Simple vs. non-simple isn't the best way to think about code. Rather I would think about the requirements of the code. Who is going to be reading it? Maintaining it? Do advanced language features give some kind of advantage (runs faster?, less likely to have bugs?, more extensible?). Will new team members likely introduce bugs? Is spaghettti code better or worse than using less known patterns/language features? Don't…

The whole idea of calling functional features advanced language features is a bit ridiculous I think. Yes, something like java only recently started supporting functional programming, but the paradigm has existed for a very long time.

For me it is how those functional features are used that one needs to be careful of. I like the idea of the code that you read and think "yep that's right", rather than - OK I need half a day and a whiteboard to understand this.

However the exact same piece of code might be wrong in one team, and right for another, depending on their experience and backgrounds.

Re: Simplistic programming is underrated

#57
post #7

I agree that overcomplicating code is bad, but then again, what is "simplistic"? Let's talk Python. To me, using comprehensions is way simpler than loops. Using for i, item in enumerate(my_list): # do some stuff with i and item is way simpler than for i in range(len(my_list)): # do some stuff with i and my_list[i] And still, I bet that most C/Java folks will look at these things with disdain. Also, higher-order funct…

The first is Pythonic code. I'm guessing the author isn't talking about conventional code, but a more agnostic point of creating complexity for complexity sake, which, unfortunately, is a very common issue. The other way can also be a problem. If you are manually writing out range(len(stuff)) in Python on all your loops, you are writing code that is complicated, overly verbose, difficult to understand, and error-pron…

Actually I don't think he was successfully making that agnostic point.

It's more like: don't gold plate it, and don't use abstractions that you learnt later.

Not gold plating things seems obvious. I think there's a TDD advocate who has an example of when he created a wiki that stored its data in a text file. Purely by accident. But it worked perfectly for his use case; he didn't actually need to fire up the latest distributed NoSql blah blah blah. And perhaps that's something worth considering.

Not using abstractions learnt later in life tho. I think that's a problem. It took me years of contorting my head to fit in some of the customary Haskell abstractions like monads and functors. Today I probably couldn't describe them accurately, but I'm sure I benefit from when I think in terms of them. For instance, it seems that the code is better if I write a method which accepts an object then does something, vs writing a method which might accept an object, then tests for null, and if not null it does something. (And similarly for looping constructions for instance. You write a more superficial level of code that knows about nulls or arrays and a deeper level of code which doesn't. Directly thinking "monad" literally helps me here.) It's simpler, but it's not at all more simplistic.

And so at this point, I want to distinguish between complex/complicated and simple/simplistic. Things which are complicated or simplistic are bad because they're simpler or more complex than they should be. Things which are complex or simple are inevitable and complaining about them is unproductive, like complaining about the weather.

Re: Simplistic programming is underrated

#58
post #54

I don't think it's underrated; it's that it's hard to write. You almost go full-circle. You start off writing highly procedural code (with too much branching), join the GOF-all-the-things religion and eventually revert to highly procedural code (more specifically "algorithmic code" or "functional code"). As an example, many years ago I wrote a dependency resolver. It needed to find cycles (as we had some rules that c…

Simplicity is the answer without the question.

Re: Simplistic programming is underrated

#59
post #54

I don't think it's underrated; it's that it's hard to write. You almost go full-circle. You start off writing highly procedural code (with too much branching), join the GOF-all-the-things religion and eventually revert to highly procedural code (more specifically "algorithmic code" or "functional code"). As an example, many years ago I wrote a dependency resolver. It needed to find cycles (as we had some rules that c…

I agree. There seems to be two interpretations of "simple" - simple in being concise like that of a beautiful mathematical equation, or simple in being easy to follow and understand. I assume the latter is preferable when factoring in having other pairs of eyes reading/maintaining your code, especially since the latter does not always imply less efficient code

Re: Simplistic programming is underrated

#60

Earlier quoted context omitted.

Off by one errors can't happen in the functional version. There's no reason to take a fatalist stance here. Just saying "well those programmers should write more tests" is silly when you could say, well why not tests and write code that is naturally hardened against foot guns. I was referring to mental overhead; though in a more modern language like rust the performance implications would be far less profound than th…

> Off by one errors can't happen in the functional version. No? Not only can they happen, but I'd argue that it's easier for them to occur when using `reduce`, because you have to remember the initializer. Omitting it has no effect in the given example, but the given example is contrived. It's not rare to be dealing with something more complex than a list of numbers, so let's try that instead. Let's say your items ar…

> No? Not only can they happen, but I'd argue that it's easier for them to occur when using `reduce`, because you have to remember the initializer.

I would say that's not an off by one error. Its a similar scale and type of error, but not the same.

Post reply on HN