Live data from Hacker News

Programming Idioms

programming-idioms.org

61–70 of 99 posts

Re: Programming Idioms

#61
post #36

Earlier quoted context omitted.

For me the strlen call appears directly before loops backwards jump when set to -O0, resulting in a call every iteration as far as I can tell. However -O1 already seems to optimize it to a single call at the start of the function.

I find it every time funny that when using languages that want to give you "total control" over the execution of your code (mostly C/C++) you actually almost never know what code gets executed in the end. It depends on the compiler, it's version, it's flags, and likely "the position of the moon". Of course the compiler is only allowed to do transformations that the spec permits. But it's impossible for a human being…

I think what matters is the intent. Here the intent is to compare against strlen at every turn of the loop.

When the compiler is optimizing it might very well realize that the parameter to strlen doesn't change and the output can be saved first.

If the intent is to compute the length only once, then we can save the length in a variable.

Of course; as others have pointed out; there is no need to call strlen at all in this example.

Re: Programming Idioms

#62
post #12
post #7

The random idiom I got was: > Idiom #120 Read integer from stdin > Read an integer value from the standard input into variable n int n[15]; fgets(n, 15, stdin); Really?

The longer I look at this example, the more weirdness I spot: - There are no standard integer types that take 15 (decimal) digits to represent. - The array contains ints instead of chars - Why would you use fgets() instead of just gets()? (Though I don't touch C very often so perhaps that is considered proper style) - Obviously no conversion of the digits into else, let alone specifying a base or handling a `0x` pref…

> There are no standard integer types that take 15 (decimal) digits to represent

Nitpick: that is irrelevant. The code reads in at most 14 characters.

> Why would you use fgets() instead of just gets()?

You don’t use gets because it doesn’t exist anymore. It got removed in C11 (it rightfully was deemed so bad that backwards compatibility was sacrificed). You can use

  char *gets_s( char *str, rsize_t n )
, though.

(https://en.cppreference.com/w/c/io/gets)

Re: Programming Idioms

#63
post #35
post #7

The random idiom I got was: > Idiom #120 Read integer from stdin > Read an integer value from the standard input into variable n int n[15]; fgets(n, 15, stdin); Really?

Just wait until this gets rolled into GitHub Copilot...

What? You dare criticizing the concept of coding-AI trained on random code found on the inter-webs?

But that's the future of programing! Just ask Microsoft or JetBrains.

Soon, with the help of AI, any random dude will be empowered to write software!

Big layoffs are to be expected as AI will take over most of the high-paying jobs in the software industry.

Belief me. /s

Re: Programming Idioms

#64
post #43

Earlier quoted context omitted.

Good news then, it’s also linear time like the marginally faster but enormously grotesque for loop provided previously. I would take that clarity of intent a hundred times over squeezing a couple of comparisons out.

> it’s also linear time You raise an interesting point. It got me thinking about how big-O notation has failed us in some ways: it teaches us to ignore constant factors. In big-O, an algorithm that makes 1000 comparisons per element is no different from one that makes a single comparison per element. They are both linear time. But you can't deny that one of these will likely take 1000 times as long as the other. Of c…

I think big-O makes sense as a kind of filter for the truly bad solutions.

When you have some big constant factor that's not good.

But when you have a big exponent that's not workable anymore, even for smallest input.

Re: Programming Idioms

#65

Earlier quoted context omitted.

It's not unreasonable to assume the compiler will optimize it to a single call. Though I guess people who are capable of making that judgement won't need to look this idiom up on the internet.

We don't write code only for compilers, but for human readers as well. Why write code that makes a smart human wonder "Is that going to be quadratic? I'd better make sure the compiler optimizes it out!"

Smart human for you, someone obsessed with micro-optimization but lacking knowledge of compiler optimizations for me..

Writing it for human readers can be used to argue for the original implementation if you think of for(i=0;i<expr;i++) as the C idiom for "iterate expr times" and here you want expr to equal the length of the string, which is what the (obviously pure) function yields. No unnecessary variables and assignments -- no clutter. It perfectly describes the intent.

Re: Programming Idioms

#66
post #16

Earlier quoted context omitted.

Not to mention that proper idiom for this task would be: int n = strspn(s,"0123456789"); BOOL b = (s[n] == 0);

That is nice and simple, but it makes ten comparisons for each character in s, where only two are needed. Of course it would be a good approach if the set of characters you're testing against is not contiguous, unlike 0..9.

Correct, but we're talking about "idiomatic" not "most efficient" solution. Input validation is usually not time-critical, and for these cases the code clearly showing the intent is much better than optimal one.

Re: Programming Idioms

#68
post #34

I see a lot of people taking issue with the idioms presented, and rightfully so in many cases. Add the ability for people to improve or debate the solutions. Ultimately we should have a large curated cookbook (with additional variant selections and associated recipe variants). The most important human element of programming is knowing what to build (and what pieces to build to make the bigger thing). How often do I h…

For the languages that have considerable feature velocity (so let's say I'll include even C++ and Python there but not C) you'd want to have a way to update idioms to match the current language. You might in some cases want to split out a previously idiomatic solution too.

For example IntoIterator wasn't defined for Rust arrays, and then one day Rust 1.54 implemented IntoIterator on arrays (and hacked things so that this doesn't cause old code to do something unexpected, Rust 2021 will remove that hack since old code wouldn't claim to be Rust 2021, thereby unlocking the new behaviour for syntax that once meant something different). Anyway this changes the idiomatic way to do various trivial array operations, since previously you'd have created a reference to the array, that has IntoIterator so that you can iterate it. That still works, but it's no longer idiomatic.

  for &x in &[2, 4, 6, 8, 10]   /* needed until 1.54 */

  for x in [2, 4, 6, 8, 10]   /* makes more sense */

Re: Programming Idioms

#70
post #36

Earlier quoted context omitted.

For me the strlen call appears directly before loops backwards jump when set to -O0, resulting in a call every iteration as far as I can tell. However -O1 already seems to optimize it to a single call at the start of the function.

I find it every time funny that when using languages that want to give you "total control" over the execution of your code (mostly C/C++) you actually almost never know what code gets executed in the end. It depends on the compiler, it's version, it's flags, and likely "the position of the moon". Of course the compiler is only allowed to do transformations that the spec permits. But it's impossible for a human being…

I guess that's true. Calling an expensive function effectively in the body of a loop like in this example is going to be an issue in every language.

It is difficult to optimise because you need the compiler to evaluate and prove at compile time that both the loop cannot affect the result of the function call and the function call will not affect the loop.

It's a common and easy optimisation to simply move function calls like this out of the loop.

For the cost of 1 line of code I've regularly seen 10%, 100%, 1000% speed ups.

It's actually one of the most common optimisations to do in non-compiled / "slow" languages if you know how functions are evaluated, you see that the cost of a simple getter function call can be the most expensive part of a loop.

Post reply on HN