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

return if #2966

Closed
mseld2 opened this issue Nov 15, 2019 · 18 comments
Closed

return if #2966

mseld2 opened this issue Nov 15, 2019 · 18 comments

Comments

@mseld2
Copy link

mseld2 commented Nov 15, 2019

I find myself writing code like this:

if (boolean_expr)
    return <value>;
else
   return <other_value>;

if(value == null) 
    return <default_value>;
 else 
    return value;

But I find myself thinking, 'This would be nicer':

return if(boolean_expr) <value> else <other_value>;

return value ?? <default_value>;
@mseld2
Copy link
Author

mseld2 commented Nov 15, 2019

I need to amend. The second item in my example is currently legal (see below). Please disregard.

return value ?? <default_value>;

Thanks,
Melissa

@spydacarnage
Copy link

spydacarnage commented Nov 15, 2019 via email

@BhaaLseN
Copy link

You can do this today.

// bool
return boolean_expr ? <value> : <other_value>;
// null
return value ?? <default_value>;

@mseld2
Copy link
Author

mseld2 commented Nov 15, 2019

Wow. That was a fast response.

Yes, I know the second one was incorrect, which is why I amended. The first one can be done that way, too. If you have more complicated expr in return. It's a bit messy though.

return if(boolean_expr) 
  { <expr>; 
    <value>; } 
else 
  { <expr>;
    value; }

@BhaaLseN
Copy link

Doesn't seem worth it to me just to save 7 characters (that is "return ".Length in front of the second value); especially at the cost of readability (💭 Is this being returned, or just executed? Let me check the beginning of the method if there's a return in front of the if)

@mseld2
Copy link
Author

mseld2 commented Nov 15, 2019

It's not just for return, but can be for assignment using =

result =  if(boolean_expr) 
  { <expr>; 
    <value>; } 
else 
  { <expr>;
    <other_value>; }

@BhaaLseN
Copy link

BhaaLseN commented Nov 15, 2019

That sounds a bit like #377, which might allow you to do this:

result = boolean_expr switch
{
   true => { <expr>; <value>; },
   false => { <expr>; <other_value>; },
};

(syntax may vary)

@mseld2
Copy link
Author

mseld2 commented Nov 15, 2019

Again, thanks for response.

I like it! Can this also be extended to switch with pattern matching?

@BhaaLseN
Copy link

Not sure what you mean. This is a switch expression that uses pattern matching.

@mseld2
Copy link
Author

mseld2 commented Nov 15, 2019

I apologize. I'm not a language person. But what I mean is https://docs.microsoft.com/en-us/dotnet/csharp/pattern-matching. Specifically the section: var declarations in case expressions.

@mseld2
Copy link
Author

mseld2 commented Nov 15, 2019

The examples I saw were all constant expressions being match true, false, 0, "string", etc. I'm wondering if it can match non-constant values (determined at runtime), too, as described in link.

@CyrusNajmabadi
Copy link
Member

The first one can be done that way, too. If you have more complicated expr in return. It's a bit messy though.

result =  if(boolean_expr) 
  { <expr>; 
    <value>; } 
else 
  { <expr>;
    <other_value>; }

That can be done like so:

<expr>;
result = boolExpr ? value : otherValue;

@mseld2
Copy link
Author

mseld2 commented Nov 15, 2019

In that example, true, but if expressions are different, cannot be done that way.

result =  if(boolean_expr) 
  { <expr>; 
    <value>; } 
else 
  { <other_expr>;
    <other_value>; }

@CyrusNajmabadi
Copy link
Member

CyrusNajmabadi commented Nov 15, 2019

In that example, true, but if expressions are different, cannot be done that way.

Then i don't see the value here :-/ . Use a local function, or just keep it a statement-based if-statement. Squeezing everything that's a statemnet into an expression form doesn't make things automatically better. It's just inverting into a different form for no great reason afaict.

If your code is complicated enough to need multiple statements embedded within, then just use statements. that's their purpose :)

--

Note: i'm not trying to be negative here for the sake of being negative. I honestly know that it's a constant desire of people to continually squeeze more and more into expressions. But, honestly, i don't think that's a goal of the language, and there needs to be serious thought and apprehension around this as it really can actually make things less readable as you squeeze things tighter and tighter. If your loic is doing a lot of stuff, it's ok for the code to show that. Not everything has to be a one-liner that attempts to combine everything together into as small an expr as possible.

@mseld2
Copy link
Author

mseld2 commented Nov 15, 2019

You're right about squeezing more and more into an expression. I do a lot of development using C++ and Kotlin. Kotlin does a lot of squeezing things into expressions (which is probably what drove my line of questions). I've definitely found myself frustrated with the readability. I have not found myself frustrated with the readability of C++. The static analyzer for C++ doesn't flag as issues not using compact expressions; whereas, the Kotlin one does.

I appreciate the thought that goes into the design of C#. It's a very expressive language, and I'm glad it'll continue to keep its 'feel'.

Thanks for the great insight.

@CyrusNajmabadi
Copy link
Member

Absolutely! And hopefully i'm not coming across super negative. The feedback is definitely very welcome, and it's totally appropriate to ask for this. I'm just putting forth my opinion on keeping a good balance of flexibility and expressiveness in the language.

@mseld2 mseld2 closed this as completed Nov 15, 2019
@CyrusNajmabadi
Copy link
Member

@mseld2 FWIW, you don't have to close this. In general most proposals will receive some amount of feedback against it. Only close if you truly believe yourself that you no longer want the proposal. If this is still something you want, def keep open and it can be assessed and thought about during future planning.

Cheers!

@mseld2
Copy link
Author

mseld2 commented Nov 15, 2019

@CyrusNajmabadi I thought about it a bit, especially what you said about the balance between compactness, flexibility, expressiveness and readability. In one language I have code like below. It's concise, I didn't have to type much, but honestly...it's a bit hard on the eyes. Every time I see code I've written with complex logic on one of the cases, it's always hard to read. I'm not sure that having syntax to make fewer lines of code is worth it when I have to read the code 6 months later. I'm not sure I'd want to introduce something like this into a language that I use every day...a language, that frankly, I actually really like and find very expressive.

My proposal isn't adding value in the sense that it's doing something new. I can do the exact same thing using constructs currently available in the language. Some people say that C# has a bit of an older style to it, it doesn't have some of the constructs in new languages like for(index in 0..2), etc. Some things aren't truly adding value, IMO. It's just a new way to do something that can already be done. I'm sure there's a balance between evolution and adding things because that's what languages do now. But just because some languages have "modern" constructs doesn't necessarily mean they're more expressive. C# has its own style. Kotlin has its own style. C++ has its own style. Swift has its own style. Is one better than the other? I have my preference, but one isn't better than the other. They're just different from each other. And the difference between them is a positive thing. It gives us...choice and the ability to express ourselves in a way that suits our needs. C# isn't Kotlin or Swift, and it never should be. It should always be C#.


    private fun parseAudioStreamingDescriptor(subtype: Byte): UsbBase = when(subtype.toInt()) {
            AS_DECODER -> parseDecoderDescriptor()
            AS_ENCODER -> ASEncoder(_length, _type)
            AS_FORMAT_TYPE -> parseFormatDescriptor()
            AS_GENERAL -> {
                if (_type.toInt() == DESCRIPTOR_AUDIO_ENDPOINT) {
                    ASIsochronousAudioDataEndpoint(_length, _type)
                } else {
                    ASGeneral(_length, _type)
                }
            }
            else -> {
                Logger.warning(getClassTag(), "Unknown audio stream descriptor sub type (${toHexString(subtype.toInt(), 1)}")
                null
            }
        }
    }

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

4 participants