Open FroMage opened 8 years ago
I suppose that's mostly a question for @gavinking ;)
:+1: I've run into this several times.
Also, other cases where the declaration is split from an asserted definition, like:
shared class Foo(X val) {
Y y;
Z z;
if (val.hasYZ) {
assert(exists y = val.possiblyY());
assert(exists z = val.possiblyZ());
}
else {
y = ...;
z = ...;
}
...
}
and the same with destructuring.
I don't particularly see an obvious solution to this problem.
What if the exists
is not really narrowing the type of the resulting expression as in this case? The Y
is the same type before and after the assert.
@quintesse well in that case the problem simply doesn't exist.
I'm not sure I understand. What I'm saying is that it seems it could work for the case where y
has the type Y
both before and after the assert and that it's just used to test the type of the expression that gets assigned to y
. I don't know which problem doesn't exist in that case.
The problem in code like
shared Y y;
assert(exists y = val.possiblyY());
is that normally, an is
, exists
or nonempty
condition always introduces a new variable. In this case, we want it to refer to an existing, definitely uninitialized variable instead.
EDIT: To clarify my comment: I don’t yet see what’s being proposed here. Under which conditions do we allow the is
condition to refer to an existing variable instead of a new one?
variable
“variables”?assert
s?@lucaswerkmeister I'd say "yes", "no" (we still need the assurance variables don't get changed) and "no" (it would work everywhere we have type narrowing exist
and is
)
Actually I have changed my mind. In fact there's nothing wrong with:
Y y;
assert(exists y = val.possiblyY());
Since we actually accept this:
assert(exists Y y = val.possiblyY());
So in fact we could simply eliminate the error in this case.
The thing that would be new here would be the idea that a condition can be used to initialize an uninitialized but pre-declared variable, which is not currently possible. I'm not sure if that would be unacceptably confusing. Perhaps it would be.
An alternative would be to let you write:
assert(exists shared Y y = val.possiblyY());
But that's probably even worse.
An alternative would be to let you write:
assert(exists shared Y y = val.possiblyY());
But that's probably even worse.
Agreed, on both counts (it’s an alternative, but a horrible one). You really don’t want to fit a long docstring in there.
If the type of the variable y
must remain the same, the condition is redundant information. But I think it would be better and more natural to allow narrowing. So, a condition on an uninitialized value would initialize and (if necessary) narrow.
Instead of:
Y y;
if (...) {
assert(is Y y = val.possiblyY());
assert(is YSub y);
y.doYSubStuff();
}
You'd have:
Y y;
if (...) {
assert(is YSub y = val.possiblyY());
y.doYSubStuff();
}
Or a stef
expression:
shared Y y = stef(exists x = f()) x;
Where stef
has the same powers as assert
but with a cooler name. Ties in well with my other issue about assert
in comprehensions...
Bumped into this issue today
I'm trying to do this:
And well, it's not allowed, so I have to do this stupid code:
Is it something we could allow or is there another way to do this?