Hacker News new | ask | show | jobs
by VulgarExigency 7 days ago
I can't, as my employer owns the code, not me, but there are several examples in one of the Ruby codebases I unfortunately maintain where I can see this degeneration happen via the git history. A small 8 line method with just two parameters slowly grows in complexity over time, until one day one of the original parameters supports two different shapes, and later on it's not that easy to understand which shape it should have in the specific conditional branch you're trying to fix, and the last person to touch that code left the company 4 years ago.

The fault, of course, ultimately lies with the people who wrote and approved this nonsense, but types, or at least type hints, help to avoid this issue.

2 comments

Can you point to it? That doesn't sound like "the language forced all this extra baggage on it due to 'safety'" so much as the developers kept adding functions to the function without rethinking if and how they should.
My point was not about the safety of the code, it was about the expressiveness, which is also what the comment I replied to was about. If the parameter has an explicit type (instead of no type, as is normal in Ruby, or `void*`, which is the C equivalent), it forces the developer to consider the design of the function, instead taking the path of least resistance because they're inexperienced/incompetent/a large language model/burnt-out to the point where even the thought of opening the file makes them feel the not-anxiety of burnout/<insert reason here>.
> instead of no type, as is normal in Ruby, or `void`, which is the C equivalent*

“void *” is not the equivalent of “no type” from Ruby. “void *” says “I operate on raw memory”. It says exactly the same thing as “byte *”.

For sure you should generally not write a function that accepts a “void *” and then internally casts it to some concrete pointer type and operates on that type, but the problem there is the internal behavior, not the choice of byte vs void pointer.

Forcing developers to consider and more is harmful though. You're arguing to put all of the forethought upfront, when you have the least context and least understanding of what can go wrong, and carrying that complexity forward rather than starting simple and refactoring over time.
You’re really citing a mess in a Ruby code base caused by lack of typing as evidence for why void * is problematic in C/C++?

These are so wildly different cases that the comparison isn’t meaningful. This is like saying you should wear a helmet while playing tennis because sometimes helmets save bicyclists lives.

> You’re really citing a mess in a Ruby code base caused by lack of typing as evidence for why void * is problematic in C/C++?

If you read GP's post you'll understand it exemplifies exactly the issue that the likes of (void *) present in C.

I mean, read the message, particularly this:

> later on it's not that easy to understand which shape it should have in the specific conditional branch you're trying to fix

That is exactly the purpose of void *. By design. It's a pointer to an unspecified type. The unspecified type is exactly why this thing is used.

> later on it's not that easy to understand which shape it should have in the specific conditional branch you're trying to fix

This is not idiomatic C. I have no doubt that someone (likely many someones) have written a function that takes a void * and then internally does some insane half baked dynamic typing. But I’ve never seen it and it’s not common.

You also cannot fix this behavior by changing the pointer type. The type of the pointer is essentially meaningless in this case.

> That is exactly the purpose of void *. By design. It's a pointer to an unspecified type. The unspecified type is exactly why this thing is used.

This is also the purpose of byte * in the examples. Coercing an arbitrary pointer from void to byte doesn’t accomplish anything. It’s lipstick on a pig at best.