April 09, 2008 Re: I just got it! (invariant/const) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Janice Caron | Janice Caron wrote:
> On 09/04/2008, Denton Cockburn <diboss@hotmail.com> wrote:
>
>> > Of course, the explicit cast necessary to
>> > create an invariant C in the first place is a bit ugly. Maybe we need
>> > "inew" to make new invariant objects?
>>
>>Couldn't the compiler insert the cast based on the declaration?
>
>
> No, because objects created by new are not necessarily transitively
> unique. For example
>
> class C
> {
> int * p;
>
> this()
> {
> p = &someGlobalVariable;
> }
> }
>
> invariant C c = cast(invariant) new C;
> someGlobalVariable = 1;
>
> Whoops! c just changed!
>
> The explicit cast makes it the programmer's fault, not the compiler's!
>
> Come to think of it, "inew" would suffer the exact same problem, so it
> doesn't solve anything. Looks like there's no easy way to make an
> invariant class instance.
It should be illegal to cast objects invariant unless the compiler can guarantee the invariantness. So the cast here should produce an error.
| |||
April 09, 2008 Re: I just got it! (invariant/const) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to guslay | "guslay" wrote
> Janice Caron Wrote:
>
>> On 09/04/2008, Georg Wrede wrote:
>>
>> int f(invariant D d) invariant pure { ... }
>
> Shouldn't it be
>
> int f(invariant D d) pure { ... }
>
> Pure functions are a subset of invariant functions, no?
No.
A function does not necessarily need to take an invariant 'this' pointer to be pure.
For example:
class C
{
invariant int x;
pure int getX() { return x;}
}
void foo()
{
C c = new C;
c.getX(); // ok
}
-Steve
| |||
April 09, 2008 Re: I just got it! (invariant/const) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Georg Wrede | On 09/04/2008, Georg Wrede <georg@nospam.org> wrote: > > int f(invariant D d) { ... } invariant pure > > > > And that would mean that f takes as it's parameters the hidden invariant parameter "this" and an invariant D d. It is pure, and returns an int. > > Which is precisely the same as the previous one? No, again, that we my fault for misreading the question, and for which I now feel very silly. The qualifiers are /not/ allowed following the function body, and I apologise for giving that impression. However, the following are all equivalent. int f(invariant D d) invariant pure { ... } int f(invariant D d) pure invariant { ... } pure int f(invariant D d) invariant { ... } invariant int f(invariant D d) pure { ... } pure invariant int f(invariant D d) { ... } invariant pure int f(invariant D d) { ... } ...unless of course pure implies invariant, which we would hope, in which case you only have one of int f(D d) pure { ... } pure int f(D d) { ... } > Additionally, I seem to remember that stuff like > > kljal alsje fss laskef(kajs aks) { > > // potentially hundreds of lines here > > } lksjd afaf > > was frowned upon in D. Has this changed? No. Apologies for confusion. > > Well, they can be optimised away, at least. > > They can be flatly removed! That's what "optimised away" means. :-) > - Any pure function has to return a value. To be /useful/ it has to return a value. To be /syntactically correct/, probably not. For example: void doNothing(int x) pure { } int doSomething(int x) pure { doNothing(x); return x + 1; } That looks OK to me. doNothing() will be optimised away completely, but I think it needs to be /allowed/ because such a function could conceivably arise as a result of template instantiation or string mixin. > - In a pure function, ignoring the return value of a called function is an > error. I see no reason why that should be an error. Again, generic programming might result in such code. > This is even stronger than (1) above, it is clearer, > and it's *right*. Sure, but you don't need to outlaw code that does nothing. :-) | |||
April 09, 2008 Re: I just got it! (invariant/const) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to guslay | On 09/04/2008, guslay <guslay@gmail.com> wrote:
> Janice Caron Wrote:
>
> > On 09/04/2008, Georg Wrede <georg@nospam.org> wrote:
> >
>
> > int f(invariant D d) invariant pure { ... }
>
> Shouldn't it be
>
> int f(invariant D d) pure { ... }
Hopefully, it will just be
int f(D d) pure {...}
and pure will imply, not only that "this" is invariant, but that all function arguments are too. However, at this stage we can only guess at what the syntax will be.
| |||
April 09, 2008 Re: I just got it! (invariant/const) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Georg Wrede | "Georg Wrede" wrote > Janice Caron wrote: >> On 09/04/2008, Denton Cockburn wrote: >> >>> > Of course, the explicit cast necessary to >>> > create an invariant C in the first place is a bit ugly. Maybe we need >>> > "inew" to make new invariant objects? >>> >>>Couldn't the compiler insert the cast based on the declaration? >> >> >> No, because objects created by new are not necessarily transitively unique. For example >> >> class C >> { >> int * p; >> >> this() >> { >> p = &someGlobalVariable; >> } >> } >> >> invariant C c = cast(invariant) new C; >> someGlobalVariable = 1; >> >> Whoops! c just changed! >> >> The explicit cast makes it the programmer's fault, not the compiler's! >> >> Come to think of it, "inew" would suffer the exact same problem, so it doesn't solve anything. Looks like there's no easy way to make an invariant class instance. > > It should be illegal to cast objects invariant unless the compiler can guarantee the invariantness. So the cast here should produce an error. This cannot be guaranteed by the compiler. It is depending on you to ensure that the object stays invariant. From http://www.digitalmars.com/d/2.0/const3.html "The second way (to create invariant data) is to cast data to invariant. When doing so, it is up to the programmer to ensure that no other mutable references to the same data exist." -Steve | |||
April 09, 2008 Re: I just got it! (invariant/const) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Janice Caron | Janice Caron Wrote:
> On 09/04/2008, Georg Wrede <georg@nospam.org> wrote:
> > This is even stronger than (1) above, it is clearer,
> > and it's *right*.
>
> Sure, but you don't need to outlaw code that does nothing. :-)
D already outlaws having code that isn't run. I would prefer for code that does nothing to be considered an error. Of course, with most functions being impure, that's tough to enforce. With pure functions, it should be easy.
| |||
April 09, 2008 Re: I just got it! (invariant/const) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 09/04/2008, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
> A function does not necessarily need to take an invariant 'this' pointer to
> be pure.
>
> For example:
> <snip>
Trouble is, that means we'll end up having to write "invariant" all over the place, and it's really quite a long keyword!
Maybe Walter will let us shorten it to "in"? (Yes, I know "in" means
"const" right now).
| |||
April 09, 2008 Re: I just got it! (invariant/const) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Janice Caron | Janice Caron wrote: > On 09/04/2008, Georg Wrede <georg@nospam.org> wrote: > > However, > the following are all equivalent. > > int f(invariant D d) invariant pure { ... } > int f(invariant D d) pure invariant { ... } > pure int f(invariant D d) invariant { ... } > invariant int f(invariant D d) pure { ... } > pure invariant int f(invariant D d) { ... } > invariant pure int f(invariant D d) { ... } Thanks. (Although I'd really love to see less possibilities here. Grepping for code, quickly skimming others' code, and for me personally, making less mistakes, ...) > ...unless of course pure implies invariant, which we would hope, in > which case you only have one of > > int f(D d) pure { ... } > pure int f(D d) { ... } Excellent. >>>Well, they can be optimised away, at least. >> >> They can be flatly removed! > > That's what "optimised away" means. :-) :-) >> - Any pure function has to return a value. > > To be /useful/ it has to return a value. To be /syntactically > correct/, probably not. For example: > > void doNothing(int x) pure > { > } > > int doSomething(int x) pure > { > doNothing(x); > return x + 1; > } > > That looks OK to me. doNothing() will be optimised away completely, > but I think it needs to be /allowed/ because such a function could > conceivably arise as a result of template instantiation or string > mixin. > >> - In a pure function, ignoring the return value of a called function is an >>error. > > I see no reason why that should be an error. Again, generic > programming might result in such code. > >> This is even stronger than (1) above, it is clearer, >> and it's *right*. > > Sure, but you don't need to outlaw code that does nothing. :-) In the same manner as unreachable code is an error with many compilers, this might be polite. But, I do believe the template issue! | |||
April 09, 2008 Re: I just got it! (invariant/const) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Georg Wrede | Georg Wrede Wrote:
> Simen Kjaeraas wrote:
> > On Wed, 09 Apr 2008 15:40:37 +0200, Janice Caron wrote:
>
> >> You know that. I know that. Why would anyone think it strange?
> >
> > I think it is because invMemberFunc is invariant. Many read this as "will not change anything", even though it is not what it means.
>
> I seriously think the problem is with the phrase "invMemberFunc is invariant".
>
> This leads people to think invariantness is a property of the function, instead of it merely requiring an invariant "this".
>
> Maybe we should figure out another way of stating it.
Is that really the best solution? Why not have do what people nievely think it does? The code optimizer would benefit from that as well.
| |||
April 09, 2008 Re: I just got it! (invariant/const) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | Steven Schveighoffer wrote:
>
> There are interesting puzzles that I'm not sure how they will be solved. For example:
>
> pure int f()
> {
> char[] c = new char[15];
> c[0] = 'h'; // does this compile?
> }
>
> Does c need to be invariant to access members of the array? Clearly from this code, you can see that c is private to f. But under the rules, the data c references is not invariant, and so should be inaccessible. How will the compiler make this distinction?
Before commenting on the rest,
to me it is obvious that c is solely owned by f (because no references to c can exist outside of f), and therefore c is considered internal to f, so it's legal.
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply