Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Add 'Unless' conditional statement, as seen in Ruby #560

Closed
Nick-Lucas opened this issue May 9, 2017 · 18 comments
Closed

Proposal: Add 'Unless' conditional statement, as seen in Ruby #560

Nick-Lucas opened this issue May 9, 2017 · 18 comments

Comments

@Nick-Lucas
Copy link

Nick-Lucas commented May 9, 2017

One of the best design features of Ruby is the fluid read-time semantics of code which can be achieved.

Probably the most useful feature to this effect is the unless statement, which behaves like an if statement, except code runs if the expression evaluates to false.

This is great at reducing logical noise, particularly where an if statement's expression is complex enough to need wrapping in brackets before inversion.

For example
// C# today
if (!(faa || bar || baz)) 
{
  DoSomething();
}
else 
{
  DoSomethingElse();
}
# Ruby today
unless faa || bar || baz
  do_something()
else
  do_something_else()
end
Proposed syntax:
unless (faa || bar || baz) 
{
  DoSomething();
}
else 
{
  DoSomethingElse();
}

It's quite a small language feature in the grand scheme of things, but I believe this could reduce the read-time complexity on a lot of C# code.

@lachbaer
Copy link
Contributor

lachbaer commented May 9, 2017

We had that already in closed issue #157.

@lachbaer
Copy link
Contributor

lachbaer commented May 9, 2017

You can write a custom tool function that fits your needs enough.

class MyTools {
  public static bool SeeAsUsing(bool expr) => !expr;
}

and use it

using MyTools;
if ( SeeAsUsing( faa || bar || baz ) )  
  DoSomething();
else 
  DoSomethingElse();

Or start reading to your mind "if not" or "unless" if you see if (! (...)). I was already tilting at windmills with it 😉

@lachbaer
Copy link
Contributor

lachbaer commented May 9, 2017

PS: why are you using curly braces for single statements in your if-else? I'm asking because of a discussion in #559.

Besides, it's written useless not unless 🤣 😆

@Nick-Lucas
Copy link
Author

Nick-Lucas commented May 9, 2017

Thanks for pointing #157 out, I didn't manage to find that while searching for a similar proposal.

After reading I disagree that this is a duplicate, as #157 and all the debate surrounding it propose a solution which would not provide any semantic advantages over what we already have, and the style was much more appropriate for VB.Net. The debate became derailed by the choice of syntax, as opposed to the usefulness of the concept.

Under the original proposal (and its discourse) you would still have to flip the logic in your head (read: "if not foo or bar or baz"), as opposed to writing a sentence which reads naturally (read: "unless foo or bar or baz")

I would like to see this discussed again under this updated proposal

@lachbaer
Copy link
Contributor

lachbaer commented May 9, 2017

You might want to point out, especially to @CyrusNajmabadi ( 👋 ) that there exist humans in the world who would have a much easier life if some keywords existed that reflect their usual (cultural?) way of thinking.

@lachbaer
Copy link
Contributor

lachbaer commented May 9, 2017

@casperOne When you give 👎 you should at least explain why! 😞

@HaloFour
Copy link
Contributor

HaloFour commented May 9, 2017

You already have the options of inverting the condition or changing the order of the then-statements and the else-statements. Adding another keyword doesn't provide any benefits other than satisfying a stylistic preference of specific developers at the detriment of adding yet-another-way of doing something.

@bondsbw
Copy link

bondsbw commented May 9, 2017

I prefer something like

if !(obj is string s)
{
    ...
}

as discussed in #7927 at roslyn. That discussion was moved to #157 (which was closed due to lack of support for the original proposal and not specifically lack of support for if!).

So I don't feel like if! was really rejected, and seems to have more support than this proposal.

@lachbaer
Copy link
Contributor

lachbaer commented May 10, 2017

I'd like to cite team mebmber @CyrusNajmabadi

When other languages provide significant value (i.e. not a reduction of a tiny number of characters), and that value would be widespread (i.e. you'd expect to see it show up in a significant percent of code of a significant percent of projects), then it's worth working on.

For the case of just being able ot restate something that is already extremely easy to state, and for the use-case of a very strange operator that i don't think you're writing properly in the first place, then this is just not proving it's worth.

Somewhere else (I don't find it at the moment) he stated more explicitly that the minor benefits, that changes like this proposal will bring, will never outweigh the [i.a. real money] costs of implementing it. Also there is simply no time to engage in features that "just add another way of doing something that can already be done in different ways". Especially when it is only about saving 2 characters.

@DavidArno
Copy link

...Also there is simply no time to engage in features that "just add another way of doing something that can already be done in different ways". Especially when it is only about saving 2 characters.

I'm glad they decided upon that policy after implementing expression-bodied members 😇

@lachbaer
Copy link
Contributor

@DavidArno Though probably used most times for shortening the appearance of methods, expression bodies have an actually different concept behind it, namely allowing expression-syntax instead of statement-syntax. That's why while et co. are not allowed in expression-bodies. I think that's mainly to be coherent with llambda "functions". Anyhow, they are used a lot. That allone justifies them ✌️

@CyrusNajmabadi
Copy link
Member

I'm glad they decided upon that policy after implementing expression-bodied members

We were still following that policy. In this case though, expressoin-bodied members provided enough value to make us feel that it was worthwhile.

@MisinformedDNA
Copy link

We were still following that policy. In this case though, expressoin-bodied members provided enough value to make us feel that it was worthwhile.

@CyrusNajmabadi How so? Do expression-bodied members really provide value? I always thought they were just a shorter way of saying the same thing. What can I do with expression-bodied members that aren't easily done with previous constructs?

@CyrusNajmabadi
Copy link
Member

@CyrusNajmabadi How so? Do expression-bodied members really provide value?

Yes. There is a substantial reduction in language ceremony for exceptionally common patterns. With the dual benefit of greatly decreasing code and having that be very widespread, this sugar was deemed worth it.

@audigex
Copy link

audigex commented Jun 25, 2020

I very much disagree with the earlier justifications against this keyword (both in this thread and in #157)

Are there other ways to achieve the result? Sure. Are they better? No.

The whole logic of "We can already do this with xyz" makes no sense to me. If that was the case, why create C# at all? We could do everything in Visual Basic.

Why create the using keyword when we already had .Dispose()? Why create async/await when you can do everything just fine with Task? And isn't a foreach just a lazy man's for, which itself is just syntactic sugar for while. And what a waste of time Linq was, I can do everything it does with a few loops!

In fact, why are we using high level languages at all, give me back my punch cards and let me code like a man.

It's nonsense. The fact is that an unless keywoard would fit many use cases perfectly, and produce cleaner, more elegant, more readable code.

I'm going to particularly single out "Especially when it is only about saving 2 characters." here... it's not about saving two characters, it's about the ability to read something at a glance

if( !localUser.IsAdministrator ) is less readable than unless( localUser.IsAdministrator ), particularly when scanning code. The former has the problems of being an unnatural negative, and in this specific case the !l combination makes it harder to see by simple virtue of how scan reading works. It's so easy to miss the ! next to an l, or even without a confusing l next to it.

And even ignoring the visual side of things "If not local user is an administrator" is obviously less comprehensible at a glance than "Unless the local user is an administrator". I know that everyone in this thread has likely been coding for a decade or more, that's the nature of the community... but that just means we're used to a bad way of doing things, it doesn't make it good.

"We can already do that in some other, slightly less readable way" is antithetical to everything else I see in C#, and I object to it strongly. This would be a fine addition to C#

Show me someone who claims they have never once misread if( !MyConditional ) as if( MyConditional ), and I'll show you a liar.

@HaloFour
Copy link
Contributor

HaloFour commented Jun 25, 2020

@audigex

Show me someone who claims they have never once misread if( !MyConditional ) as if( MyConditional ), and I'll show you a liar.

I guess I must be a liar, I've never had problems with !.

You can also do if (MyConditional == false) and C# 9.0 will add if (MyConditional is not true).

@jnm2
Copy link
Contributor

jnm2 commented Jun 29, 2020

🖐 I honestly think that makes me a liar too?

@theunrepentantgeek
Copy link

Yeah, count me too. I learned the lesson about the need to pay attention to every character long before I encountered any of the languages in the C family that use ! for negation. (I learned Sinclair, Applesoft & Amstrad Basics, 6502 & Z80 assembly languages, Logo, and UCSD & Turbo Pascals before I encountered C for the first time. I guess that dates me. 😀)

So I'm pretty confident that I've not overlooked a ! ... and I'm a heretic who prefers a proportional font to monospaced, so each ! is really narrow.

FWIW though, I'd kind of low key like to see if and unless permitted as conditional suffixes after other statements ...

Console.WriteLine(name) unless name == null;

... but that's been discussed to death and it's not going to happen ... and I'm happy enough with that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants