What practically annoys you on a regular basis in programming languages?

Started by
70 comments, last by Dawoodoz 4 years, 6 months ago
59 minutes ago, Oberon_Command said:

It is unclear to me what would justify that feeling. The purpose of a style guide is to provide canonical answers to common questions regarding how to write the code to keep the programmers from arguing with each other and cut down on the cognitive burden incurred by interacting with the code via well-known conventions for common situations. If management (rather than tech leadership) is imposing the style guidelines, then they're doing style guides wrong, because the style guide should be driven by the developers, for the developers.

Nothing that complex goes into style arguments. Some coders want two-space soft-tab, others hard-tab or smart-tab. Some place "{" on new lines. Everyone could have their own preference without affecting coworkers if IDEs stop storing layout information with the code and get closer to the pure abstract syntax tree while feeling like editing text.

Advertisement
23 minutes ago, Dawoodoz said:

Nothing that complex goes into style arguments. Some coders want two-space soft-tab, others hard-tab or smart-tab. Some place "{" on new lines. Everyone could have their own preference without affecting coworkers if IDEs stop storing layout information with the code and get closer to the pure abstract syntax tree while feeling like editing text.

My experience is otherwise. Once the basic formatting rules are set, programmers will then proceed to argue over naming conventions, whether to use struct or class, whether to use type aliases, how deeply to nest namespaces, how to split related code into multiple files (and whether to do that in the first place)... I could go on at some length with more examples. My point is that "style" is a lot more than just formatting. :)

At work we don't have a written-out style guide. Instead, you are encouraged to modify code in the style of what's already there. Over time we have converged to a common style that we can all live with, although not every piece of code follows it uniformly.

 

Full disclaimer: I am not a game developer. I am a software developer.

I personally hate how many older programming languages have a ton of what feels like boilerplate. Love it or hate it, but one of the nicer things about Python is how much simpler it is to do basic operations. What would take 5 lines in Java is one line in Python. Now of course, Python has other issues...but this is something I liked about it. Golang seems like a happy medium between some of the newer features we see without sacrificing everything that older languages have. 

No one expects the Spanish Inquisition!

16 hours ago, Alberth said:

One of the problems in code is perhaps that we use identity as equality notion a lot, that is, mathematical equality is relatively rare. Perhaps a language should be created that by default has no equality at all.

Would introducing a === operator for this make sense in the context of C++?

10 hours ago, Kaetemi said:

Would introducing a === operator for this make sense in the context of C++?

That would be confusing for two reasons.

First, the masses of unwashed plebs who cut their teeth on Javascript would get hopelessly confused and those of us who provide support to C++ developers would strain our eye muscles with too much rolling activity and our cynicism would overflow onto the floor potentially causing undefined behaviour among the cleaning staff.

Second, the rocketship operator actually takes care of pretty much every equivalence need in C++; you don't need an equality operator any more.  Introducing a new equals operator to supplement the equality and rocketship operators with a disjunction of both sounds like something the standards committee would reject on the grounds that it would be too easy to write code with bad behaviour for no gain at all.

I mean, go ahead and suggest it.  Just don't make your expectation of acceptance too high.

Stephen M. Webb
Professional Free Software Developer

12 hours ago, Bregma said:

[snip] it would be too easy to write code with bad behaviour [snip]

I thought that was the whole point of C/C++. xD

According to the documentation the <=> operator has 4 different possible standard return types, with each 3 or 4 different possible values, of which two can be == 0. I guess they're aiming at a different level of confusion. :ph34r:

12 hours ago, Bregma said:

[snip] the masses of unwashed plebs who cut their teeth on Javascript would get hopelessly confused [snip]

So in my imaginary programming language, I'd need three operators to be precise. Equivalence, equality, and identity?

On 8/15/2019 at 10:39 AM, Oberon_Command said:

I agree on equality, that should be automatically generated and I've never been clear on why it isn't

If you have a structure that has a pointer to another structure, or a pointer to a pointer, or some other indirection... automatically generated equality could become some weird blend of equality and indirect identity.

Let's say I have two lists containing lists containing lists. Am I looking for

  • The two lists actually being one list? (Identity)
  • Two lists that contain the same collection of lists?
  • Two lists that both contain lists that contain the same lists?
  • Two lists that both contain lists that each contain lists with the same values? (Deep equality)

Equality and identity in itself already seem to be a non-binary property...

So we have the following situation in C/C++ (and a similar situation in Java):


char *a; // "hello world";
char *b; // "hello world";
int x; // 42
int y; // 42
a == b; // false
x == y; // true

Which is... coldly logical... but not intuitive.

However... assuming all hell breaks loose, and suddenly operators on pointers could be overloaded to allow for a more intuitive experience, we're no longer able to do the identity comparison there. Which would mean either explicit unoverloadable identity comparison operators, or a mechanism to get the original operator of a type, would be required in such case.

Another coldly logical but non-intuitive syntax oddity in many programming languages, and one that's extremely common in game development:


if (5 < x && x < 10) { }
if (5 < x < 10) { }

The second form is what everyone has already learned during primary school, but cold hard logic makes it expand to something that's absolutely useless, hence we're stuck with needing the first verbose syntax. There doesn't actually seem to be any technical reason why comparison operators couldn't be logically chained by a compiler though... (Just looked it up, and it seems Python actually implements comparison chaining, which is neat :))

4 hours ago, Kaetemi said:

If you have a structure that has a pointer to another structure, or a pointer to a pointer, or some other indirection... automatically generated equality could become some weird blend of equality and indirect identity.

I'd be fine with just automatically calling operator== on each member as the default. We already get that with the implicit copy constructor/assignment operators. If the default doesn't do what I want, I'll override it, but most classes I work with are just doing that, anyway. It's the most usual case and therefore should be the default and automatic one.

My assumption is that the standards committee, being highly concerned with the implementation of the standard libraries, often encounters cases where this is not the default situation. It seems to me that, in general, there is a distinct trend of the standards committee prioritizing library authors when adding new features and rules.

Or perhaps this is an aspect of the "zero cost abstractions" philosophy and the committee doesn't want to force (what I consider) the reasonable default on everyone on the grounds that it would be a default with potential runtime costs. But... we already have that, with copy constructors... And now I'm just speculating.

4 hours ago, Kaetemi said:

Let's say I have two lists containing lists containing lists.

My expectation here as a C++ programmer would be deep equality, because that's how the standard library types generally behave and how the vast majority of user types I have encountered in production code behave. If I wanted identity rather than equality, I would compare the pointers or similar - eg. handles, in cases where my data is double-buffered or relocatable. If you want to do something else in your own idiom, that's fine, that's why we have operator overloading, but in C++ I'm always going to expect a deep comparison and you should specifically tell me when the type is doing something different.

IMO operator overloading should be reserved for non-default cases and should not be required for holding the compiler's hand through the default ones.

4 hours ago, Kaetemi said:

Which is... coldly logical... but not intuitive.

It seems intuitive enough if you keep in mind that char* as "pointer to string" rather than "string value." I would further argue that this is the correct way to think of a char* and "a == b" in your example is the behavior that I would expect. :) 

4 hours ago, Kaetemi said:

Another coldly logical but non-intuitive

What's unintuitive or odd about this? It's certainly not always convenient, but the idea that comparison operators are binary (and more complex conditions are created by composing them) is a simple and clear one.

This topic is closed to new replies.

Advertisement