ceylon / ceylon-spec

DEPRECATED
Apache License 2.0
108 stars 34 forks source link

assert with body #1434

Open gavinking opened 8 years ago

gavinking commented 8 years ago

In #891 it was proposed that we could support stuff like this:

assert (exists length, nonempty sequence, length>0) {
    return null;
}

Even though #891 is now implemented, there may still be value in that. I personally find it to be a more pleasing and more powerful way to write "guards".

lucaswerkmeister commented 8 years ago

I still think it’s much clearer with else, i. e.

assert (exists length, nonempty sequence, length>0) else {
    return null;
}
FroMage commented 8 years ago

So the difference with if is that the new values scope extends to the end like normal assert, and the difference with normal assert is the failure code that can be customised rather than just throw, right?

gavinking commented 8 years ago

Well the really big difference is that to write the above with if, I would have to write:

if (!exists length) {
    return null;
}
if (!nonempty sequence) {
    return null;
}
if (length<=0) {
    return null;
}

Which is significantly worse.

quintesse commented 8 years ago

I can't help but intensely dislike this, but I don't see any other option since we decided a long time ago to have this , notation in conditions.

zamfofex commented 8 years ago

Honestly, I agree with @quintesse. I think a better aproach would be to allow people to put ! before conditional thingies:

if!(exists bar, foo())
{
    assert(false);
}
bar.baz();

Same for while!(), and assert!()...

But also, I agree with @gavinking that these "guard" thingles are not very ceylonic. If you end up with a bunch of ifs guarding your actual code, then just put your code actually inside the if block...

if(!exists foo) { return(null); }
if(!exists bar) { return(null); }
if(!exists baz) { return(null); }
// actual code

becomes

if!(exists foo, exists bar, exists baz)
{
    // actual code
}
else
{
    return(null);
}
bjansen commented 8 years ago

Oh so now I could rewrite this Java code:

if (foo == null || foo == bar) {
    return;
}

to a nice

assert(exists foo, foo != bar) {
    return;
}

instead of the ugly

if (foo?.equals(bar) else true) {
    return;
}
assert(exists foo);

I like that :+1:

RossTate commented 8 years ago

I agree with @lucaswerkmeister, the else is necessary to make this clear to people not familiar with the feature.

luolong commented 8 years ago

I somewhat dislike the else after the assert condition.

Although, I can see how it makes the it more explicit when the block is being invoked...

I would however add an additional condition to the assertion failure block that it has to definitely return.

Otherwise it is indistinguishable from if

gavinking commented 8 years ago

I would however add an additional condition to the assertion failure block that it has to definitely return.

Yes, of course, I'm assuming that.

FroMage commented 8 years ago

I'd also put an else.

davidfestal commented 8 years ago

+1 for the else also

lukedegruchy commented 8 years ago

+1 for else.

ncorai commented 8 years ago

+1 for else

zamfofex commented 8 years ago

I thought I had posted this already, but apparently not: besides my distaste for this feature (and my preference for if!()), I prefer the version with else as well. Not exclusively because it makes it easier it easier for people unfamiliar with the feature to understand, but also because it makes more sense syntactic-wise. It bring the syntax closer to the if structure, having the else block contain code that is executed when the structure's normal behavior isn't performed...

jvasileff commented 8 years ago

I really like the idea, but I'm not sure about the syntax. assert suggests the input is invalid, or at least deficient, making many uses of this powerful feature look like abuses.

The if!() idea doesn't make sense to me, because ! is confusing. Are all of the conditions negated? What happens to the ,s?

If any were a keyword, I'd suggest:

if any (!exists length, !nonempty sequence, length <= zero) {
    return;
}

perhaps subtle, but another idea would be to use ;s for the || analog to &&'s , in if statements:

if (!exists length; !nonempty sequence; length <= zero) {
   return;
}
zamfofex commented 8 years ago

The if!() idea doesn't make sense to me, because ! is confusing. Are all of the conditions negated? What happens to the ,s?

The ! means that all the conditions should be false.

if!(foo, bar, baz)
{
    print("hi");
}

is equivalent to

if(!(foo && bar && baz))
{
    print("hi");
}

Of course, that substituition wouldn't work for is, exists and nonempty...