Re: It seems pure ain't so pure after all

2012-10-07 Thread Marco Leise
Am Tue, 02 Oct 2012 09:38:56 +0200
schrieb Don Clugston d...@nospam.com:

 Any code that behaves differently when compiled with -O, will do this as 
 well. Constant folding of floating point numbers does the same thing, if 
 the numbers are represented in the compiler in a different precision to 
 how the machine calculates them. I believe that GCC, for example, uses 
 very much higher precision (hundreds of bits) at compile time.

I'm not an expert, but I would have thought compilers
strive to be IEEE compliant - whatever that means in detail.
I've seen a compression algorithm that relies on exact
floating-point semantics and accuracy. It would just fail,
if compilers were creative or lax at certain optimization
levels. (excluding the I know what I am doing -ffast-math.)

-- 
Marco



Re: It seems pure ain't so pure after all

2012-10-04 Thread Tommi

On Tuesday, 2 October 2012 at 01:00:25 UTC, Walter Bright wrote:


Since all you need to do to guarantee compile time evaluation 
is use it in a context that requires CTFE, which are exactly 
the cases where you'd care that it was CTFE'd, I just don't see 
much utility here.


I suppose the most common use case would be efficient struct 
literals which are essentially value types but have non-trivial 
constructors.


struct Law
{
ulong _encodedId;

this(string state, int year) @aggressive_ctfe
{
// non-trivial constructor sets _encodedId
// ...
}
}

Policy policy = getPolicy();

if( policy.isLegalAccordingTo(Law(Kentucky, 1898)) )
{
// ...
}

I think the function attribute would be the most convenient 
solution.



Note that it is also impossible in the general case for the 
compiler to guarantee that a specific function is CTFE'able for 
all arguments that are also CTFE'able.


I'll have to take your word for it for not knowing enough 
(anything) about the subject.


Re: It seems pure ain't so pure after all

2012-10-02 Thread foobar

On Monday, 1 October 2012 at 22:47:48 UTC, Timon Gehr wrote:



A D compiler is also a D interpreter. I wouldn't even bother 
with D if this wasn't the case.


A D compiler _contains_ a limited interpreter for constant 
expression evaluation. This has limitations such as not being 
able to perform IO at compile-time (there's a special pragma for 
that). This is merely an outgrowth of a compiler optimization 
technique.


Now, back on topic:
I agree with Jonathan - in general the compiler can't evaluate 
_all_ functions at-compile time due these limitations of CTFE and 
adding a compiler flag will make compilation times far worse than 
c++. Adding a function attribute adds marginal benefit over 
simply assigning to a static/enum variable.


Re: It seems pure ain't so pure after all

2012-10-02 Thread Don Clugston

On 01/10/12 07:40, Tommi wrote:

import std.stdio;

int pow2(int val) pure
{
 if (__ctfe)
 return 6;
 else
 return val * val;
}

void main()
{
assert(pow2(3) == 9);
 static assert(pow2(3) == 6);

 writeln(9 = 6 ... I knew it! '6' was faking it all along);
 readln();
}


You don't need the if (__ctfe) to show this behaviour. Nor do you even 
need CTFE at all (though it would be a bit less obvious). You could 
demonstrate it in C++ too.


Any code that behaves differently when compiled with -O, will do this as 
well. Constant folding of floating point numbers does the same thing, if 
the numbers are represented in the compiler in a different precision to 
how the machine calculates them. I believe that GCC, for example, uses 
very much higher precision (hundreds of bits) at compile time.








Re: It seems pure ain't so pure after all

2012-10-01 Thread Tommi
On Monday, 1 October 2012 at 05:43:39 UTC, Alex Rønne Petersen 
wrote:


As far as purity goes, pow2 *is* pure. ...


According to http://en.wikipedia.org/wiki/Pure_function it's not:

The [pure] function always evaluates the same result value given 
the same argument value(s)


Re: It seems pure ain't so pure after all

2012-10-01 Thread Jonathan M Davis
On Monday, October 01, 2012 07:43:59 Alex Rønne Petersen wrote:
 This is a corner case.
 
 __ctfe is there to allow special-cased CTFE code when absolutely
 necessary. By necessity, this separates a function into two worlds:
 compile time and run time.
 
 As far as purity goes, pow2 *is* pure. It just does something different
 depending on whether you run it at compile time or run time. I don't see
 this as a problem in practice.

It would be kind of like complaining that a pure function returns different 
values on Linux and Windows due to a version statement or static if. It's just 
that in the thing that varies is compile time vs runtime not the target 
machine. e.g.

int func(int val) pure
{
version(linux)
return val + 2;
else version(Windows)
return val + 3;
}

- Jonathan M Davis


Re: It seems pure ain't so pure after all

2012-10-01 Thread Jonathan M Davis
On Monday, October 01, 2012 07:58:39 Tommi wrote:
 On Monday, 1 October 2012 at 05:43:39 UTC, Alex Rønne Petersen
 
 wrote:
  As far as purity goes, pow2 *is* pure. ...
 
 According to http://en.wikipedia.org/wiki/Pure_function it's not:
 
 The [pure] function always evaluates the same result value given
 the same argument value(s)

Forget what Wikipedia says about pure. If you focus on that, you're going to 
be complaining about D's pure left and right, because what it's talking about 
and what D does are related but very different. D takes a very practical 
approach to functional purity. You should read this:

http://stackoverflow.com/questions/8572399

- Jonathan M Davis


Re: It seems pure ain't so pure after all

2012-10-01 Thread Tommi

On Monday, 1 October 2012 at 06:01:24 UTC, Jonathan M Davis wrote:


It would be kind of like complaining that a pure function 
returns different
values on Linux and Windows due to a version statement or 
static if. It's just
that in the thing that varies is compile time vs runtime not 
the target

machine. e.g.



Actually... let's not even worry about the definition of the word 
'pure'. Let's just ask ourselves: do we really want to live in a 
world where people can write code like that:


void main()
{
auto x = pow2(3);
enum y = pow2(3);

assert(x == y + 3);

writeln(Take that mr. \math\ professor!);
readln();
}


Re: It seems pure ain't so pure after all

2012-10-01 Thread Brad Roberts
On 9/30/2012 11:09 PM, Tommi wrote:
 On Monday, 1 October 2012 at 06:01:24 UTC, Jonathan M Davis wrote:

 It would be kind of like complaining that a pure function returns different
 values on Linux and Windows due to a version statement or static if. It's 
 just
 that in the thing that varies is compile time vs runtime not the target
 machine. e.g.
 
 
 Actually... let's not even worry about the definition of the word 'pure'. 
 Let's just ask ourselves: do we really want to
 live in a world where people can write code like that:
 
 void main()
 {
 auto x = pow2(3);
 enum y = pow2(3);
 
 assert(x == y + 3);
 
 writeln(Take that mr. \math\ professor!);
 readln();
 }

So, Tommi, do you have a suggestion or proposal to make or are you just trying 
to point and snicker?  There's a
multitude of ways that bad programmers can write bad code.


Re: It seems pure ain't so pure after all

2012-10-01 Thread Jonathan M Davis
On Monday, October 01, 2012 08:09:38 Tommi wrote:
 On Monday, 1 October 2012 at 06:01:24 UTC, Jonathan M Davis wrote:
  It would be kind of like complaining that a pure function
  returns different
  values on Linux and Windows due to a version statement or
  static if. It's just
  that in the thing that varies is compile time vs runtime not
  the target
  machine. e.g.
 
 Actually... let's not even worry about the definition of the word
 'pure'. Let's just ask ourselves: do we really want to live in a
 world where people can write code like that:
 
 void main()
 {
  auto x = pow2(3);
  enum y = pow2(3);
 
  assert(x == y + 3);
 
  writeln(Take that mr. \math\ professor!);
  readln();
 }

Then don't write a function which claims to square a value and does something 
else. That's just bad naming. No language is going to prevent programmers from 
being idiots.

A function which uses __ctfe should probably do essentially the same thing at 
both runtime and compile time, but it _has_ __ctfe, because the runtime 
implementation won't work at compile time, and it's up to the programmer to 
make sure that the function does what it's supposed to at both compile time 
and runtime. The compiler can't possibly enforce that.

- Jonathan M Davis


Re: It seems pure ain't so pure after all

2012-10-01 Thread Tommi

On Monday, 1 October 2012 at 06:13:51 UTC, Brad Roberts wrote:


So, Tommi, do you have a suggestion or proposal to make or are 
you just trying to point and snicker?  There's a

multitude of ways that bad programmers can write bad code.


I can't provide a solution until we've agreed that there is a 
problem.


Re: It seems pure ain't so pure after all

2012-10-01 Thread Tommi

On Monday, 1 October 2012 at 06:18:48 UTC, Jonathan M Davis wrote:


A function which uses __ctfe should probably do essentially the 
same thing at
both runtime and compile time, but it _has_ __ctfe, because the 
runtime
implementation won't work at compile time, and it's up to the 
programmer to
make sure that the function does what it's supposed to at both 
compile time

and runtime. The compiler can't possibly enforce that.


Thus we're in a situation where pure means pure only by 
convention, not because it's enforced by the compiler. It's like 
const in c++ then, it's const only by convention, only because 
people promise that they're not going to mutate it. I don't like 
rules that are enforced only by everybody relying on good manners.




Re: It seems pure ain't so pure after all

2012-10-01 Thread Jonathan M Davis
On Monday, October 01, 2012 08:25:39 Tommi wrote:
 On Monday, 1 October 2012 at 06:18:48 UTC, Jonathan M Davis wrote:
  A function which uses __ctfe should probably do essentially the
  same thing at
  both runtime and compile time, but it _has_ __ctfe, because the
  runtime
  implementation won't work at compile time, and it's up to the
  programmer to
  make sure that the function does what it's supposed to at both
  compile time
  and runtime. The compiler can't possibly enforce that.
 
 Thus we're in a situation where pure means pure only by
 convention, not because it's enforced by the compiler. It's like
 const in c++ then, it's const only by convention, only because
 people promise that they're not going to mutate it. I don't like
 rules that are enforced only by everybody relying on good manners.

No. We're not in that situation at all. The function will do the same thing 
with every call at compile time, and it will do the same thing with every call 
at runtime. It's like you're complaining about the fact that a function on a 
big endian machine doesn't do exactly the same thing as when it's compiled for 
a little endian machine. It's being compiled for a different environment, so 
its behavior can change. __ctfe really isn't all that different from static if 
or version blocks which effectively result in different functions depending on 
how or where the code is compiled.

What isn't enforced is that the function does the same thing at compile time 
as at runtime, and you can't enforce that any more than you can enforce that 
it does the same thing on one machine as another when they have different 
architectures or OSes or whatot. By using __ctfe, you are providing an 
alternate implementation for compile time just like you could provide 
alternate implementations for different OSes or architectures.

- Jonathan M Davis


Re: It seems pure ain't so pure after all

2012-10-01 Thread Jonathan M Davis
On Sunday, September 30, 2012 23:38:43 Jonathan M Davis wrote:
 On Monday, October 01, 2012 08:25:39 Tommi wrote:
  Thus we're in a situation where pure means pure only by
  convention, not because it's enforced by the compiler. It's like
  const in c++ then, it's const only by convention, only because
  people promise that they're not going to mutate it. I don't like
  rules that are enforced only by everybody relying on good manners.
 
 No. We're not in that situation at all. The function will do the same thing
 with every call at compile time, and it will do the same thing with every
 call at runtime. It's like you're complaining about the fact that a
 function on a big endian machine doesn't do exactly the same thing as when
 it's compiled for a little endian machine. It's being compiled for a
 different environment, so its behavior can change. __ctfe really isn't all
 that different from static if or version blocks which effectively result in
 different functions depending on how or where the code is compiled.
 
 What isn't enforced is that the function does the same thing at compile time
 as at runtime, and you can't enforce that any more than you can enforce
 that it does the same thing on one machine as another when they have
 different architectures or OSes or whatot. By using __ctfe, you are
 providing an alternate implementation for compile time just like you could
 provide alternate implementations for different OSes or architectures.

While __ctfe is not used in a static if, that's effectively the behavior that 
it has. You're basically complaining about how these two functions don't 
return the same value:

static if(__ctfe)
{
int pow2(int val) pure
{
return 6;
}
}
else
{
int pow2(int val) pure
{
return val * val;
}
}

They're effectively completely different functions that share the same name 
(and 
presumably the same intent), but they're implementations are different, and 
it's obviously up to the programmer to make sure that they do what they're 
supposed to do. It has _nothing_ to do with pure.

- Jonathan M Davis


Re: It seems pure ain't so pure after all

2012-10-01 Thread Andrei Alexandrescu

On 10/1/12 2:19 AM, Tommi wrote:

On Monday, 1 October 2012 at 06:13:51 UTC, Brad Roberts wrote:


So, Tommi, do you have a suggestion or proposal to make or are you
just trying to point and snicker? There's a
multitude of ways that bad programmers can write bad code.


I can't provide a solution until we've agreed that there is a problem.


Don't want to sound dismissive, but the short answer is there is no problem.

Andrei


Re: It seems pure ain't so pure after all

2012-10-01 Thread Tommi
I'll have to consider all functions potentially schizophrenic 
then. They might do one thing at compile-time and another at 
run-time.


I was going to make a feature request to add a compiler flag for 
making more functions execute at compile-time than those which 
the compiler *has* to. But this __ctfe thing renders that 
impossible.




Re: It seems pure ain't so pure after all

2012-10-01 Thread Jonathan M Davis
On Monday, October 01, 2012 09:46:43 Tommi wrote:
 I'll have to consider all functions potentially schizophrenic
 then. They might do one thing at compile-time and another at
 run-time.

That's only the case if they're buggy, so that's pretty much the same as 
considering all functions potentially buggy.

 I was going to make a feature request to add a compiler flag for
 making more functions execute at compile-time than those which
 the compiler *has* to. But this __ctfe thing renders that
 impossible.

I have no idea how you could possibly use a compiler flag for that, whether 
__ctfe or not. It really doesn't make sense to try and make functions in 
general run at compile time. Most of the time, functions need to be run at 
runtime, otherwise you wouldn't even need to generate an executable, just a 
result. And you _can't_ determine ahead of time which functions can be safely 
executed at compile time either, because that's an instance of the halting 
problem. So, it really doesn't make sense to have the compiler trying to 
evaluate functions at compile time when it hasn't been explicitly told to.

And it works just fine to assign the result of a function call to enum if you 
want a specific function call to be executed at compile time, so I really don't 
think that this is an issue anyway.

- Jonathan M Davis


Re: It seems pure ain't so pure after all

2012-10-01 Thread Jakob Ovrum

On Monday, 1 October 2012 at 06:25:19 UTC, Tommi wrote:
On Monday, 1 October 2012 at 06:18:48 UTC, Jonathan M Davis 
wrote:


A function which uses __ctfe should probably do essentially 
the same thing at
both runtime and compile time, but it _has_ __ctfe, because 
the runtime
implementation won't work at compile time, and it's up to the 
programmer to
make sure that the function does what it's supposed to at both 
compile time

and runtime. The compiler can't possibly enforce that.


Thus we're in a situation where pure means pure only by 
convention, not because it's enforced by the compiler. It's 
like const in c++ then, it's const only by convention, only 
because people promise that they're not going to mutate it. I 
don't like rules that are enforced only by everybody relying on 
good manners.


The only real problem here is that you wrote a function called 
pow2 that effectively returns 6 unconditionally. I doubt your 
math professor would be particularly impressed. If you had used 
__ctfe properly, it would return the same value both at 
compile-time and runtime. At present, __ctfe is a necessary evil 
as CTFE can be severely crippled without it.




Re: It seems pure ain't so pure after all

2012-10-01 Thread deadalnix

Le 01/10/2012 08:07, Jonathan M Davis a écrit :

On Monday, October 01, 2012 07:58:39 Tommi wrote:

On Monday, 1 October 2012 at 05:43:39 UTC, Alex Rønne Petersen

wrote:

As far as purity goes, pow2 *is* pure. ...


According to http://en.wikipedia.org/wiki/Pure_function it's not:

The [pure] function always evaluates the same result value given
the same argument value(s)


Forget what Wikipedia says about pure. If you focus on that, you're going to
be complaining about D's pure left and right, because what it's talking about
and what D does are related but very different. D takes a very practical
approach to functional purity. You should read this:

http://stackoverflow.com/questions/8572399

- Jonathan M Davis


Or that : http://klickverbot.at/blog/2012/05/purity-in-d/


Re: It seems pure ain't so pure after all

2012-10-01 Thread Steven Schveighoffer

On Mon, 01 Oct 2012 01:40:37 -0400, Tommi tommitiss...@hotmail.com wrote:


import std.stdio;

int pow2(int val) pure
{
 if (__ctfe)
 return 6;
 else
 return val * val;
}

void main()
{
assert(pow2(3) == 9);
 static assert(pow2(3) == 6);

 writeln(9 = 6 ... I knew it! '6' was faking it all along);
 readln();
}


You have a bug in your code, here let me fix that for you:


int pow2(int val) pure
{
return val * val;
}


OK, on to the next thread...

-Steve


Re: It seems pure ain't so pure after all

2012-10-01 Thread Tommi

On Monday, 1 October 2012 at 08:04:49 UTC, Jonathan M Davis wrote:
And you _can't_ determine ahead of time which functions can be 
safely executed at compile time either, because that's an

instance of the halting problem.


I don't understand (I did read what halting problem means just 
now, but I still don't understand). If there was no __ctfe 
variable, and thus a guarantee that all functions do the same 
thing at compile-time and run-time, couldn't the compiler just 
try aggressively to execute all function calls at compile-time? 
Obviously it wouldn't bother trying CTFE for function calls that 
had arguments which weren't evaluable at compile-time. Nor would 
it bother with functions that it knows have memory allocations or 
other limitations of CTFE.


If not a compiler flag, then it could be a function attribute. 
Just like c++ function attribute constexpr, which guarantees that 
the function executes at compile time given you provide it with 
compile-time evaluable arguments (and there are limitations to 
what the function can do). Why wouldn't this attribute be 
possible with D?


Re: It seems pure ain't so pure after all

2012-10-01 Thread Tommi

On Monday, 1 October 2012 at 08:00:47 UTC, Jakob Ovrum wrote:


The only real problem here is that you wrote a function called 
pow2 that effectively returns 6 unconditionally. I doubt your 
math professor would be particularly impressed. If you had used 
__ctfe properly, it would return the same value both at 
compile-time and runtime. At present, __ctfe is a necessary 
evil as CTFE can be severely crippled without it.


I solemnly swear not to use __ctfe improperly. But my problem 
with it is, that there *exists* the possibility of improper use 
of __ctfe.


Plus, I just realized, I've never actually met any math 
professor. I never went to a university (nor study programming 
for that matter).


Re: It seems pure ain't so pure after all

2012-10-01 Thread foobar

On Monday, 1 October 2012 at 17:46:00 UTC, Tommi wrote:
On Monday, 1 October 2012 at 08:04:49 UTC, Jonathan M Davis 
wrote:
And you _can't_ determine ahead of time which functions can be 
safely executed at compile time either, because that's an

instance of the halting problem.


I don't understand (I did read what halting problem means 
just now, but I still don't understand). If there was no __ctfe 
variable, and thus a guarantee that all functions do the same 
thing at compile-time and run-time, couldn't the compiler just 
try aggressively to execute all function calls at compile-time? 
Obviously it wouldn't bother trying CTFE for function calls 
that had arguments which weren't evaluable at compile-time. Nor 
would it bother with functions that it knows have memory 
allocations or other limitations of CTFE.


If not a compiler flag, then it could be a function attribute. 
Just like c++ function attribute constexpr, which guarantees 
that the function executes at compile time given you provide it 
with compile-time evaluable arguments (and there are 
limitations to what the function can do). Why wouldn't this 
attribute be possible with D?


__ctfe is a horrible yet very useful hack to address the 
underlying issue - the execution model for CTFE, which I 
personally do not agree with. Adding a compiler flag for the 
existing model, makes no sense whatsoever. Functions are 
essentially a run-time abstraction and the compiler generally 
speaking has no business trying to execute them at compile-time. 
The compiler is after all *not* an interpreter.


Besides, what would be the use case for such a flag anyway? If 
you already know that all parameters are known at compile-time, 
you can already tell the compiler to execute the function by 
assigning to a static/enum variable.


IMO, this mixing of code for various stages of execution is bad 
design but this cannot be changed in a backwards compatible way.


Re: It seems pure ain't so pure after all

2012-10-01 Thread Jesse Phillips

On Monday, 1 October 2012 at 06:09:18 UTC, Tommi wrote:

Actually... let's not even worry about the definition of the 
word 'pure'. Let's just ask ourselves: do we really want to 
live in a world where people can write code like that:


Yes, yes we do, because if we didn't there wouldn't be a _ctfe to 
make this possible.


Re: It seems pure ain't so pure after all

2012-10-01 Thread Graham Fawcett

On Monday, 1 October 2012 at 17:53:35 UTC, Tommi wrote:

On Monday, 1 October 2012 at 08:00:47 UTC, Jakob Ovrum wrote:


The only real problem here is that you wrote a function called 
pow2 that effectively returns 6 unconditionally. I doubt your 
math professor would be particularly impressed. If you had 
used __ctfe properly, it would return the same value both at 
compile-time and runtime. At present, __ctfe is a necessary 
evil as CTFE can be severely crippled without it.


I solemnly swear not to use __ctfe improperly. But my problem 
with it is, that there *exists* the possibility of improper use 
of __ctfe.


Can you name a programming language that supports CTFE, but 
doesn't allow the possibility of misuse?


Actually, can you name any language with a safety or purity 
feature that cannot be thwarted by a motivated programmer?


To echo Jonathan's sentiment, no programming language can stop a 
programmer who is determined to write stupid code from doing so.


For the sake of discussion, here's an example of a pure function 
in Haskell (arguably the purest language in wide use today) 
that happily returns a random integer every time it is called.


import System.IO.Unsafe
import System.Random

pureFunction :: () - Int
pureFunction x = unsafePerformIO impureInside
where impureInside = getStdRandom (randomR (1,6))

main = do
  print (pureFunction ())
  print (pureFunction ())
  print (pureFunction ())

This prints three random integers between 1 and 6 when executed.

-- Graham



Re: It seems pure ain't so pure after all

2012-10-01 Thread Jonathan M Davis
On Monday, October 01, 2012 19:46:16 Tommi wrote:
 On Monday, 1 October 2012 at 08:04:49 UTC, Jonathan M Davis wrote:
  And you _can't_ determine ahead of time which functions can be
  safely executed at compile time either, because that's an
  instance of the halting problem.
 
 I don't understand (I did read what halting problem means just
 now, but I still don't understand). If there was no __ctfe
 variable, and thus a guarantee that all functions do the same
 thing at compile-time and run-time,

__ctfe exists purely so that you can provide an alternate implementation which 
works at compile time when the normal implementation doesn't (since CTFE _is_ 
more restrictive in what it allows than running a function at runtime is).

 couldn't the compiler just
 try aggressively to execute all function calls at compile-time?

So, the compiler is supposed to run every function at compile time and then 
back up if it a function doesn't work? It can't even always know for sure when 
a function doesn't work (e.g. infinite loop). This would absolutely _tank_ 
compilation times. Most functions _can't_ be run at compile time simply 
because of how they're called, and the compiler can't necessarily know that 
unless it does full flow analysis if not outright _runs_ every function, which 
would be _incredibly_ expensive.

 If not a compiler flag, then it could be a function attribute.
 Just like c++ function attribute constexpr, which guarantees that
 the function executes at compile time given you provide it with
 compile-time evaluable arguments (and there are limitations to
 what the function can do). Why wouldn't this attribute be
 possible with D?

CTFE was specifically designed with the idea that you would not need to mark 
functions as CTFEable. You can call _any_ function at compile time. Some will 
fail, because they're doing things that CTFE won't allow, but that's quickly 
caught, because it happens at compile time. It completely avoids needing to 
mark functions as CTFEable all over the place (which would generally mean that 
functions wouldn't be CTFEable, because people would frequently not mark them 
as CTFEable). constexpr is in direct conflict with that design goal.

And if you want a function to be executed at compile time, you assign its 
result to an enum or static variable. Done. It's easy and straightforward. I 
really don't understand why this is an issue at all.

- Jonathan M Davis


Re: It seems pure ain't so pure after all

2012-10-01 Thread Jonathan M Davis
On Monday, October 01, 2012 19:53:53 Tommi wrote:
 I solemnly swear not to use __ctfe improperly. But my problem
 with it is, that there *exists* the possibility of improper use
 of __ctfe.

I could just as easily name a function pow2 and make it return the square 
root. I could overload operator + to do operator -. I could make it so that a 
function does one thing on Linux and does something completely different and 
unreleated on Windows. There are _tons_ of places in programming where the 
programmer has to not be an idiot or their fellow programmers are going to end 
up with tons of pain.

__ctfe is no different from static if or version or any feature which makes it 
so that the block of code is different on different machines, and it's 
generally 
a whale of a lot less error-prone than stuff like endianness issues. It's even 
trivial to use the same unit tests to test that your function does the same 
thing in CTFE as at runtime, which you can test on the same machine, unlike 
with architecture and OS differences.

I really think that you're blowing this way out of proportion. Certainly,
you think that there's a problem here when the rest of us don't.

- Jonathan M Davis


Re: It seems pure ain't so pure after all

2012-10-01 Thread Tommi

On Monday, 1 October 2012 at 18:36:23 UTC, Jonathan M Davis wrote:
CTFE was specifically designed with the idea that you would not 
need to mark functions as CTFEable. You can call _any_ functio
at compile time. Some will fail, because they're doing things 
that CTFE won't allow, but that's quickly caught, because it 
happens at compile time. It completely avoids needing to mark

functions as CTFEable all over the place (which would generally
mean that functions wouldn't be CTFEable, because people would
frequently not mark them as CTFEable). constexpr is in direct
conflict with that design goal.


That's not what I suggested. I meant that all functions would 
still be implicitly CTFEable by default, but an attribute like 
force_ctfe would make it so that the function is guaranteed to 
execute at compile-time when its arguments are compile-time 
constants.


And if you want a function to be executed at compile time, you 
assign its result to an enum or static variable. Done. It's easy

and straightforward. I really don't understand why this is an
issue at all.


The issue to me is complicating the syntax of your code. The 
problem is *having* to assign the result first to an enum, when I 
shouldn't have to. I would like to be able to just say 
fun(times) and be confident that that's going to be evaluated 
at compile-time. I feel like I've done my part of the deal here, 
I provided the compile-time argument, and now I'd expect the 
compiler to do his part and evaluate the function at compile-time 
(if it has that force_ctfe attribute).




Re: It seems pure ain't so pure after all

2012-10-01 Thread Steven Schveighoffer

On Mon, 01 Oct 2012 16:10:48 -0400, Tommi tommitiss...@hotmail.com wrote:


On Monday, 1 October 2012 at 18:36:23 UTC, Jonathan M Davis wrote:
CTFE was specifically designed with the idea that you would not need to  
mark functions as CTFEable. You can call _any_ functio
at compile time. Some will fail, because they're doing things that CTFE  
won't allow, but that's quickly caught, because it happens at compile  
time. It completely avoids needing to mark

functions as CTFEable all over the place (which would generally
mean that functions wouldn't be CTFEable, because people would
frequently not mark them as CTFEable). constexpr is in direct
conflict with that design goal.


That's not what I suggested. I meant that all functions would still be  
implicitly CTFEable by default, but an attribute like force_ctfe would  
make it so that the function is guaranteed to execute at compile-time  
when its arguments are compile-time constants.


And if you want a function to be executed at compile time, you assign  
its result to an enum or static variable. Done. It's easy

and straightforward. I really don't understand why this is an
issue at all.


The issue to me is complicating the syntax of your code. The problem is  
*having* to assign the result first to an enum, when I shouldn't have  
to. I would like to be able to just say fun(times) and be confident  
that that's going to be evaluated at compile-time. I feel like I've done  
my part of the deal here, I provided the compile-time argument, and now  
I'd expect the compiler to do his part and evaluate the function at  
compile-time (if it has that force_ctfe attribute).


We already have that, use templates:

private auto _funimpl(string s) {
/* what was previously in fun(string) */
}

template fun(string s)
{
   enum fun = _funimpl(s);
}

// usage:

fun!(times); // always executes _funimpl at compile time

-Steve


Re: It seems pure ain't so pure after all

2012-10-01 Thread Tommi
On Monday, 1 October 2012 at 20:16:09 UTC, Steven Schveighoffer 
wrote:

We already have that, use templates:

private auto _funimpl(string s) {
/* what was previously in fun(string) */
}

template fun(string s)
{
   enum fun = _funimpl(s);
}

// usage:

fun!(times); // always executes _funimpl at compile time


Yes, I know. And this helps even more:

template ct(alias expr)
{
 enum ct = expr;
}

auto fun(string s)
{
 ...
}

// usage:

ct!(fun(times))

But that's still a nuisance.




Re: It seems pure ain't so pure after all

2012-10-01 Thread jerro

private auto _funimpl(string s) {
/* what was previously in fun(string) */
}

template fun(string s)
{
   enum fun = _funimpl(s);
}

// usage:

fun!(times); // always executes _funimpl at compile time

-Steve


You could even use this template:

template ct(alias f)
{
template ct(params...)
{
enum ct = f(params);
}
}

to define templates like this:

alias ct!((string s)
{
// function body...
}) fun;


or with this syntax:

alias ct!(a = a * a) pow2;





Re: It seems pure ain't so pure after all

2012-10-01 Thread Tommi
It's a lot less work to add one attribute to your function once, 
than to write something extra every time you call that function.




Re: It seems pure ain't so pure after all

2012-10-01 Thread Graham Fawcett

On Monday, 1 October 2012 at 20:30:26 UTC, Tommi wrote:
It's a lot less work to add one attribute to your function 
once, than to write something extra every time you call that 
function.


string exclaim(string v)() {
  return v ~ !;
}

void main() {
  writeln(exclaim!(howdy));
}

Graham



Re: It seems pure ain't so pure after all

2012-10-01 Thread Tommi

On Monday, 1 October 2012 at 20:33:29 UTC, Graham Fawcett wrote:

string exclaim(string v)() {
  return v ~ !;
}

void main() {
  writeln(exclaim!(howdy));
}


It doesn't scale well to have to write both compile-time and 
run-time versions of your functions.


Re: It seems pure ain't so pure after all

2012-10-01 Thread Steven Schveighoffer

On Mon, 01 Oct 2012 16:23:17 -0400, Tommi tommitiss...@hotmail.com wrote:


On Monday, 1 October 2012 at 20:16:09 UTC, Steven Schveighoffer wrote:

We already have that, use templates:

private auto _funimpl(string s) {
/* what was previously in fun(string) */
}

template fun(string s)
{
   enum fun = _funimpl(s);
}

// usage:

fun!(times); // always executes _funimpl at compile time


Yes, I know. And this helps even more:

template ct(alias expr)
{
  enum ct = expr;
}

auto fun(string s)
{
  ...
}

// usage:

ct!(fun(times))

But that's still a nuisance.


Hm... I was focusing on changing fun(times) into fun!(times) in order  
to make it always execute at compile time.  I think that is not so bad.


The idea is that _funimpl is implementation details for fun, and doesn't  
ever expect to be called at runtime.  In fact, you could do if(!_ctfe)  
throw Error();


-Steve


Re: It seems pure ain't so pure after all

2012-10-01 Thread Graham Fawcett

On Monday, 1 October 2012 at 20:41:53 UTC, Tommi wrote:

On Monday, 1 October 2012 at 20:33:29 UTC, Graham Fawcett wrote:

string exclaim(string v)() {
 return v ~ !;
}

void main() {
 writeln(exclaim!(howdy));
}


It doesn't scale well to have to write both compile-time and 
run-time versions of your functions.


And how is your proposed @force_ctfe attribute going to solve 
this issue? If you're forcing CTFE, by definition you don't have 
runtime support.


As you clearly know, D already supports functions that can run at 
compile-time and run-time: that's the whole point of of CTFE.


Graham





Re: It seems pure ain't so pure after all

2012-10-01 Thread Tommi

On Monday, 1 October 2012 at 21:15:40 UTC, Graham Fawcett wrote:
And how is your proposed @force_ctfe attribute going to solve 
this issue? If you're forcing CTFE, by definition you don't 
have runtime support.


Maybe the name @force_ctfe is misleading. But, like I said: the 
attribute @asdf would make it so that the function is guaranteed 
to execute at compile-time when its arguments are compile-time 
constants. Never do I say that the attribute would prevent 
run-time evaluation. The function would behave just like 
constexpr functions do in c++ (although, in c++ what those 
functions can actually do is much more limited).


Re: It seems pure ain't so pure after all

2012-10-01 Thread Jonathan M Davis
On Monday, October 01, 2012 23:15:55 Graham Fawcett wrote:
 On Monday, 1 October 2012 at 20:41:53 UTC, Tommi wrote:
  On Monday, 1 October 2012 at 20:33:29 UTC, Graham Fawcett wrote:
  string exclaim(string v)() {
  
  return v ~ !;
  
  }
  
  void main() {
  
  writeln(exclaim!(howdy));
  
  }
  
  It doesn't scale well to have to write both compile-time and
  run-time versions of your functions.
 
 And how is your proposed @force_ctfe attribute going to solve
 this issue? If you're forcing CTFE, by definition you don't have
 runtime support.
 
 As you clearly know, D already supports functions that can run at
 compile-time and run-time: that's the whole point of of CTFE.

If I understand correctly, what he wants is for CTFE to be forced only in 
cases where all of the arguments are known at compile time (e.g. when you pass 
a string literal), so it wouldn't prevent anything from running at runtime.

This would be a complete disaster if it were done in the general case. For 
instance, writeln(hello) can't be executed at compile time, and since the 
only way for the compiler to know that in most cases is to run the function, 
compile times would tank and probably cause other entertaining issues. So, a 
compiler flag like was previously suggested in this thread would be a _very_ 
bad idea.

On the other hand, if a function attribute were introduced where the 
programmer indicated that they wanted that function to execute at compile time 
as long as all of the arguments were known at compile time, that would work 
just fine (as long as it really _could_ be executed at compile time - but we 
already have that issue when assigning the results of functions to enums). The 
question is whether it's worth adding such an attribute to the language, and 
clearly, most of us think that explicitly using enum suffices whereas Tommi 
wants such a function attribute.

- Jonathan M Davis


Re: It seems pure ain't so pure after all

2012-10-01 Thread Tommi

On Monday, 1 October 2012 at 21:29:33 UTC, Tommi wrote:
Maybe the name @force_ctfe is misleading. But, like I said: 
the attribute @asdf would make it so that the function is 
guaranteed to execute at compile-time when its arguments are 
compile-time constants.


Oh, wait. Now I understand why that sentence is misleading. It 
should be:


The function attribute @asdf would guarantee compile-time 
evaluation of all such calls to that function, where all 
arguments (that you pass into the function), of which the 
function's output depends on, are compile-time evaluable.





Re: It seems pure ain't so pure after all

2012-10-01 Thread Tommi

On Monday, 1 October 2012 at 21:35:16 UTC, Jonathan M Davis wrote:

The question is whether it's worth adding such an attribute to
the language, and clearly, most of us think that explicitly
using enum suffices whereas Tommi wants such a function
attribute.


You'd get simpler syntax at the cost of just one lousy new 
keyword. It's a once in a life time deal! Any takers?




Re: It seems pure ain't so pure after all

2012-10-01 Thread Jonathan M Davis
On Monday, October 01, 2012 23:55:11 Tommi wrote:
 On Monday, 1 October 2012 at 21:35:16 UTC, Jonathan M Davis wrote:
  The question is whether it's worth adding such an attribute to
  the language, and clearly, most of us think that explicitly
  using enum suffices whereas Tommi wants such a function
  attribute.
 
 You'd get simpler syntax at the cost of just one lousy new
 keyword. It's a once in a life time deal! Any takers?

Keywords are considered to be incredibly expensive. Being able to use a name 
starting with @ rather than a keyword does reduce the cost, but you're still 
going to have to drive a very hard bargain to talk Walter into adding anything 
like that to the language at this point. Adding much of _anything_ to the 
language is generally considered expensive.

- Jonathan M Davis


Re: It seems pure ain't so pure after all

2012-10-01 Thread Timon Gehr

On 10/01/2012 08:02 PM, foobar wrote:

On Monday, 1 October 2012 at 17:46:00 UTC, Tommi wrote:

On Monday, 1 October 2012 at 08:04:49 UTC, Jonathan M Davis wrote:

And you _can't_ determine ahead of time which functions can be safely
executed at compile time either, because that's an
instance of the halting problem.


I don't understand (I did read what halting problem means just now,
but I still don't understand). If there was no __ctfe variable, and
thus a guarantee that all functions do the same thing at compile-time
and run-time, couldn't the compiler just try aggressively to execute
all function calls at compile-time? Obviously it wouldn't bother
trying CTFE for function calls that had arguments which weren't
evaluable at compile-time. Nor would it bother with functions that it
knows have memory allocations or other limitations of CTFE.

If not a compiler flag, then it could be a function attribute. Just
like c++ function attribute constexpr, which guarantees that the
function executes at compile time given you provide it with
compile-time evaluable arguments (and there are limitations to what
the function can do). Why wouldn't this attribute be possible with D?


__ctfe is a horrible yet very useful hack to address the underlying
issue - the execution model for CTFE, which I personally do not agree
with. Adding a compiler flag for the existing model, makes no sense
whatsoever. Functions are essentially a run-time abstraction and the
compiler generally speaking has no business trying to execute them at
compile-time. The compiler is after all *not* an interpreter.



A D compiler is also a D interpreter. I wouldn't even bother with D if 
this wasn't the case.



Besides, what would be the use case for such a flag anyway? If you
already know that all parameters are known at compile-time, you can
already tell the compiler to execute the function by assigning to a
static/enum variable.

IMO, this mixing of code for various stages of execution is bad design
but this cannot be changed in a backwards compatible way.




Re: It seems pure ain't so pure after all

2012-10-01 Thread Tommi

On Monday, 1 October 2012 at 22:23:51 UTC, Jonathan M Davis wrote:
Keywords are considered to be incredibly expensive. Being able 
to use a name
starting with @ rather than a keyword does reduce the cost, but 
you're still
going to have to drive a very hard bargain to talk Walter into 
adding anything
like that to the language at this point. Adding much of 
_anything_ to the

language is generally considered expensive.


I'm not sure if you meant the same, but I meant the word cost 
of a feature as the amount the feature complicates the 
language. Also, I'm only asking people to buy this feature in 
the sense of: what would you say about this feature if the 
language was still back on the drawing board and nothing had been 
written down yet.


Re: It seems pure ain't so pure after all

2012-10-01 Thread Jonathan M Davis
On Tuesday, October 02, 2012 01:19:51 Tommi wrote:
 I'm not sure if you meant the same, but I meant the word cost
 of a feature as the amount the feature complicates the
 language. Also, I'm only asking people to buy this feature in
 the sense of: what would you say about this feature if the
 language was still back on the drawing board and nothing had been
 written down yet.

No offense, but a feature proposal is pretty pointless if it's a this would 
have been nice had we had thought of it when we could have easily added it. A 
feature proposal is only relevant if it's really an attempt to change the 
language now.

