Why doesn't Zig have an unary + operator?

Except that it isn’t harmless. And very definitely not all languages support it.

Look at the grammar twisting that Rust does to support unary minus. Rust consequently does not support unary plus.

Grammar parsing is a very complex dance of giving enough power to enable lots of programs while still having your tooling be able to work quickly.

1 Like

It is justifiable to ignore something that is not a solution.

2 Likes

Languages which can parse unary -, can easily parse unary +.

You can parse it as,

unary_expression:
  | PLUS x=expression; { UnaryAddExpression(x) }
  | MINUS x=expression; { UnaryMinusExpression(x) }

Sorry, but your argument that Zig/Rust can support unary -, but for some reason adding unary + will lead to some unforeseen catastrophic complexity, is most likely misguided.

Sure, we can agree that often unary operators can be challenging to parse, but if you can parse unary -, parsing unary + becomes simple (as shown above)

Oh! You don’t need more operators, because they seem “mathematical”?

Then why do you need unary - operator for?

Just write 0 - x instead of -x.

1 Like

I actually quite like that idea, personally (no unary minus). But I would not advocate for it…

One technical argument for why unary + shouldn’t be supported is that it serves no semantic purpose yet is another detail the user needs to remember the specifics of and introduces a risk of users bringing with them incorrect preconceived notions from other languages.

In the C family of languages, unary + performs integer promotions, meaning it promotes values of smaller integer types like char or short to int. Type inference isn’t very common in C itself, but it is in C++, C# or Java. Additionally, in many dynamically typed languages, unary + coerces strings or “number-like” types to some default numeric type. These differences in behavior could result in subtle mistakes and bugs when users port code to Zig.

It might sound silly but there’s a precedent for these kind of decisions. Zig already banned leading zeroes in numeric literals, another feature that serves no semantic purpose, to prevent mistakes when translating code from languages that use leading zeroes for octals (where octal 0755 is decimal 493, not decimal 755).

Note that unary - does serve a purpose because it might map to a unary negation processor instruction, distinct from “subtract from zero”.

3 Likes

Well, to be fair, there actuallyis a tiny semantic purpose: When reading +x I can be sure that x is a number.

Regarding the difficult meaning of unary plus in other languages like C or C++, and the possible confusion that a much simpler meaning in Zig could cause for people coming from other languages, I’m pretty sure that most developers aren’t aware of this (I for sure weren’t), and that this argument has never stopped Zig from doing something slightly different (eg see the discussions about assert, or the try keyword etc).

The leading zeroes topic is not comparable to this.
I think we all agree to it’s elimination.

I think an unary plus is nice to have (but not really needed), does not harm, and should be simple to implement.
If someone comes up with a PR, why not?

The technical semantic would be a no-op.

1 Like

I can see it is frustrating but it’s really quite hard to have a debate around this without more concrete examples of code that would actually benefit from this, especially current code that exists in std or other repos.

The usage of “we” here and the empathic statements that this should just be obvious also don’t help - who actually is “we” and do you speak for them? Your argument is weakened by it’s communicated assumption from the start your position is the only obvious one and any opposition is ignorance.

Unfortunately the argument at the moment seems to come down to wanting it because you’re used to it, and the want to remove the frustration you’re feeling in it’s absence. Those are legitimate feelings, but they probably aren’t gonna be enough to convince anyone to put it in Zig.

6 Likes

It is conventional to include unary + and - operators.

They exist in almost all languages that support unary operations.

Our opposition is to the fact that Zig removed a perfectly harmless operator without providing any technical reason for it. Including it would not introduce any complexity to the language, because Zig already supports unary -, and adding a parser rule for + is not difficult (no matter how much people on the forum may disagree).

The decision to remove unary + was Zig dev’s purely personal preference, without any technical reasoning behind it. Now, those of us who want the unary + operator, are being asked to provide explicit reasoning regarding why we want it.

With all due respect, this feels rather weird. Why shoulld we have to provide all of the reasons regarding why some feature is necessary, while the dev team can remove anything they want without giving any reason?

We want this because it is necessary in mathematics to,

  • Imply intention that something is positive.
  • Align + and - values so they look consistent, and are easy to read, and debug.
  • For symmetry with the unary - operator, however I don’t know if explaining this is helpful.

