Re: impure

2024-04-08 Thread Alexandru Ermicioi via Digitalmars-d-learn

On Monday, 8 April 2024 at 07:53:01 UTC, Dom DiSc wrote:



On Sunday, 24 March 2024 at 07:41:41 UTC, Dom DiSc wrote:
Try `debug unittest {...}`?


Cool. This seems to work. That's a nice workaroud for tests. 
Yay!


Nice, fyi, you can use it with statements inside function bodies 
as well. Usefull for doing logging in pure functions.




Re: impure

2024-04-08 Thread Dom DiSc via Digitalmars-d-learn

On Monday, 8 April 2024 at 07:03:40 UTC, Alexandru Ermicioi wrote:

On Sunday, 24 March 2024 at 07:41:41 UTC, Dom DiSc wrote:
I'm creating a library that is completely pure, but it doesn't 
compile with pure: at the top because of one impure unittest 
(which uses random to  test some things only probabilistic)!


So do I really need to declare every function pure 
individually because of a test?!?


Can we please have a @impure attribute?
And by the way also @throws and @gc?
That would make live so much easier...


Try `debug unittest {...}`?


Cool. This seems to work. That's a nice workaroud for tests. Yay!


Re: impure

2024-04-08 Thread Dom DiSc via Digitalmars-d-learn

On Sunday, 7 April 2024 at 23:32:24 UTC, MrJay wrote:
A better way to apply a attribute to an entire file is to use 
an explicit scope you can still apply this to basically the 
entire file but leave the tests out of it.


Better than an explicit impure (or pure=false) attribute?
I don't think so. It heavily uglyfies the file, as single items 
without a specific attribute are interspersed in the file. So the 
scope need to end before and start again after the affected 
function or test.


An it stops working at all if e.g. one test is impure and another 
test is @gc, because then the scopes overlap and can no more be 
contained in each other.


Really, having the counter-attributes would improve the language.


Re: impure

2024-04-08 Thread Alexandru Ermicioi via Digitalmars-d-learn

On Sunday, 24 March 2024 at 07:41:41 UTC, Dom DiSc wrote:
I'm creating a library that is completely pure, but it doesn't 
compile with pure: at the top because of one impure unittest 
(which uses random to  test some things only probabilistic)!


So do I really need to declare every function pure individually 
because of a test?!?


Can we please have a @impure attribute?
And by the way also @throws and @gc?
That would make live so much easier...


Try `debug unittest {...}`?


Re: impure

2024-04-07 Thread MrJay via Digitalmars-d-learn

On Sunday, 24 March 2024 at 07:41:41 UTC, Dom DiSc wrote:
I'm creating a library that is completely pure, but it doesn't 
compile with pure: at the top because of one impure unittest 
(which uses random to  test some things only probabilistic)!


So do I really need to declare every function pure individually 
because of a test?!?


Can we please have a @impure attribute?
And by the way also @throws and @gc?
That would make live so much easier...


A better way to apply a attribute to an entire file is to use an 
explicit scope you can still apply this to basically the entire 
file but leave the tests out of it.


second since these are test its better for them to be pure, so 
use debug as it implicitly tells you where all global mutation 
happen, if you need your unit tests to run without debug for what 
ever reason fall back to suggestion one.


`dmd test.d -debug`

``` d
// File name test.d
import std.stdio;

int var = 0;

void main() {
  writeln(var);
  var = 1;
  writeln(var);
  foo();
  writeln(var);
  baz();
  writeln(var);
}

pure {

  int foo() {
debug { var = 2;}
return 2;
  }
  // you can nest scopes
  @safe {
int bar () {
  return 3;
}
  }
}

void baz() {
  var = 4;
}

```


Re: impure

2024-04-06 Thread Jonathan M Davis via Digitalmars-d-learn
On Friday, April 5, 2024 3:11:42 AM MDT Dom DiSc via Digitalmars-d-learn 
wrote:
> On Sunday, 24 March 2024 at 09:16:20 UTC, Jonathan M Davis wrote:
> > So, yes, you've run into a problem that it would be nice to
> > have a better fix for, but even if we could negate attributes
> > in general, there are good reasons to prefer to avoid
> > mass-applying attributes.
>
> I don't see it as "mass-applying attributes" rather than changing
> the default to something more sane, so that I have to apply
> *less* attributes to any single function.

The core issue is that the place that is applying the attributes is far from
what they're being applied to, which makes it extremely easy to miss them
and not know which attributes are actually being applied - particularly when
reviewing code, since then you tend to be looking primarily at diffs and not
the entire file. It's going to be less of a problem with personal projects,
but with any project where multiple people work on the code, it can start
being a problem. Ultimately, having the attributes directly on what they
apply to tends to result in fewer maintenance issues - particularly with
larger projects.

> If the addition of new keywords (like "throws", "@gc" and
> "impure") is a problem, why not doing it like @nogc(false) or
> @nogc=false (likewise for nothrow and pure)?

There are a number of ways that it could be done, but regardless, we'd need
a DIP and an implementation, and neither has happened. It's a known problem
but hasn't been a big enough problem to have been made a priority.

- Jonathan M Davis





Re: impure

2024-04-05 Thread Dom DiSc via Digitalmars-d-learn

On Sunday, 24 March 2024 at 09:16:20 UTC, Jonathan M Davis wrote:
So, yes, you've run into a problem that it would be nice to 
have a better fix for, but even if we could negate attributes 
in general, there are good reasons to prefer to avoid 
mass-applying attributes.


I don't see it as "mass-applying attributes" rather than changing 
the default to something more sane, so that I have to apply 
*less* attributes to any single function.


If the addition of new keywords (like "throws", "@gc" and 
"impure") is a problem, why not doing it like @nogc(false) or 
@nogc=false (likewise for nothrow and pure)?


Re: impure

2024-03-24 Thread Jonathan M Davis via Digitalmars-d-learn
On Sunday, March 24, 2024 1:41:41 AM MDT Dom DiSc via Digitalmars-d-learn 
wrote:
> I'm creating a library that is completely pure, but it doesn't
> compile with pure: at the top because of one impure unittest
> (which uses random to  test some things only probabilistic)!
>
> So do I really need to declare every function pure individually
> because of a test?!?
>
> Can we please have a @impure attribute?
> And by the way also @throws and @gc?
> That would make live so much easier...

It's been brought up a number of times before that it would be desirable to
have a way to negate attributes, and maybe we'll get that ability at some
point, but for now, we don't have it. The only attributes that can be
negated are @safe, @trusted, and @system, because using one of them directly
on a function overrides any others that are applied more globally. So, for
now, you cannot apply pure to an entire module and then have it not apply to
something within the module (though you could put that one test at the top
before you apply pure).

Another thing you could do would be to use debug {} to ignore attributes
within that block (though then that code will only be run when building with
-debug). How much sense that makes depends on what your test is doing, but
it is a way to get around pure in code that isn't intended to be used in
production.

All of that being said, I'd be inclined to argue that in general,
mass-applying attributes is asking for trouble. It works to a point, but it
makes it easy to forget which attributes apply, and in some cases,
attributes get ignored when they're mass-applied (though that's mostly on
types IIRC). It makes more sense when you're applying an attribute to the
entire module and not just a section of a module, but it does have a
tendency to become a maintenance problem - particularly when it's code that
more than one person works on. It also makes code harder to review, because
diffs won't include any of the attributes that are being mass-applied,
making it easy to miss the fact that a particular attribute applies to the
code being changed.

So, yes, you've run into a problem that it would be nice to have a better
fix for, but even if we could negate attributes in general, there are good
reasons to prefer to avoid mass-applying attributes.

- Jonathan M Davis





Re: cannot call impure function

2020-10-04 Thread Mathias LANG via Digitalmars-d-learn

On Sunday, 4 October 2020 at 18:02:11 UTC, Michael wrote:

On Sunday, 4 October 2020 at 17:43:13 UTC, Michael wrote:

[...]
I used the dmg file: dmd.2.094.0.dmg


I reinstalled using the installation script (install.sh) and 
now it works. Still don't know why the dmg-based intstallation 
did not work.

https://dlang.org/install.html

Anyway, thanks for your responses!


I think there might have been a mismatch between the compiler 
used, and the Phobos library used. This might happen if you used 
multiple sources for installation, e.g.  brew / macports / dmg 
(install script is self contained and never affected).


Re: cannot call impure function

2020-10-04 Thread Michael via Digitalmars-d-learn

On Sunday, 4 October 2020 at 17:43:13 UTC, Michael wrote:

On Sunday, 4 October 2020 at 17:37:52 UTC, Mathias LANG wrote:

On Sunday, 4 October 2020 at 17:05:33 UTC, Michael wrote:

On Sunday, 4 October 2020 at 17:01:44 UTC, Paul Backus wrote:

On Sunday, 4 October 2020 at 16:48:24 UTC, Michael wrote:

Dear all,

Sorry for the potentially stupid question, but I'm a 
complete newbie to D. Why does compiling the following 
trivial code fail?


import std.stdio;

void main()
{
writeln(3.14);
}


Works fine for me using DMD 2.094.0 on Linux. What OS and 
compiler version are you using, and how did you install DMD?


DMD64 D Compiler v2.094.0
on macOS 10.15.6


I cannot reproduce locally (macOS 10.15.6 too). How did you 
install DMD ?


I used the dmg file: dmd.2.094.0.dmg


I reinstalled using the installation script (install.sh) and now 
it works. Still don't know why the dmg-based intstallation did 
not work.

https://dlang.org/install.html

Anyway, thanks for your responses!


Re: cannot call impure function

2020-10-04 Thread Michael via Digitalmars-d-learn

On Sunday, 4 October 2020 at 17:37:52 UTC, Mathias LANG wrote:

On Sunday, 4 October 2020 at 17:05:33 UTC, Michael wrote:

On Sunday, 4 October 2020 at 17:01:44 UTC, Paul Backus wrote:

On Sunday, 4 October 2020 at 16:48:24 UTC, Michael wrote:

Dear all,

Sorry for the potentially stupid question, but I'm a 
complete newbie to D. Why does compiling the following 
trivial code fail?


import std.stdio;

void main()
{
writeln(3.14);
}


Works fine for me using DMD 2.094.0 on Linux. What OS and 
compiler version are you using, and how did you install DMD?


DMD64 D Compiler v2.094.0
on macOS 10.15.6


I cannot reproduce locally (macOS 10.15.6 too). How did you 
install DMD ?


I used the dmg file: dmd.2.094.0.dmg


Re: cannot call impure function

2020-10-04 Thread Imperatorn via Digitalmars-d-learn

On Sunday, 4 October 2020 at 16:48:24 UTC, Michael wrote:

Dear all,

Sorry for the potentially stupid question, but I'm a complete 
newbie to D. Why does compiling the following trivial code fail?


[...]


I have tried my best to make it fail, but can't. Maybe it's 
something with the combination of dmd64 and MACOS?


Re: cannot call impure function

2020-10-04 Thread Mathias LANG via Digitalmars-d-learn

On Sunday, 4 October 2020 at 17:05:33 UTC, Michael wrote:

On Sunday, 4 October 2020 at 17:01:44 UTC, Paul Backus wrote:

On Sunday, 4 October 2020 at 16:48:24 UTC, Michael wrote:

Dear all,

Sorry for the potentially stupid question, but I'm a complete 
newbie to D. Why does compiling the following trivial code 
fail?


import std.stdio;

void main()
{
writeln(3.14);
}


Works fine for me using DMD 2.094.0 on Linux. What OS and 
compiler version are you using, and how did you install DMD?


DMD64 D Compiler v2.094.0
on macOS 10.15.6


I cannot reproduce locally (macOS 10.15.6 too). How did you 
install DMD ?


Re: cannot call impure function

2020-10-04 Thread Michael via Digitalmars-d-learn

On Sunday, 4 October 2020 at 17:05:33 UTC, Michael wrote:

On Sunday, 4 October 2020 at 17:01:44 UTC, Paul Backus wrote:

On Sunday, 4 October 2020 at 16:48:24 UTC, Michael wrote:

Dear all,

Sorry for the potentially stupid question, but I'm a complete 
newbie to D. Why does compiling the following trivial code 
fail?


import std.stdio;

void main()
{
writeln(3.14);
}


Works fine for me using DMD 2.094.0 on Linux. What OS and 
compiler version are you using, and how did you install DMD?


DMD64 D Compiler v2.094.0
on macOS 10.15.6


I did not use any compiler flags, but just:
dmd test1.d



Re: cannot call impure function

2020-10-04 Thread Michael via Digitalmars-d-learn

On Sunday, 4 October 2020 at 17:01:44 UTC, Paul Backus wrote:

On Sunday, 4 October 2020 at 16:48:24 UTC, Michael wrote:

Dear all,

Sorry for the potentially stupid question, but I'm a complete 
newbie to D. Why does compiling the following trivial code 
fail?


import std.stdio;

void main()
{
writeln(3.14);
}


Works fine for me using DMD 2.094.0 on Linux. What OS and 
compiler version are you using, and how did you install DMD?


DMD64 D Compiler v2.094.0
on macOS 10.15.6



Re: cannot call impure function

2020-10-04 Thread Paul Backus via Digitalmars-d-learn

On Sunday, 4 October 2020 at 16:48:24 UTC, Michael wrote:

Dear all,

Sorry for the potentially stupid question, but I'm a complete 
newbie to D. Why does compiling the following trivial code fail?


import std.stdio;

void main()
{
writeln(3.14);
}


Works fine for me using DMD 2.094.0 on Linux. What OS and 
compiler version are you using, and how did you install DMD?


cannot call impure function

2020-10-04 Thread Michael via Digitalmars-d-learn

Dear all,

Sorry for the potentially stupid question, but I'm a complete 
newbie to D. Why does compiling the following trivial code fail?


import std.stdio;

void main()
{
writeln(3.14);
}

Error message:

/Library/D/dmd/src/phobos/std/format.d(1601): Error: pure 
function std.format.FormatSpec!char.FormatSpec.toString cannot 
call impure function 
std.format.FormatSpec!char.FormatSpec.toString!(Appender!string).toString
/Library/D/dmd/src/phobos/std/format.d(478): Error: template 
instance std.format.FormatSpec!char error instantiating
/Library/D/dmd/src/phobos/std/stdio.d(1590):instantiated 
from here: formattedWrite!(LockingTextWriter, char, double)
/Library/D/dmd/src/phobos/std/stdio.d(3927):instantiated 
from here: write!(double, char)

test1.d(5):instantiated from here: writeln!double

Cheers,
Michael


Re: Why is there no throws, @gc, impure, mutable ?

2020-09-07 Thread wjoe via Digitalmars-d-learn

On Monday, 7 September 2020 at 11:44:40 UTC, Paul Backus wrote:

On Monday, 7 September 2020 at 11:25:15 UTC, wjoe wrote:
It's easy to declare the entire module @safe and functions 
which can't be can be declared @system.
However there is const, immutable, pure, @nogc and nothrow but 
no mutable, impure, @gc and throws.


Why is that ?


Mostly because nobody's bothered to add them (yet). There's an 
accepted proposal to add a "throw" attribute as the opposite of 
nothrow [1], but it looks like it still hasn't been implemented 
in the compiler.


For const and immutable, you can use std.traits.Unconst [2] to 
remove them in most cases.


[1] 
https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1029.md
[2] 
http://dpldocs.info/experimental-docs/std.traits.Unconst.html


Very interesting. Thanks.


Re: Why is there no throws, @gc, impure, mutable ?

2020-09-07 Thread Paul Backus via Digitalmars-d-learn

On Monday, 7 September 2020 at 11:25:15 UTC, wjoe wrote:
It's easy to declare the entire module @safe and functions 
which can't be can be declared @system.
However there is const, immutable, pure, @nogc and nothrow but 
no mutable, impure, @gc and throws.


Why is that ?


Mostly because nobody's bothered to add them (yet). There's an 
accepted proposal to add a "throw" attribute as the opposite of 
nothrow [1], but it looks like it still hasn't been implemented 
in the compiler.


For const and immutable, you can use std.traits.Unconst [2] to 
remove them in most cases.


[1] 
https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1029.md

[2] http://dpldocs.info/experimental-docs/std.traits.Unconst.html


Why is there no throws, @gc, impure, mutable ?

2020-09-07 Thread wjoe via Digitalmars-d-learn
It's easy to declare the entire module @safe and functions which 
can't be can be declared @system.
However there is const, immutable, pure, @nogc and nothrow but no 
mutable, impure, @gc and throws.


Why is that ?



Re: How to override impure function from pure function

2016-12-12 Thread Nicholas Wilson via Digitalmars-d-learn

On Tuesday, 13 December 2016 at 05:13:01 UTC, Nikhil Jacob wrote:
I mistook the original statement to mean that an impure 
function can be called from a pure function with some manual 
overrides.


Thank you for the clarification.


Yeah you can't do that, except in a debug statement. You can 
however cheat with SetFunctionAttributes (from std.traits).


Re: How to override impure function from pure function

2016-12-12 Thread Nicholas Wilson via Digitalmars-d-learn

On Tuesday, 13 December 2016 at 04:48:11 UTC, Nikhil Jacob wrote:
In the D spec for pure functions it says that a pure function 
can override


"can override an impure function, but an impure function cannot 
override a pure one"


Can anyone help me how to do this ?


what this means is

class Foo
{
   void foo() { ... }
}

class Bar : Foo
{
override void foo() pure { ... }
}

is allowed. but

int someglobal;
class Foo
{
   void foo() pure { ... }
}

class Bar : Foo
{
override void foo()  { someglobal = 42; }
}

in not.


Re: How to override impure function from pure function

2016-12-12 Thread Nikhil Jacob via Digitalmars-d-learn
On Tuesday, 13 December 2016 at 05:10:02 UTC, Nicholas Wilson 
wrote:
On Tuesday, 13 December 2016 at 04:48:11 UTC, Nikhil Jacob 
wrote:
In the D spec for pure functions it says that a pure function 
can override


"can override an impure function, but an impure function 
cannot override a pure one"


Can anyone help me how to do this ?


what this means is

class Foo
{
   void foo() { ... }
}

class Bar : Foo
{
override void foo() pure { ... }
}

is allowed. but

int someglobal;
class Foo
{
   void foo() pure { ... }
}

class Bar : Foo
{
override void foo()  { someglobal = 42; }
}

in not.


I mistook the original statement to mean that an impure function 
can be called from a pure function with some manual overrides.


Thank you for the clarification.


How to override impure function from pure function

2016-12-12 Thread Nikhil Jacob via Digitalmars-d-learn
In the D spec for pure functions it says that a pure function can 
override


"can override an impure function, but an impure function cannot 
override a pure one"


Can anyone help me how to do this ?


Re: cannot call impure function ~this

2013-10-17 Thread Kenji Hara

On Wednesday, 16 October 2013 at 07:58:09 UTC, Namespace wrote:
On Wednesday, 16 October 2013 at 07:32:27 UTC, monarch_dodra 
wrote:

On Wednesday, 16 October 2013 at 07:27:25 UTC, Namespace wrote:
On Wednesday, 16 October 2013 at 07:23:45 UTC, monarch_dodra 
wrote:

On Tuesday, 15 October 2013 at 21:37:40 UTC, Namespace wrote:

I get this error:

/d701/f223.d(11): Error: pure function 'f223.getA' cannot 
call impure function 'f223.A.~this'



with this code:

import std.stdio;

struct A {
public:
~this() {
writeln(DTor);
}
}

A getA() pure nothrow {
return A();
}

void main()
{
A a = getA();

writeln(end of main);
}


But without pure and nothrow I get this output:

end of main
DTor


Why the compiler thinks that the function should/could call 
A::~this?


It could have something to do with the fact that RVO is an 
optimization *opportunity* that the compiler is allowed to 
go for, even if it changes the program output.


Hoewever, being an *opportunity*, the compiler still has to 
make sure the code is valid without said optimization, which 
in this case, isn't: getA would destroy it's temporary after 
blitting it on the stac, leading to an impure call.


So it _could_ be impure, but mostly it isn't, right?


I guess that's one way to put it. I'd say it *is* impure, but 
all its impure bits have been optimized out. That's my 
explanation anyways.


I'm curious: Is this a problem for you? The function calling 
getA *can't* be pure either, so marking getA as pure is ...


I was going to say useless, but I guess pure is always an 
optimization opportunity for the compiler.


I'd file an ER, you never know.
No, I was just curious what's behind it. So specifically why 
the compiler could call the destructor.


In this case, the created struct literal A() will be moved out to 
the function getA(). So dtor is not called and compiler should 
not cause cannot call impure function error.


I filed a bug report and posted possible compiler fix.

http://d.puremagic.com/issues/show_bug.cgi?id=11286
https://github.com/D-Programming-Language/dmd/pull/2677

Kenji Hara


Re: cannot call impure function ~this

2013-10-17 Thread Namespace
In this case, the created struct literal A() will be moved out 
to the function getA(). So dtor is not called and compiler 
should not cause cannot call impure function error.


I filed a bug report and posted possible compiler fix.

http://d.puremagic.com/issues/show_bug.cgi?id=11286
https://github.com/D-Programming-Language/dmd/pull/2677

Kenji Hara

Nice, thank you!



Re: cannot call impure function ~this

2013-10-16 Thread monarch_dodra

On Tuesday, 15 October 2013 at 21:37:40 UTC, Namespace wrote:

I get this error:

/d701/f223.d(11): Error: pure function 'f223.getA' cannot call 
impure function 'f223.A.~this'



with this code:

import std.stdio;

struct A {
public:
~this() {
writeln(DTor);
}
}

A getA() pure nothrow {
return A();
}

void main()
{
A a = getA();

writeln(end of main);
}


But without pure and nothrow I get this output:

end of main
DTor


Why the compiler thinks that the function should/could call 
A::~this?


It could have something to do with the fact that RVO is an 
optimization *opportunity* that the compiler is allowed to go 
for, even if it changes the program output.


Hoewever, being an *opportunity*, the compiler still has to make 
sure the code is valid without said optimization, which in this 
case, isn't: getA would destroy it's temporary after blitting it 
on the stac, leading to an impure call.


Re: cannot call impure function ~this

2013-10-16 Thread Namespace
On Wednesday, 16 October 2013 at 07:23:45 UTC, monarch_dodra 
wrote:

On Tuesday, 15 October 2013 at 21:37:40 UTC, Namespace wrote:

I get this error:

/d701/f223.d(11): Error: pure function 'f223.getA' cannot call 
impure function 'f223.A.~this'



with this code:

import std.stdio;

struct A {
public:
~this() {
writeln(DTor);
}
}

A getA() pure nothrow {
return A();
}

void main()
{
A a = getA();

writeln(end of main);
}


But without pure and nothrow I get this output:

end of main
DTor


Why the compiler thinks that the function should/could call 
A::~this?


It could have something to do with the fact that RVO is an 
optimization *opportunity* that the compiler is allowed to go 
for, even if it changes the program output.


Hoewever, being an *opportunity*, the compiler still has to 
make sure the code is valid without said optimization, which in 
this case, isn't: getA would destroy it's temporary after 
blitting it on the stac, leading to an impure call.


So it _could_ be impure, but mostly it isn't, right?


Re: cannot call impure function ~this

2013-10-16 Thread monarch_dodra

On Wednesday, 16 October 2013 at 07:27:25 UTC, Namespace wrote:
On Wednesday, 16 October 2013 at 07:23:45 UTC, monarch_dodra 
wrote:

On Tuesday, 15 October 2013 at 21:37:40 UTC, Namespace wrote:

I get this error:

/d701/f223.d(11): Error: pure function 'f223.getA' cannot 
call impure function 'f223.A.~this'



with this code:

import std.stdio;

struct A {
public:
~this() {
writeln(DTor);
}
}

A getA() pure nothrow {
return A();
}

void main()
{
A a = getA();

writeln(end of main);
}


But without pure and nothrow I get this output:

end of main
DTor


Why the compiler thinks that the function should/could call 
A::~this?


It could have something to do with the fact that RVO is an 
optimization *opportunity* that the compiler is allowed to go 
for, even if it changes the program output.


Hoewever, being an *opportunity*, the compiler still has to 
make sure the code is valid without said optimization, which 
in this case, isn't: getA would destroy it's temporary after 
blitting it on the stac, leading to an impure call.


So it _could_ be impure, but mostly it isn't, right?


I guess that's one way to put it. I'd say it *is* impure, but all 
its impure bits have been optimized out. That's my explanation 
anyways.


I'm curious: Is this a problem for you? The function calling getA 
*can't* be pure either, so marking getA as pure is ...


I was going to say useless, but I guess pure is always an 
optimization opportunity for the compiler.


I'd file an ER, you never know.


Re: cannot call impure function ~this

2013-10-16 Thread Namespace
On Wednesday, 16 October 2013 at 07:32:27 UTC, monarch_dodra 
wrote:

On Wednesday, 16 October 2013 at 07:27:25 UTC, Namespace wrote:
On Wednesday, 16 October 2013 at 07:23:45 UTC, monarch_dodra 
wrote:

On Tuesday, 15 October 2013 at 21:37:40 UTC, Namespace wrote:

I get this error:

/d701/f223.d(11): Error: pure function 'f223.getA' cannot 
call impure function 'f223.A.~this'



with this code:

import std.stdio;

struct A {
public:
~this() {
writeln(DTor);
}
}

A getA() pure nothrow {
return A();
}

void main()
{
A a = getA();

writeln(end of main);
}


But without pure and nothrow I get this output:

end of main
DTor


Why the compiler thinks that the function should/could call 
A::~this?


It could have something to do with the fact that RVO is an 
optimization *opportunity* that the compiler is allowed to go 
for, even if it changes the program output.


Hoewever, being an *opportunity*, the compiler still has to 
make sure the code is valid without said optimization, which 
in this case, isn't: getA would destroy it's temporary after 
blitting it on the stac, leading to an impure call.


So it _could_ be impure, but mostly it isn't, right?


I guess that's one way to put it. I'd say it *is* impure, but 
all its impure bits have been optimized out. That's my 
explanation anyways.


I'm curious: Is this a problem for you? The function calling 
getA *can't* be pure either, so marking getA as pure is ...


I was going to say useless, but I guess pure is always an 
optimization opportunity for the compiler.


I'd file an ER, you never know.
No, I was just curious what's behind it. So specifically why the 
compiler could call the destructor.


cannot call impure function ~this

2013-10-15 Thread Namespace

I get this error:

/d701/f223.d(11): Error: pure function 'f223.getA' cannot call 
impure function 'f223.A.~this'



with this code:

import std.stdio;

struct A {
public:
~this() {
writeln(DTor);
}
}

A getA() pure nothrow {
return A();
}

void main()
{
A a = getA();

writeln(end of main);
}


But without pure and nothrow I get this output:

end of main
DTor


Why the compiler thinks that the function should/could call 
A::~this?


Why is to(T) pure but roundTo(T) impure?

2012-06-09 Thread Chris Saunders

Hi --

I've been trying to learn more about D's purity features after 
reading David Nadlinger's interesting post on this topic. While 
'purifying' some existing code I discovered that I can't use 
roundTo in a pure function, and I don't understand why. Is this a 
general problem with most floating-point library calls? (e.g. I 
noticed std.math.floor() is impure as well).



import std.conv;

int func(double d) pure {  // compiles...
return to!int(d);
}

int func2(double d) pure {  //doesn't compile!?!
return roundTo!int(d);
}


Thanks for any pointers!

-Chris


Re: Why is to(T) pure but roundTo(T) impure?

2012-06-09 Thread Jonathan M Davis
On Saturday, June 09, 2012 20:43:42 Chris Saunders wrote:
 Hi --
 
 I've been trying to learn more about D's purity features after
 reading David Nadlinger's interesting post on this topic. While
 'purifying' some existing code I discovered that I can't use
 roundTo in a pure function, and I don't understand why. Is this a
 general problem with most floating-point library calls? (e.g. I
 noticed std.math.floor() is impure as well).
 
 
 import std.conv;
 
 int func(double d) pure {  // compiles...
   return to!int(d);
 }
 
 int func2(double d) pure {  //doesn't compile!?!
   return roundTo!int(d);
 }
 
 
 Thanks for any pointers!

