www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Conditional Pure?

reply %u <wfunction hotmail.com> writes:
I wanted to suggest a feature similar to inout: conditional purity. That is,
sometimes a function is pure iff the delegates passed to it are pure, and as
of right now, I don't think there's any way to document this other than by
overloading the function as a template (which results in lots of code
duplication).

The idea would be to make this a bit more general than just a particular fix
for "pure", though, since if in the future, new qualifiers arise (I guess this
might also work for  trusted and such), then the solution should work for
those too.
Jan 22 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
%u Wrote:

 I wanted to suggest a feature similar to inout: conditional purity. That is,
 sometimes a function is pure iff the delegates passed to it are pure,

I think this is useless. If this is possible, then you just mark every single not-pure function in the program with conditionally_pure, and we are back to the beginning. Bye, bearophile
Jan 22 2011
next sibling parent reply %u <wfunction hotmail.com> writes:
 I think this is useless. If this is possible, then you just mark every single

beginning. Oh, but that's not what I meant! I meant something like this: int call(TFn)(TFn fn) pure(isPure!(TFn)) if (isCallable!(TFn)) { return fn(5); } This way we specify purity based on a static boolean.
Jan 22 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
%u:

 Oh, but that's not what I meant! I meant something like this:
 
   int call(TFn)(TFn fn) pure(isPure!(TFn))
      if (isCallable!(TFn))
   {
      return fn(5);
   }
 
 This way we specify purity based on a static boolean.

I see. I'd like a more general-purpose solution, something that works with nothrow too and other future attributes too. So I have suggested: http://d.puremagic.com/issues/show_bug.cgi?id=5125 Bye, bearophile
Jan 22 2011
parent reply %u <wfunction hotmail.com> writes:
 I see. I'd like a more general-purpose solution, something that works with

Funny, that was going to be my next comment. :) The only thing that scares me a bit is that code like this: public(isPublic!(TFn)) static(isStatic!(TFn)) int memoize(TFn)(TFn fn) pure(isPure!(TFn)) if (isCallable!(TFn)) { //etc. } might turn out a bit unreadable. And, furthermore, I'd *like* to be able to say something like "this method returns a shared const value iff the given type is int or long" but this won't work with const() or shared() because of their syntax (you can't say const(is(T == int))). Any ideas on how we might be able to get that to work? Oh, and while on the note of const, here's a somewhat unrelated concern: I've noticed that code like this: static const int* addressOf(ref int x) { return &x; } is *very* tricky and misleading, because it's declaring the method as const, not the pointer. Would it be a bad idea to forbid const, pure, nothrow, and the like from coming before the method name? That way it won't be ambiguous like this.
Jan 22 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
%u:

 might turn out a bit unreadable. And, furthermore, I'd *like* to be able to say
 something like "this method returns a shared const value iff the given type is
int
 or long" but this won't work with const() or shared() because of their syntax
(you
 can't say const(is(T == int))). Any ideas on how we might be able to get that
to work?

optional_tag(is(T == int) || is(T == long)), const)
 Oh, and while on the note of const, here's a somewhat unrelated concern: I've
 noticed that code like this:
 
 static const int* addressOf(ref int x) { return &x; }
 
 is *very* tricky and misleading, because it's declaring the method as const,
not
 the pointer. Would it be a bad idea to forbid const, pure, nothrow, and the
like
 from coming before the method name? That way it won't be ambiguous like this.

I and few other people have asked for this, I think there is one closed enhancement request on this in Bugzilla, but I think Walter closed it on the basis of uniformity in attribute syntax (and maybe compiler simplicity too). Sometimes it's worth breaking uniformity if this avoids some troubles, especially if all this breakage does is creating some easy-to-fix compile-time errors. I think this is one of such cases. Bye, bearophile
Jan 22 2011
parent reply %u <wfunction hotmail.com> writes:
 Any ideas on how we might be able to get that to work?


Ouch... a bit less pretty than I'd hoped (the underscore makes it a bit ugly IMHO). Does it really need to be a tag, though? Why not just: optional(const, is(T == int) || is(T == long)) ?
 I and few other people have asked for this, I think there is one closed

of uniformity in attribute syntax (and maybe compiler simplicity too).
 Sometimes it's worth breaking uniformity if this avoids some troubles,

errors. I think this is one of such cases. Huh... but what's the difference between "static" and "const", that allows "const" to go after the header but doesn't allow "static" to?
Jan 22 2011
parent Michel Fortin <michel.fortin michelf.com> writes:
On 2011-01-22 21:34:52 -0500, %u <wfunction hotmail.com> said:

 Any ideas on how we might be able to get that to work?


Ouch... a bit less pretty than I'd hoped (the underscore makes it a bit ugly IMHO). Does it really need to be a tag, though? Why not just: optional(const, is(T == int) || is(T == long)) ?

If you're trying to make it pretty, I'd suggest this: template func(T) { const pure if (is(T == int) || is(T == long)) { void func(T); } } From what I know of the front end, I'm of the opinion that it'd be much easier to implement conditional attributes in the front end that way. But things gets messed up once you consider the 'static' attribute. :-( -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jan 22 2011
prev sibling next sibling parent so <so so.do> writes:
 nothrow too and other future attributes too.

 Funny, that was going to be my next comment. :)
 The only thing that scares me a bit is that code like this:

 public(isPublic!(TFn)) static(isStatic!(TFn)) int memoize(TFn)(TFn fn)
     pure(isPure!(TFn))
     if (isCallable!(TFn))
 {
     //etc.
 }

A question, Is this the only use case? I mean do we always want something like "xxx(isxxx(T))"? If so, this mess is quite pointless.
Jan 22 2011
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday 22 January 2011 14:41:08 %u wrote:
 I think this is useless. If this is possible, then you just mark every
 single

not-pure function in the program with conditionally_pure, and we are back to the beginning. Oh, but that's not what I meant! I meant something like this: int call(TFn)(TFn fn) pure(isPure!(TFn)) if (isCallable!(TFn)) { return fn(5); } This way we specify purity based on a static boolean.

This has been suggested a time or two (I _definitely_ want something like this, and I think that we _need_ it if we want pure to be truly, generally useful), but nothing has come of it yet. Andrei's suggestion the last time this came up was to do something similar to what you have there and make pure take a conditional argument to determine its purity. I don't know what it will take to get something like this in the language (I think that it's a given that it will have to wait untill after th 64-bit port is done), but I think that it's critical if we want purity to work with templates. And since so much of D is likely to be templatized (in particular, Phobos uses templates quite heavily), we _need_ purity to work with templates. - Jonathan M Davis
Jan 22 2011