April 09, 2008
On 09/04/2008, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
>  class C
>  {
>     int *m;
>     invariant(int *) i;
>  }
>
>  pure int getI(C c)
>  {
>     return *i;
>  }
>
>  There may be a reason to use i, but not m in a pure function.  Why should
>  pure restrict this?  It's technically correct and statically verifiable.

Except that there's no way to initialise i.

My understanding of the whole raw vs cooked thing in accu-functional.pdf is that it's a way of making an entirely invariant class. There would still be no way to create a class with some members invariant and others not, except for those that can be initialised at compile time.
April 09, 2008
"Janice Caron" wrote
> On 09/04/2008, Steven Schveighoffer wrote:
>>  class C
>>  {
>>     int *m;
>>     invariant(int *) i;
>>  }
>>
>>  pure int getI(C c)
>>  {
>>     return *i;
>>  }
>>
>>  There may be a reason to use i, but not m in a pure function.  Why
>> should
>>  pure restrict this?  It's technically correct and statically verifiable.
>
> Except that there's no way to initialise i.
>
> My understanding of the whole raw vs cooked thing in accu-functional.pdf is that it's a way of making an entirely invariant class. There would still be no way to create a class with some members invariant and others not, except for those that can be initialised at compile time.

I think this is a limitation that should be lifted, as there may be reasons to have an invariant member of a class that is set upon construction.  I can't see any reason to disallow it.

-Steve


April 09, 2008
Lionello Lunesu wrote:
> One thing that I like is that suddenly C++ "const &" construction can be standardized and made safe at the same time! Because of invariant, "in" can safely pass the arguments by ref, instead of by value.

And the compiler can make the decision for you as to which would be more efficient on your architecture. Happiness all around.
April 09, 2008
On Wed, 09 Apr 2008 20:40:38 +0200, Janice Caron <caron800@googlemail.com> wrote:

> What you're describing is something different - a non-invariant class
> with invariant members. Well, the only time you can assign an
> invariant member is at compile-time. That means they have to be
> assigned with compile-time constants. That, in turn, means they might
> as well be static, because they are not going to differ from instance
> to instance. And /that/ means you can rewrite your counterexample as
>
>     class C
>     {
>         static invariant int x = 4;
>
>         static int getX() pure
>         {
>             return x;
>         }
>     }
>
>     auto c = new C(4);
>     int n = c.getX;
>
> Now getX() is pure because it's static, and therefore /has/ no this pointer.

class foo
{
	invariant int bar;
	
	this()
	{
		bar = 4;
	}
}

This works under DMD 2.012. However, this does not work:

class foo
{
	invariant int bar = 2;
	
	this()
	{
		bar = 4;
	}
}

There is nothing wrong with having non-static, invariant member variables, which are assigned in the constructor. Of course, you'd get the exact same result (except for function which require invariant parameters, i.e. pure functions) with a const int.

-- Simen
April 09, 2008
On 09/04/2008, Simen Kjaeraas <simen.kjaras@gmail.com> wrote:
>  class foo
>  {
>         invariant int bar;
>
>         this()
>         {
>                 bar = 4;
>         }
>  }
>
>  This works under DMD 2.012.

That's interesting. I did not know that.
April 10, 2008
"Jason House" <jason.james.house@gmail.com> wrote in message news:ftiuj8$mob$1@digitalmars.com...
> 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.

I agree.. And one less keyword, which, it seems, is a goal in itself.

L. 

April 10, 2008
"Jason House" <jason.james.house@gmail.com> wrote in message news:ftislk$3m0$1@digitalmars.com...
> 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.

Why? If pure-ness (uh, purity?) can be checked, it can also be deducted (*), so the compiler could optimize/complain in either case.

Tagging a function explicitely as "pure" would only enable a constraint as to what other functions can be called, which is something I'd rather see solved using more generalized tagging abilities (See Scott Meyers' presentation on red-code, green-code [1]).

Maybe identifiers between the parameter list and the function body could work as ad-hoc constraints. This would work for pure and nothrow, and the user can add whatever identifier/constraint s/he wants.

L.

(*) Is this conclusion correct? It feels correct, but I don't think I can proof it.

[1] http://www.nwcpp.org/Downloads/2007/redcode_-_updated.pdf 

April 10, 2008
Lionello Lunesu wrote:
> 
> "Jason House" <jason.james.house@gmail.com> wrote in message news:ftislk$3m0$1@digitalmars.com...
>> 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.
> 
> Why? If pure-ness (uh, purity?) can be checked, it can also be deducted (*), so the compiler could optimize/complain in either case.

I was thinking along the same lines last week or so.  A lot of things
about a method signature can be deduced from what's inside.  Including
types of the arguments in many cases.  Languages like ML take this to
the extreme.  But the point of putting the info explicitly in the
signature is so that
A) the compiler doesn't need to see the implementation right away to
tell what's inside (separate compilation).
B) Joe Programmer doesn't have to see the implementation to know if he
can call it or not (documentation).
C) Fred Programmer can declare his intent to Joe that the method work in
such a way, and the compiler can tell Fred if what he though was true is
not (verification).

CTFE-ness is automatically deduced by the compiler, but using CTFE always requires access to the source of the method so A) is not an issue.  Still it might be nice to have a "ctfe" tag for purpose B).

So I think deduction of such stuff is not really viable overall. Perhaps it could be allowed for templates though?  The source is required to be available for those anyway.

--bb
April 10, 2008
On 10/04/2008, Lionello Lunesu <lionello@lunesu.remove.com> wrote:
>
> > Janice Caron Wrote:
> >
> > ...
> >
> > 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.

No I did not. That was Jason House. Please be careful with your level of nesting!
April 10, 2008
On 10/04/2008, Lionello Lunesu <lionello@lunesu.remove.com> wrote:
>  Why? If pure-ness (uh, purity?) can be checked, it can also be deducted

"purity" is the right word. (But "deducted" should be "deduced" :-))

> (*), so the compiler could optimize/complain in either case.

It would slow down compilation no end though. For example, a pure function is not allowed to call non-pure functions. Without the "pure" keyword, you'd have to follow through every function call recursively, and that could take a long time.

Moreover, just because the compiler decides the function is impure, that doesn't necessarily mean that the programmer /intended/ for it to be impure. Perhaps there was a bug? Perhaps there was a silly, simple, one line bug, that the programmer could fix in a jiffy if the compiler would only say "Error: Line 53: Pure function cannot do XYZ"? It is far better for the programmer to document their intentions, so that the compiler can check that those intentions are actually met.