www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - How about 'pure' for constants?

reply Don Clugston <dac nospam.com.au> writes:
IIRC, there was a suggestion at the conference that D would get a new reserved 
word, 'pure', for functional programming. This should be considered as an 
alternative to 'enum'. I really don't like the idea of

enum SomeEnormousStruct a = SomeFunction(AnotherEnormousStruct(x, "abc"));

(and my CTFE code is already full of this sort of thing. It's simply not true 
that 'enums' would mostly be integral types).

Seems to fit with the idea of 'having no side-effects' - a pure value would not 
be stored anywhere, and make no contribution to the size of the executable.

pure real pi = 3.141592564;

// this is really silly if you use 'enum' instead.
pure real myNaN = real.nan;

BTW, a pure function taking only pure parameters returns a pure value, so this 
seems to be entirely consistent:

pure int foo(int a, int b);
Dec 11 2007
next sibling parent "Aziz K." <aziz.kerim gmail.com> writes:
Introducing 'pure' as a new storage class for denoting manifest constants  
and functions without sideeffects sounds very good to me. I'd be happy  
with that solution. Much better than abusing the poor enum keyword. It  
just wants to enumerate stuff, can't you see it? Let's not be that cruel :)
Dec 11 2007
prev sibling next sibling parent Daniel Keep <daniel.keep.lists gmail.com> writes:
This is by far the best suggestion thus far.  This way, there's no
confusion over what it does based on existing behaviour, we can define
exactly how it should behave, and it's logically consistent with pure
functions.

Nicely done :)

	-- Daniel
Dec 11 2007
prev sibling next sibling parent Sean Kelly <sean f4.ca> writes:
Don Clugston wrote:
 IIRC, there was a suggestion at the conference that D would get a new 
 reserved word, 'pure', for functional programming. This should be 
 considered as an alternative to 'enum'. I really don't like the idea of
 
 enum SomeEnormousStruct a = SomeFunction(AnotherEnormousStruct(x, "abc"));
 
 (and my CTFE code is already full of this sort of thing. It's simply not 
 true that 'enums' would mostly be integral types).
 
 Seems to fit with the idea of 'having no side-effects' - a pure value 
 would not be stored anywhere, and make no contribution to the size of 
 the executable.
 
 pure real pi = 3.141592564;
 
 // this is really silly if you use 'enum' instead.
 pure real myNaN = real.nan;
 
 BTW, a pure function taking only pure parameters returns a pure value, 
 so this seems to be entirely consistent:
 
 pure int foo(int a, int b);
I've been wondering the same thing, but couldn't decide if the keyword made sense in this context. But by your explanation it clearly does. It has my vote. Sean
Dec 11 2007
prev sibling next sibling parent reply "Craig Black" <cblack ara.com> writes:
"Don Clugston" <dac nospam.com.au> wrote in message 
news:fjli16$1efd$1 digitalmars.com...
 IIRC, there was a suggestion at the conference that D would get a new 
 reserved word, 'pure', for functional programming. This should be 
 considered as an alternative to 'enum'. I really don't like the idea of

 enum SomeEnormousStruct a = SomeFunction(AnotherEnormousStruct(x, "abc"));

 (and my CTFE code is already full of this sort of thing. It's simply not 
 true that 'enums' would mostly be integral types).

 Seems to fit with the idea of 'having no side-effects' - a pure value 
 would not be stored anywhere, and make no contribution to the size of the 
 executable.

 pure real pi = 3.141592564;

 // this is really silly if you use 'enum' instead.
 pure real myNaN = real.nan;

 BTW, a pure function taking only pure parameters returns a pure value, so 
 this seems to be entirely consistent:

 pure int foo(int a, int b);
Much better than enum. Thanks Don.
Dec 11 2007
parent reply "Janice Caron" <caron800 googlemail.com> writes:
Best suggestion so far. (Even better than wildebeest! :-) )

Now let's see what Walter and Andrei think.
Dec 11 2007
parent =?ISO-8859-1?Q?=22J=E9r=F4me_M=2E_Berger=22?= <jeberger free.fr> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Janice Caron wrote:
 Best suggestion so far. (Even better than wildebeest! :-) )
 
I agree :) Jerome - -- +------------------------- Jerome M. BERGER ---------------------+ | mailto:jeberger free.fr | ICQ: 238062172 | | http://jeberger.free.fr/ | Jabber: jeberger jabber.fr | +---------------------------------+------------------------------+ -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (GNU/Linux) iD8DBQFHXt1Yd0kWM4JG3k8RAu8xAJ9ylvOBvx4Gj5c7GMgogC0Koyv5TgCglPvn WRHpTlXo/mToR4ccWMgvsAI= =eNDA -----END PGP SIGNATURE-----
Dec 11 2007
prev sibling next sibling parent reply guslay <guslay gmail.com> writes:
Don Clugston Wrote:

 
 enum SomeEnormousStruct a = SomeFunction(AnotherEnormousStruct(x, "abc"));
 
I thought the enum concept (regardless of the keyword) was for compile time strings and primitives. Is it also supposed to work with structs?
Dec 11 2007
next sibling parent Sean Kelly <sean f4.ca> writes:
guslay wrote:
 Don Clugston Wrote:
 
 enum SomeEnormousStruct a = SomeFunction(AnotherEnormousStruct(x, "abc"));
I thought the enum concept (regardless of the keyword) was for compile time strings and primitives. Is it also supposed to work with structs?
Anything that can be represented as a compile-time constant, I believe. And that includes structs. Sean
Dec 11 2007
prev sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"guslay" <guslay gmail.com> wrote in message 
news:fjmhgg$tv2$1 digitalmars.com...
 Don Clugston Wrote:

 enum SomeEnormousStruct a = SomeFunction(AnotherEnormousStruct(x, 
 "abc"));
I thought the enum concept (regardless of the keyword) was for compile time strings and primitives. Is it also supposed to work with structs?
Why not? If they're made of strings and primitives, it seems perfectly fine. They're value types, after all.
Dec 11 2007
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Jarrett Billingsley" wrote
 "guslay" wrote
 Don Clugston Wrote:

 enum SomeEnormousStruct a = SomeFunction(AnotherEnormousStruct(x, 
 "abc"));
I thought the enum concept (regardless of the keyword) was for compile time strings and primitives. Is it also supposed to work with structs?
Why not? If they're made of strings and primitives, it seems perfectly fine. They're value types, after all.
What if the struct has methods? The fact that it has methods is ok as those are separate entities, but struct methods require a this pointer. If this is a manifest constant, it's possible that the struct cannot have a pointer to the data. I think this could be averted if the 'this' portion of a struct was not passed by reference, but passed by value. Maybe there should be a way to define whether 'this' is a pointer or a value? This would also allow operators to be used in constant expressions (one of the problems with using a struct as a replacement for a math type). I like the pure for manifest constants idea. However, it implies that only pure methods could be called on a struct that is a manifest constant, which seems too limited to me. If structs are allowed as manifest constants, then I don't think pure is a good keyword for it (though it's better than enum). -Steve
Dec 11 2007
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Steven Schveighoffer wrote:
 "Jarrett Billingsley" wrote
 "guslay" wrote
 Don Clugston Wrote:

 enum SomeEnormousStruct a = SomeFunction(AnotherEnormousStruct(x, 
 "abc"));
I thought the enum concept (regardless of the keyword) was for compile time strings and primitives. Is it also supposed to work with structs?
Why not? If they're made of strings and primitives, it seems perfectly fine. They're value types, after all.
What if the struct has methods? The fact that it has methods is ok as those are separate entities, but struct methods require a this pointer. If this is a manifest constant, it's possible that the struct cannot have a pointer to the data.
The compiler could make a copy on the stack, and pass a pointer to that. It already does that for stuff like "Struct(datamembers).method()", and the manifest constant could be considered equal to a "struct constructor" call with constant parameters. The stack copy could be elided when the method is inlined, of course. (Which isn't all that unlikely to happen, since struct methods can't be virtual)
 I think this could be averted if the 'this' portion of a struct was not 
 passed by reference, but passed by value.  Maybe there should be a way to 
 define whether 'this' is a pointer or a value?  This would also allow 
 operators to be used in constant expressions (one of the problems with using 
 a struct as a replacement for a math type).
So opAdd & friends aren't CTFE'd? That seems like a silly omission, and should be easy enough to fix. No need to pass 'this' by value.
Dec 11 2007
next sibling parent reply "Janice Caron" <caron800 googlemail.com> writes:
On 12/11/07, Frits van Bommel <fvbommel remwovexcapss.nl> wrote:
 So opAdd & friends aren't CTFE'd? That seems like a silly omission, and
 should be easy enough to fix.
I figure "static" within struct declaration scope means "has no this pointer". Only at global scope does it mean CTFE. I guess "static" was a bad choice of keyword for CTFE! My personal choice of keyword for CTFE would be /none at all/. Why would you need one? Let the compiler decide! If the function is /called/ at compile time, then that should be enough to declare it as CTFE. As for structs and pure, I think it works. If a struct can be used in a pure function, and contains only pure functions, then "pure" still seems a better word than "enum". And if it's /not/ pure, then just use const like we have up till now, and live with the storage cost!
Dec 11 2007
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Janice Caron" <caron800 googlemail.com> wrote in message 
news:mailman.310.1197398288.2338.digitalmars-d puremagic.com...
 On 12/11/07, Frits van Bommel <fvbommel remwovexcapss.nl> wrote:
 So opAdd & friends aren't CTFE'd? That seems like a silly omission, and
 should be easy enough to fix.
I figure "static" within struct declaration scope means "has no this pointer". Only at global scope does it mean CTFE. I guess "static" was a bad choice of keyword for CTFE! My personal choice of keyword for CTFE would be /none at all/. Why would you need one? Let the compiler decide! If the function is /called/ at compile time, then that should be enough to declare it as CTFE.
Where did you get this idea? You don't need to declare a function in any special way, at global scope or in structs, to get it to work with CTFE. If a function _can_ be called at compile time, it will be. Otherwise, it will defer the call to runtime. The same function can be evaluated at compile time and at runtime.
Dec 11 2007
parent "Janice Caron" <caron800 googlemail.com> writes:
On 12/11/07, Jarrett Billingsley <kb3ctd2 yahoo.com> wrote:
 Where did you get this idea?
I don't know. Glad to hear I'm wrong! Anyway, it turns out the rule is: "the function may not be a non-static member, i.e. it may not have a this pointer", so maybe that's what confused me. That does look like it rules out opAdd et al though.
Dec 11 2007
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Frits van Bommel" wrote in message
 Steven Schveighoffer wrote:
 "Jarrett Billingsley" wrote
 "guslay" wrote
 Don Clugston Wrote:

 enum SomeEnormousStruct a = SomeFunction(AnotherEnormousStruct(x, 
 "abc"));
I thought the enum concept (regardless of the keyword) was for compile time strings and primitives. Is it also supposed to work with structs?
Why not? If they're made of strings and primitives, it seems perfectly fine. They're value types, after all.
What if the struct has methods? The fact that it has methods is ok as those are separate entities, but struct methods require a this pointer. If this is a manifest constant, it's possible that the struct cannot have a pointer to the data.
The compiler could make a copy on the stack, and pass a pointer to that. It already does that for stuff like "Struct(datamembers).method()", and the manifest constant could be considered equal to a "struct constructor" call with constant parameters. The stack copy could be elided when the method is inlined, of course. (Which isn't all that unlikely to happen, since struct methods can't be virtual)
Yes, you are correct. It could do this. It makes sense too, thanks for pointing it out :) however, I'm still against pure as a keyword if structs can be manifest constants because it implies that the struct can only call pure methods, which is too limited in my opinion.
 I think this could be averted if the 'this' portion of a struct was not 
 passed by reference, but passed by value.  Maybe there should be a way to 
 define whether 'this' is a pointer or a value?  This would also allow 
 operators to be used in constant expressions (one of the problems with 
 using a struct as a replacement for a math type).
So opAdd & friends aren't CTFE'd? That seems like a silly omission, and should be easy enough to fix. No need to pass 'this' by value.
From the CTFE description: 4. the function may not be a non-static member, i.e. it may not have a this pointer I'm all for changing that, but I'm guessing Walter had a reason to specify it that way :) If the CTFE engine just did what you said above (make a copy of the constant on the stack, and pass the pointer to that), I think it would work! -Steve
Dec 11 2007
prev sibling next sibling parent reply Robert Fraser <fraserofthenight gmail.com> writes:
Don Clugston wrote:
 IIRC, there was a suggestion at the conference that D would get a new 
 reserved word, 'pure', for functional programming. This should be 
 considered as an alternative to 'enum'. I really don't like the idea of
 
 enum SomeEnormousStruct a = SomeFunction(AnotherEnormousStruct(x, "abc"));
 
 (and my CTFE code is already full of this sort of thing. It's simply not 
 true that 'enums' would mostly be integral types).
 
 Seems to fit with the idea of 'having no side-effects' - a pure value 
 would not be stored anywhere, and make no contribution to the size of 
 the executable.
 
 pure real pi = 3.141592564;
 
 // this is really silly if you use 'enum' instead.
 pure real myNaN = real.nan;
 
 BTW, a pure function taking only pure parameters returns a pure value, 
 so this seems to be entirely consistent:
 
 pure int foo(int a, int b);
Hmmm... It's not a bad idea, but (like with enum & final), this worries me: pure { int x = 5; // Manifest Constant void func() { } // Function without side effects }
Dec 11 2007
next sibling parent "Janice Caron" <caron800 googlemail.com> writes:
On 12/11/07, Robert Fraser <fraserofthenight gmail.com> wrote:
 Hmmm... It's not a bad idea, but (like with enum & final), this worries me:

 pure
 {
      int x = 5;      // Manifest Constant
      void func() { } // Function without side effects
 }
That's not really worrying at all. Think of it like this pure int x() = 5; A function without side-effects. And since you can't take the address, what's the difference?
Dec 11 2007
prev sibling parent "Janice Caron" <caron800 googlemail.com> writes:
On Dec 11, 2007 10:05 PM, Janice Caron <caron800 googlemail.com> wrote:
 On 12/11/07, Robert Fraser <fraserofthenight gmail.com> wrote:
 Hmmm... It's not a bad idea, but (like with enum & final), this worries me:

 pure
 {
      int x = 5;      // Manifest Constant
      void func() { } // Function without side effects
 }
That's not really worrying at all. Think of it like this pure int x() = 5;
Guess I should have written pure int x() { return 5; } but you get the idea. If you're not allowed to take the address, then x the function behaves exactly like x the constant. That being so, I see no problem with using the same keyword for both. It seems appropriate somehow. In both cases, there are no side-effects.
Dec 11 2007
prev sibling next sibling parent Tom <tom nospam.com> writes:
Don Clugston escribió:
 IIRC, there was a suggestion at the conference that D would get a new 
 reserved word, 'pure', for functional programming. This should be 
 considered as an alternative to 'enum'.
 [clipped]
myVote++; -- Tom;
Dec 11 2007
prev sibling next sibling parent Alexander Panek <alexander.panek brainsware.org> writes:
On Tue, 11 Dec 2007 09:33:40 +0100
Don Clugston <dac nospam.com.au> wrote:

 Seems to fit with the idea of 'having no side-effects' - a pure value
 would not be stored anywhere, and make no contribution to the size of
 the executable.
 
 pure real pi = 3.141592564;
 
 // this is really silly if you use 'enum' instead.
 pure real myNaN = real.nan;
 
 BTW, a pure function taking only pure parameters returns a pure
 value, so this seems to be entirely consistent:
 
 pure int foo(int a, int b);
I like that very much. -- Alexander Panek <alexander.panek brainsware.org>
Dec 12 2007
prev sibling next sibling parent Russell Lewis <webmaster villagersonline.com> writes:
vote++
Dec 12 2007
prev sibling next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Don Clugston" <dac nospam.com.au> wrote in message 
news:fjli16$1efd$1 digitalmars.com...
 IIRC, there was a suggestion at the conference that D would get a new 
 reserved word, 'pure', for functional programming. This should be 
 considered as an alternative to 'enum'. I really don't like the idea of

 enum SomeEnormousStruct a = SomeFunction(AnotherEnormousStruct(x, "abc"));

 (and my CTFE code is already full of this sort of thing. It's simply not 
 true that 'enums' would mostly be integral types).

 Seems to fit with the idea of 'having no side-effects' - a pure value 
 would not be stored anywhere, and make no contribution to the size of the 
 executable.

 pure real pi = 3.141592564;

 // this is really silly if you use 'enum' instead.
 pure real myNaN = real.nan;

 BTW, a pure function taking only pure parameters returns a pure value, so 
 this seems to be entirely consistent:

 pure int foo(int a, int b);
Votity vote vote vote!
Dec 12 2007
prev sibling parent reply Hxal <hxal freenode.d.channel> writes:
Don Clugston Wrote:

 pure real pi = 3.141592564;
 ...
 pure int foo(int a, int b);
Greetings fellow D community members. (since this is my first post.) I'm not terribly fond of either the enum or the pure idea. Perhaps this discussion is the perfect opportunity to revise the use of alias declarations. Suppose we changed the alias syntax to the form of "alias x = y;" We could amend its semantics to allow aliasing of values which would give us what this discussions seems to be about - named values taking no memory space. If we wanted to be able to specify the type we could further change the syntax to either "alias optionaltype x = y;" or "optionaltype alias x = y;". As far as pure functions go I guess the new alias could enable declaring a named function literal: "alias foo = function int(int a, int b) {...};"; however I'd like to turn the attention of the community to the nifty pragma statement, which I find underused. Pragmas can be an excellent way to provide hints to the compiler without introducing new syntax, ie: pragma (pure, functionname); pragma (inline, functionname); or even pragma (pure); inside the function body. PS. My fondness of pragmas comes from my Ada programming background.
Dec 12 2007
next sibling parent reply Gilles G. <schaouette free.fr> writes:
"alias" does not express the intent of the definition.
For example, when writing "alias foo = function int(int a, int b) {...};", the
fact that the function does not have side effects is not explicit.
The expressions
pure real pi=3.14159;
pure real A = area(real diameter);
are much more informative.

Hxal Wrote:

 Don Clugston Wrote:
 
 pure real pi = 3.141592564;
 ...
 pure int foo(int a, int b);
Greetings fellow D community members. (since this is my first post.) I'm not terribly fond of either the enum or the pure idea. Perhaps this discussion is the perfect opportunity to revise the use of alias declarations. Suppose we changed the alias syntax to the form of "alias x = y;" We could amend its semantics to allow aliasing of values which would give us what this discussions seems to be about - named values taking no memory space. If we wanted to be able to specify the type we could further change the syntax to either "alias optionaltype x = y;" or "optionaltype alias x = y;". As far as pure functions go I guess the new alias could enable declaring a named function literal: "alias foo = function int(int a, int b) {...};"; however I'd like to turn the attention of the community to the nifty pragma statement, which I find underused. Pragmas can be an excellent way to provide hints to the compiler without introducing new syntax, ie: pragma (pure, functionname); pragma (inline, functionname); or even pragma (pure); inside the function body. PS. My fondness of pragmas comes from my Ada programming background.
Dec 12 2007
parent Hxal <hxal freenode.d.channel> writes:
Gilles G. Wrote:

 "alias" does not express the intent of the definition.
 For example, when writing "alias foo = function int(int a, int b) {...};", the
fact that the function does not have side effects is not explicit.
 The expressions
 pure real pi=3.14159;
 pure real A = area(real diameter);
 are much more informative.
You're right, this one doesn't. A pure pragma suits function definitions a lot better though. I realized after I wrote the first suggestion that you can even write "pragma(pure) int foo (...) {}". As for using an alias declaration for constants, it's no less informative than a pure constant declaration, except it doesn't introduce a new keyword, nor does it reuse an existing one in a non-obvious way (enum).
Dec 12 2007
prev sibling parent reply Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
Hxal wrote:
 Don Clugston Wrote:
 
 pure real pi = 3.141592564;
 ...
 pure int foo(int a, int b);
I don't think pure is the optimal solution, but it is much better than enum and I could definitely live with it.
 Greetings fellow D community members. (since this is my first post.)
 
 I'm not terribly fond of either the enum or the pure idea.
 
 Perhaps this discussion is the perfect opportunity to revise the use of alias
 declarations. Suppose we changed the alias syntax to the form of "alias x = y;"
 We could amend its semantics to allow aliasing of values which would give us
 what this discussions seems to be about - named values taking no memory space.
 
 If we wanted to be able to specify the type we could further change the syntax
 to either "alias optionaltype x = y;" or "optionaltype alias x = y;".
I agree. It feels like lately, the design of D has left that of the free outside-the-box thinker and attained a C++ mindset where simplicity and elegance is rendered irrelevant. I hope I am wrong. :) -- Oskar
Dec 13 2007
parent Sean Kelly <sean f4.ca> writes:
Oskar Linde wrote:
 
 It feels like lately, the design of D has left that of the free 
 outside-the-box thinker and attained a C++ mindset where simplicity and 
 elegance is rendered irrelevant. I hope I am wrong. :)
I think this is inevitable as the popularity of a language increases and breaking changes becomes less and less appealing. But I am hoping we can hold that day off as long as possible. Still the presence of things like foreach_reverse suggest that it may already be here ;-) Sean
Dec 13 2007