If we were really back at the drawing board, there are plenty of other things 
which would change, some of which could completely change how some things work 
and possibly invalidate a feature which might seem reasonable now but wouldn't 
work with the other changes (which probably isn't the case here, but still, 
discussing what could have been doesn't really buy us anything IMHO).

- Jonathan M Davis


Re: It seems pure ain't so pure after all

2012-10-01 Thread José Armando García Sancio
On Mon, Oct 1, 2012 at 4:19 PM, Tommi tommitiss...@hotmail.com wrote:

 On Monday, 1 October 2012 at 22:23:51 UTC, Jonathan M Davis wrote:

 Keywords are considered to be incredibly expensive. Being able to use a
 name
 starting with @ rather than a keyword does reduce the cost, but you're
 still
 going to have to drive a very hard bargain to talk Walter into adding
 anything
 like that to the language at this point. Adding much of _anything_ to the
 language is generally considered expensive.


 I'm not sure if you meant the same, but I meant the word cost of a
 feature as the amount the feature complicates the language. Also, I'm
 only asking people to buy this feature in the sense of: what would you
 say about this feature if the language was still back on the drawing board
 and nothing had been written down yet.


That is a close to useless exercise (or domain problem). Problems to solve
are only interested in a specific domain. In other words the problem as you
have defined it will have a different solution in D, C++, Java, vaporware
language, etc.

To some degree it reminds me of the slew of TCP replacement protocols that
academia has designed and implemented that will probably never see the day
of light. Don't get me wrong it is educational to read them and
implementable in private networks but it is highly probably that the
Internet will never see them.

Thanks,
-Jose


Re: It seems pure ain't so pure after all

2012-10-01 Thread bearophile

Jonathan M Davis:


Adding much of _anything_ to the
language is generally considered expensive.


Sometimes you add from a language removing something, like 
allowing handy code like this, removing such limitations and 
making the language more regular/uniform:



class Foo {
int x, y;
}
struct Bar {
int x, y;
}
void main() {
auto f1 = new Foo(1, 2);
auto f2 = new Foo(1);
auto b1 = new Bar(10, 20);
auto b2 = new Bar(10);
}

Bye,
bearophile


Re: It seems pure ain't so pure after all

2012-10-01 Thread Andrei Alexandrescu

On 10/1/12 5:55 PM, Tommi wrote:

On Monday, 1 October 2012 at 21:35:16 UTC, Jonathan M Davis wrote:

The question is whether it's worth adding such an attribute to
the language, and clearly, most of us think that explicitly
using enum suffices whereas Tommi wants such a function
attribute.


You'd get simpler syntax at the cost of just one lousy new keyword. It's
a once in a life time deal! Any takers?


I understand the motivation. We will not consider such a feature for the 
time being.


Andrei




Re: It seems pure ain't so pure after all

2012-10-01 Thread Tommi

On Monday, 1 October 2012 at 23:31:21 UTC, Jonathan M Davis wrote:
No offense, but a feature proposal is pretty pointless if it's 
a this would
have been nice had we had thought of it when we could have 
easily added it. A
feature proposal is only relevant if it's really an attempt to 
change the

language now.

If we were really back at the drawing board, there are plenty 
of other things
which would change, some of which could completely change how 
some things work
and possibly invalidate a feature which might seem reasonable 
now but wouldn't
work with the other changes (which probably isn't the case 
here, but still,
discussing what could have been doesn't really buy us anything 
IMHO).


- Jonathan M Davis


I don't think you should stop trying to write the best language 
specification you can just because you're past the point of it 
being implementable by this language. Call the specification D++ 
and maybe some day someone will pick it up and try to implement 
it.




Re: It seems pure ain't so pure after all

2012-10-01 Thread Jonathan M Davis
On Tuesday, October 02, 2012 02:19:21 Tommi wrote:
 I don't think you should stop trying to write the best language
 specification you can just because you're past the point of it
 being implementable by this language.

Discussing changes to D2 is of relevance, because that affects what we're doing 
now. Discussing features for a possible D3 is of some relevance, because it 
could eventually affect the language (but is also kind of pointless in that it 
won't matter for years yet). Discussing features simply because they might 
have been nice but we don't intend to ever add them is utterly pointless IMHO.

Aside from D, discussing your dream language is all well and good, but it's 
not really going to help D if the discussion isn't aimed at improving D as it 
is now.

 Call the specification D++
 and maybe some day someone will pick it up and try to implement
 it.

Um. That would actually be bad from our point of view. We don't want to 
fragment the community. D will evolve, and we may even eventually end up with 
D3, and someone may very well create a D++ someday, but it's not really in our 
best interest to promote the creation of such a language (especially not now). 
We want D to succeed, and it's going to have to do that pretty much as it is 
now.

At some point, you have to make what you have work and get it to gain traction 
in the programming community as it is, or what you have is of little practical 
value. Forever tweaking it won't get you there even if the tweaks create what 
is theoretically a better language.

So, feel free to air your ideas, but if they're not of practical value towards
improving D right now, many of us aren't going to pay much attention to them.

- Jonathan M Davis


Re: It seems pure ain't so pure after all

2012-10-01 Thread Walter Bright

On 10/1/2012 1:10 PM, Tommi wrote:

I meant that all functions would still be
implicitly CTFEable by default, but an attribute like force_ctfe would
make it so that the function is guaranteed to execute at compile-time
when its arguments are compile-time constants.


Since all you need to do to guarantee compile time evaluation is use it 
in a context that requires CTFE, which are exactly the cases where you'd 
care that it was CTFE'd, I just don't see much utility here.


Note that it is also impossible in the general case for the compiler to 
guarantee that a specific function is CTFE'able for all arguments that 
are also CTFE'able.


It seems pure ain't so pure after all

2012-09-30 Thread Tommi

import std.stdio;

int pow2(int val) pure
{
if (__ctfe)
return 6;
else
return val * val;
}

void main()
{
   assert(pow2(3) == 9);
static assert(pow2(3) == 6);

writeln(9 = 6 ... I knew it! '6' was faking it all along);
readln();
}


Re: It seems pure ain't so pure after all

2012-09-30 Thread Alex Rønne Petersen

On 01-10-2012 07:40, Tommi wrote:

import std.stdio;

int pow2(int val) pure
{
 if (__ctfe)
 return 6;
 else
 return val * val;
}

void main()
{
assert(pow2(3) == 9);
 static assert(pow2(3) == 6);

 writeln(9 = 6 ... I knew it! '6' was faking it all along);
 readln();
}


This is a corner case.

__ctfe is there to allow special-cased CTFE code when absolutely 
necessary. By necessity, this separates a function into two worlds: 
compile time and run time.


As far as purity goes, pow2 *is* pure. It just does something different 
depending on whether you run it at compile time or run time. I don't see 
this as a problem in practice.


--
Alex Rønne Petersen
a...@lycus.org
http://lycus.org