One of them ends up calling an impure function and the other doesn't. All it 
takes is using one low-level function which isn't pure yet, and _boom_, it 
can't be pure. This currently happens with pretty much any and all string 
conversions, for instance, primarily because the low-level array stuff (like 
Appender) can't be pure yet.

In the case of to!int, this overload is called


T toImpl(T, S)(S value)
if (!isImplicitlyConvertible!(S, T) 
(isNumeric!S || isSomeChar!S) 
(isNumeric!T || isSomeChar!T))
{
enum sSmallest = mostNegative!S;
enum tSmallest = mostNegative!T;
static if (sSmallest  0)
{
// possible underflow converting from a signed
static if (tSmallest == 0)
{
immutable good = value = 0;
}
else
{
static assert(tSmallest  0);
immutable good = value = tSmallest;
}
if (!good)
throw new ConvOverflowException(Conversion negative overflow);
}
static if (S.max  T.max)
{
// possible overflow
if (value  T.max)
throw new ConvOverflowException(Conversion positive overflow);
}
return cast(T) value;
}


Notice the lack of functions being called. The only one is 
ConvOverflowException's constructor, but apparently that works in a pure 
function (even though the constructor isn't marked as pure - maybe it's 
because it's an exception which as being thrown).

Whereas, this is roundTo's definition


template roundTo(Target)
{
Target roundTo(Source)(Source value)
{
static assert(isFloatingPoint!Source);
static assert(isIntegral!Target);
return to!Target(trunc(value + (value  0 ? -0.5L : 0.5L)));
}
}


Note the call to std.math.trunc. It isn't pure, so voila, roundTo can't be 
pure. Now, it looks like trunc can't be pure because it's calling a C 
function, and there's a good chance that the declaration for that C function 
(core.stdc.math.truncl) can be marked as pure, and then trunc could be marked 
as pure, and then roundTo could be pure, but that obviously hasn't happened 
yet.

In general, it takes very little for a function to be unable to be pure, 
especially if it involves low level stuff and/or C stuff in any way.

- Jonathan M Davis


Re: Why is to(T) pure but roundTo(T) impure?

2012-06-09 Thread Chris Saunders

On Saturday, 9 June 2012 at 19:33:55 UTC, Jonathan M Davis wrote:

On Saturday, June 09, 2012 20:43:42 Chris Saunders wrote:

Hi --

I've been trying to learn more about D's purity features after
reading David Nadlinger's interesting post on this topic. While
'purifying' some existing code I discovered that I can't use
roundTo in a pure function, and I don't understand why. Is 
this a

general problem with most floating-point library calls? (e.g. I
noticed std.math.floor() is impure as well).


import std.conv;

int func(double d) pure {  // compiles...
return to!int(d);
}

int func2(double d) pure {  //doesn't compile!?!
return roundTo!int(d);
}


Thanks for any pointers!


One of them ends up calling an impure function and the other 
doesn't. All it
takes is using one low-level function which isn't pure yet, and 
_boom_, it
can't be pure. This currently happens with pretty much any and 
all string
conversions, for instance, primarily because the low-level 
array stuff (like

Appender) can't be pure yet.

In the case of to!int, this overload is called


T toImpl(T, S)(S value)
if (!isImplicitlyConvertible!(S, T) 
(isNumeric!S || isSomeChar!S) 
(isNumeric!T || isSomeChar!T))
{
enum sSmallest = mostNegative!S;
enum tSmallest = mostNegative!T;
static if (sSmallest  0)
{
// possible underflow converting from a signed
static if (tSmallest == 0)
{
immutable good = value = 0;
}
else
{
static assert(tSmallest  0);
immutable good = value = tSmallest;
}
if (!good)
throw new ConvOverflowException(Conversion 
negative overflow);

}
static if (S.max  T.max)
{
// possible overflow
if (value  T.max)
throw new ConvOverflowException(Conversion 
positive overflow);

}
return cast(T) value;
}


Notice the lack of functions being called. The only one is
ConvOverflowException's constructor, but apparently that works 
in a pure
function (even though the constructor isn't marked as pure - 
maybe it's

because it's an exception which as being thrown).

Whereas, this is roundTo's definition


template roundTo(Target)
{
Target roundTo(Source)(Source value)
{
static assert(isFloatingPoint!Source);
static assert(isIntegral!Target);
return to!Target(trunc(value + (value  0 ? -0.5L : 
0.5L)));

}
}


Note the call to std.math.trunc. It isn't pure, so voila, 
roundTo can't be
pure. Now, it looks like trunc can't be pure because it's 
calling a C
function, and there's a good chance that the declaration for 
that C function
(core.stdc.math.truncl) can be marked as pure, and then trunc 
could be marked
as pure, and then roundTo could be pure, but that obviously 
hasn't happened

yet.

In general, it takes very little for a function to be unable to 
be pure,
especially if it involves low level stuff and/or C stuff in any 
way.


- Jonathan M Davis


Thanks Jonathan. Sounds like a practical issue rather than some 
theoretical problem -- good to know.


Re: Why is to(T) pure but roundTo(T) impure?

2012-06-09 Thread Jonathan M Davis
On Sunday, June 10, 2012 04:06:03 Chris Saunders wrote:
 Thanks Jonathan. Sounds like a practical issue rather than some
 theoretical problem -- good to know.

The vast majority of purity issues with Phobos are purely an implementation 
issue and not any kind of limit in the language. Obviously some stuff can never 
be pure (e.g. Clock.currTime or writeln), but for conversions and the like, 
it's virtually a guarantee that it's an issue with not all of the lower level 
stuff or C stuff being pure like it needs to be. That's slowly getting fixed, 
but 
we still have quite a ways to go. Probably the biggest problem with that from 
the users perspective is format and to!string, because that makes it almost 
impossible to make toString pure or to have formatted error messages in 
assertions in pure functions. We'll get there though.

- Jonathan M Davis


Re: pure functions calling impure functions at compile-time

2012-05-24 Thread Don Clugston

On 23/05/12 11:41, bearophile wrote:

Simen Kjaeraas:


Should this be filed as a bug, or is the plan that only pure functions be
ctfe-able? (or has someone already filed it, perhaps)


It's already in Bugzilla, see issue 7994 and 6169.


It's just happening because the purity checking is currently being done 
in a very unsophisticated way.



But I think there is a semantic hole in some of the discussions about
this problem. Is a future compile-time JIT allowed to perform
purity-derived optimizations in CTFE?


Some, definitely. Eg.  foo(n) + foo(n)

can be changed to 2*foo(n), where n is an integer, regardless of what 
foo does.


It does need to be a bit conservative, but I think the issues aren't 
CTFE specific. Eg, something like this currently gives an assert at runtime:


pure nothrow void check(int n) pure nothrow
{
  assert(n == 4);
}

void main()
{
check(3);
}

even though check() can do nothing other than cause an error, it still 
cannot be optimized away. But you can get rid of all subsequent calls to 
it, because they'll produce the same error every time.


Re: pure functions calling impure functions at compile-time

2012-05-23 Thread bearophile

Simen Kjaeraas:

Should this be filed as a bug, or is the plan that only pure 
functions be

ctfe-able? (or has someone already filed it, perhaps)


It's already in Bugzilla, see issue 7994 and 6169.

But I think there is a semantic hole in some of the discussions 
about this problem. Is a future compile-time JIT allowed to 
perform purity-derived optimizations in CTFE?


Bye,
bearophile


Re: Why is std.algorithm.reduce impure?

2012-03-07 Thread Simen Kjærås
On Wed, 07 Mar 2012 01:41:22 +0100, Jonathan M Davis jmdavisp...@gmx.com  
wrote:



It really takes very little for something to be impure, and optimizations
often do it, because they end up using low-level constructs which aren't  
pure

- some of which could be but aren't and others which probably can't be.


Just so this is clear - no optimization of the compiler is going to change
the purity of a function. An optimization on the part of the programmer
(like using appender) might, though.


Re: Why is std.algorithm.reduce impure?

2012-03-07 Thread Timon Gehr

On 03/07/2012 05:29 PM, Simen Kjærås wrote:

On Wed, 07 Mar 2012 01:41:22 +0100, Jonathan M Davis
jmdavisp...@gmx.com wrote:


It really takes very little for something to be impure, and optimizations
often do it, because they end up using low-level constructs which
aren't pure
- some of which could be but aren't and others which probably can't be.


Just so this is clear - no optimization of the compiler is going to change
the purity of a function. An optimization on the part of the programmer
(like using appender) might, though.


Appender must become pure.


Re: Why is std.algorithm.reduce impure?

2012-03-07 Thread Jonathan M Davis
On Wednesday, March 07, 2012 17:58:43 Timon Gehr wrote:
 On 03/07/2012 05:29 PM, Simen Kjærås wrote:
  On Wed, 07 Mar 2012 01:41:22 +0100, Jonathan M Davis
  
  jmdavisp...@gmx.com wrote:
  It really takes very little for something to be impure, and optimizations
  often do it, because they end up using low-level constructs which
  aren't pure
  - some of which could be but aren't and others which probably can't be.
  
  Just so this is clear - no optimization of the compiler is going to change
  the purity of a function. An optimization on the part of the programmer
  (like using appender) might, though.
 
 Appender must become pure.

Most definitely. A variety of things which are currently impure must become 
pure. Some things which didn't used to be pure still are, but there's still 
plenty left that need to be sorted out.

- Jonathan M Davis


Re: Why is std.algorithm.reduce impure?

2012-03-07 Thread Jonathan M Davis
On Wednesday, March 07, 2012 17:29:24 Simen Kjærås wrote:
 On Wed, 07 Mar 2012 01:41:22 +0100, Jonathan M Davis jmdavisp...@gmx.com
 
 wrote:
  It really takes very little for something to be impure, and optimizations
  often do it, because they end up using low-level constructs which aren't
  pure
  - some of which could be but aren't and others which probably can't be.
 
 Just so this is clear - no optimization of the compiler is going to change
 the purity of a function. An optimization on the part of the programmer
 (like using appender) might, though.

I didn't say that it did, though maybe I wasn't clear enough. Optimizations of 
the _algorithms_ involved can make a function impure - such as use Appender 
instead of ~= when building arrays.

- Jonathan M Davis


Why is std.algorithm.reduce impure?

2012-03-06 Thread H. S. Teoh
Why is std.algorithm.reduce not marked pure? It makes it impossible to
do things like this:

pure const int product(int[] args) {
return reduce!a * b(args);
}


T

-- 
Life is unfair. Ask too much from it, and it may decide you don't deserve what 
you have now either.


Re: Why is std.algorithm.reduce impure?

2012-03-06 Thread Adam D. Ruppe

On Tuesday, 6 March 2012 at 22:39:20 UTC, H. S. Teoh wrote:

Why is std.algorithm.reduce not marked pure?


It doesn't have to be - templates are inferred to be
pure or not.

If you take the const off that signature, your example
works in today's dmd.


Re: Why is std.algorithm.reduce impure?

2012-03-06 Thread H. S. Teoh
On Tue, Mar 06, 2012 at 11:42:00PM +0100, Adam D. Ruppe wrote:
 On Tuesday, 6 March 2012 at 22:39:20 UTC, H. S. Teoh wrote:
 Why is std.algorithm.reduce not marked pure?
 
 It doesn't have to be - templates are inferred to be
 pure or not.
 
 If you take the const off that signature, your example
 works in today's dmd.

Oh? what's wrong with the const?


T

-- 
Don't modify spaghetti code unless you can eat the consequences.


Re: Why is std.algorithm.reduce impure?

2012-03-06 Thread Adam D. Ruppe

On Tuesday, 6 March 2012 at 22:48:30 UTC, H. S. Teoh wrote:

Oh? what's wrong with the const?


test10.d(3): Error: function test10.product without 'this' cannot 
be const/immutable


It works if you put parens on it:

pure const(int) product(int[] args) {


Without the parenthesis, D wants to apply it to this,
like if you write void foo() const {} in C++.

The reason here is most the attributes are at the
beginning, which is cool because this works:

const {
  void foo() {}
  int bar() {}
}

etc.


But if you put parens on it, it specifically applies
to the int.


Re: Why is std.algorithm.reduce impure?

2012-03-06 Thread H. S. Teoh
On Tue, Mar 06, 2012 at 11:51:05PM +0100, Adam D. Ruppe wrote:
 On Tuesday, 6 March 2012 at 22:48:30 UTC, H. S. Teoh wrote:
 Oh? what's wrong with the const?
 
 test10.d(3): Error: function test10.product without 'this' cannot be
 const/immutable
 
 It works if you put parens on it:
 
 pure const(int) product(int[] args) {
 
 
 Without the parenthesis, D wants to apply it to this,
 like if you write void foo() const {} in C++.

But why can't 'this' be const? For example, why does the compiler reject
this:

class A {
int[] data;
pure const int sum() {
return reduce!a*b(data);
}
}

I'm not modifying data at at all, so why should it be an error?


T

-- 
Don't modify spaghetti code unless you can eat the consequences.


Re: Why is std.algorithm.reduce impure?

2012-03-06 Thread H. S. Teoh
On Tue, Mar 06, 2012 at 03:00:16PM -0800, H. S. Teoh wrote:
[...]
 But why can't 'this' be const? For example, why does the compiler
 reject this:
 
   class A {
   int[] data;
   pure const int sum() {
   return reduce!a*b(data);
   }
   }
 
 I'm not modifying data at at all, so why should it be an error?
[...]

Actually, nevermind that. Looks like a compiler bug that got fixed in
dmd, but hasn't been pulled into gdc yet. I'll just have to be patient.
:-)


T

-- 
A mathematician is a device for turning coffee into theorems. -- P. Erdos


Re: Why is std.algorithm.reduce impure?

2012-03-06 Thread Jonathan M Davis
On Tuesday, March 06, 2012 14:41:01 H. S. Teoh wrote:
 Why is std.algorithm.reduce not marked pure? It makes it impossible to
 do things like this:
 
 pure const int product(int[] args) {
 return reduce!a * b(args);
 }

You'd have to look through the implementation and possibly tweak it to figure 
it out. All it takes is _one_ thing in there which isn't considered pure, and 
reduce won't be pure.

Glancing at it, I suspect that its use of emplace is the culprit. emplace uses 
memcpy in some of its overloads, and memcpy probably isn't marked as pure, 
since it's a C function. It theoretically _could_ be marked as pure - and 
arguably should be - but I very much doubt that it is right now.

It really takes very little for something to be impure, and optimizations 
often do it, because they end up using low-level constructs which aren't pure 
- some of which could be but aren't and others which probably can't be. More 
effort needs to be made in sorting out the purity of a number of the low-level 
constructs. Appender, for instance, screws up a lot of the string stuff, 
because it isn't pure. And it's far from the sole culprit.

- Jonathan M Davis


Re: Why is std.algorithm.reduce impure?

2012-03-06 Thread bearophile
H. S. Teoh:

 But why can't 'this' be const? For example, why does the compiler reject
 this:
 
   class A {
   int[] data;
   pure const int sum() {
   return reduce!a*b(data);
   }
   }
 
 I'm not modifying data at at all, so why should it be an error?

I think it's a small bug in std.algorithm.reduce, is this in Bugzilla already?


import std.algorithm: reduce;
void main() {
const data = [2, 3, 4];
int r1 = reduce!q{a * b}(0, data); // OK
int r2 = reduce!q{a * b}(data);
}



In std.algorithm.reduce there is also this (now bug 2443 is fixed) at about 
line 723:

// For now, just iterate using ref to avoid unnecessary copying.
// When Bug 2443 is fixed, this may need to change.
foreach(ref elem; r)
{
if(initialized)

Bye,
bearophile


Impure static

2011-11-09 Thread bearophile
This little D2 program, a pure function contains static variables initialized 
with calls to not pure functions:


int foo() {
return 1;
}
pure int bar() {
enum int x1 = foo();
static immutable int x2 = foo();
return x1;
}
void main() {}


The latest DMD gives:

test.d(5): Error: pure function 'bar' cannot call impure function 'foo'
test.d(5):called from here: foo()
test.d(5):called from here: foo()
test.d(6): Error: pure function 'bar' cannot call impure function 'foo'
test.d(6):called from here: foo()
test.d(6):called from here: foo()

I think I asked a similar question in past, is it right to expect DMD to 
compile this program?

Bye and thank you,
bearophile


Re: Impure static

2011-11-09 Thread Timon Gehr

On 11/09/2011 02:16 PM, bearophile wrote:

This little D2 program, a pure function contains static variables initialized 
with calls to not pure functions:


int foo() {
 return 1;
}
pure int bar() {
 enum int x1 = foo();
 static immutable int x2 = foo();
 return x1;
}
void main() {}


The latest DMD gives:

test.d(5): Error: pure function 'bar' cannot call impure function 'foo'
test.d(5):called from here: foo()
test.d(5):called from here: foo()
test.d(6): Error: pure function 'bar' cannot call impure function 'foo'
test.d(6):called from here: foo()
test.d(6):called from here: foo()

I think I asked a similar question in past, is it right to expect DMD to 
compile this program?



Yes. Here is the bug report:
http://d.puremagic.com/issues/show_bug.cgi?id=6169