Unary + and unary - operators are necessary because + and - values exist in mathematics.

When we write scientific code, or write values to screen/file (as shown below), sometimes we want them to be explicitly marked with + or -. Not being able to do so is limiting to what we want to express.

Sorry but if it’s not automatically evident to anyone why mathematical symmetry is important, we can not explain it with any number of examples.

So I guess no need to discuss it further.

1 Like

I don’t think the unary plus is useful for implying intention that a number is positive - because it isn’t necessarily!

I do agree though that when paired with a number literal, it can nicely emphasize its positivity.

As for the mathematical symmetry argument: can you please explain what is the symmetry between the two unary operators? Leaving aside the approximative nature of the finite data types, I don’t think there is one in a technical sense (as automorphisms of a set of numbers). I could see an argument for a symmetry between two embeddings of the naturals into the integers, which would translate having both + and - as operators of the form (e.g.)

u31 -> i32

being somehow mathematically canonical, but who would use this?

Have you considered using custom functions instead? Something like this:

Basically, use fn @“+”(x: anytype) @TypeOf(x) { return x; } and fn @“-“(x: anytype) @TypeOf(x) { return -x; }

If you don’t like @“+” and @“-“, you could name the functions whatever you want, too. I haven’t tested this, so maybe it doesn’t always work, or it has some downside that I don’t know about, but it seems to meet your three requirements.

I personally like the idea of a unary plus operator, and it doesn’t seem hard to add. I looked at the issues at https://github.com/ziglang/zig/issues?q=is%3Aissue%20unary and didn’t see any that mentioned unary plus. It’s possible that it’s missing because nobody needed it yet. I think you could open an issue asking for it to be added to the language.

From the perspective of Zig being C 2.0, I can understand why you say that it was removed, but I think that Zig is independent from C, and unary plus simply hasn’t been added yet. I’m just an onlooker, so I could be totally wrong about that, but that’s the way it looks to me.

1 Like

It is not weird, all decisions within zig have a clear and objective reason (at least that’s the goal), it’s the reason why zig is so simple a language.
There is no reason why unary + was removed, because it was never removed, because it was never in the language in the first place.

You are making many statements and assumptions about the language and the people behind it, with all due respect, that is not respectful.

But we do genuinely want to know your reasoning

If you want to convince us, this is what you need to focus on, this is a possibly objective reason.

do you mean to assert that a value is positive? how is that different from std.debug.assert(val > 0)?

do you mean to ensure that a value is positive? how is that different from @abs(val)?

do you mean something else entirely?

2 Likes

When printing a signed integer, if you specify a non-zero, non-null format width it will print the + sign for positive values.
eg print("{d:1}", .{@as(i8, 20)})+20
a width of 1, just enables the sign as all numbers are at least 1 char wide, widths larger than the number of chars for the value will add padding. tbh there should just be a dedicated + format specifier, rather than reusing the width parameter, but thats how it is atm.

1 Like

Generally when you are asking for a change to a system it is incumbent on you to provide reasons for why that change is a benefit. You are asking for work to be done, it should be done for a concrete reason. And despite your assertions to the contrary, there is no evidence that the zig team removed the unary +. Indeed there has been evidence in this very thread that shows that the unary + has never existed in zig. Ignoring that evidence makes it look like you are just arguing in bad faith.

Finally, I’m not really sure what you want out of zig. Most of the topics you have created on this forum have been ones that bring up complaints about why zig doesn’t behave in some way that another language does. While it can be good to look at other languages, and get critiques, at some point it crosses the line where the vigor of the complaints outweigh the vigor of contribution to the community or project. Perhaps if you had a larger project you were working on in zig that needed the unary + it would be easier to get support for it.

4 Likes

Again with the talk as if we’re all too dumb to understand you, but we’re just asking for one of the most basic and simple things you can possibly ask for when talking about language features - examples. You’re refusing to provide them for the sole reason that you think someone unconvinced has proved themselves too ignorant already and therefore isn’t worthy of the examples that might exist. This is such a bad faith way of making your point.

The sad part is that I wouldn’t be surprised if a bunch more people would agree if you’d provided them, me included. Give it a go, see what happens, but as it stands I’m leaving this thread less convinced that unary plus is useful than when I came in.

4 Likes