www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Temporarily disable all purity for debug prints

reply bearophile <bearophileHUGS lycos.com> writes:
From what I am seeing, in a D2 program if I have many (tens or more) pure
functions that call to each other, and I want to add (or activate) a
printf/writeln inside one (or few) of those functions to debug it, I may need
to temporarily comment out the "pure" attribute of many functions (because
printing can't be allowed in pure functions).

As more and more D2 functions become pure in my code and in Phobos, something
like a -disablepure compiler switch (and printf/writeln inside debug{}) may
allow more handy debugging with prints (if the purity is well managed by the
compiler then I think disabling the pure attributes doesn't change the program
output).

Bye,
bearophile
Apr 11 2011
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
I wonder if it would be a good idea to have logging or debug prints
that simply lie about being pure so you can use them there.

Something like this:

==
extern(C) pure void puts(const char*);

pure void hello() {
	puts("hello world from pure land\n"); // compiles
}
==
Apr 11 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Adam D. Ruppe:

 I wonder if it would be a good idea to have logging or debug prints
 that simply lie about being pure so you can use them there.
If the compiler sees a function as pure, the debug prints may or may not appear according to how much pure-related optimizations the compiler is doing. This is a test done with C code compiled with GCC 4.6: #include "math.h" #include "stdio.h" __attribute__((const, noinline)) static float sigmoid1(const float x) { puts("hello world"); return 1.0f / (1.0f - exp(-x)); } static float calculate(const float x, const unsigned int n) { unsigned int i; float sum = 0.0; for (i = 0; i < n; ++i) sum += sigmoid1(x); return sum; } int main(int argc, const char **argv) { const int x = argc; const float y = calculate(x, 20); printf("%f\n", y); return 0; } The GCC attribute "const" is similar to the pure of D (GCC also has the "pure" attribute but I think it's a little different). If you compile this program with -O0 you get 20 hello world, if you compile with -O3 GCC performs the pure optimizations and prints a single hello world. Is this an acceptable debug printing for you? For me it's not good enough. An alternative solution, that avoids the need of the -disablepure switch, is to state in the D specs that pure-related optimizations are not performed if the program is not compiled in an optimized (-O) way. I have not used D/DMD for this example because DMD isn't optimizing purity enough yet. Bye, bearophile
Apr 11 2011
next sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
bearophile wrote:
 Is this an acceptable debug printing for you?
Yes. In fact, I view it as better than always seeing it twenty times because it reflects what's actually going on. You already know what it's supposed to do, and if it did what it was supposed to do, you wouldn't be debugging it. So now you need to know what it actually is doing, and if optimizations change that, better to know about it. The single print tells you that.
Apr 11 2011
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
One extra note: in GCC 4.6 there are compiler switches like
-Wsuggest-attribute=const that generate suggestions for functions that are
implicitly const (pure) but don't have a const attribute yet.

Bye,
bearophile
Apr 11 2011
parent dsimcha <dsimcha yahoo.com> writes:
On 4/11/2011 6:23 PM, bearophile wrote:
 One extra note: in GCC 4.6 there are compiler switches like
-Wsuggest-attribute=const that generate suggestions for functions that are
implicitly const (pure) but don't have a const attribute yet.

 Bye,
 bearophile
Interesting (and practical) idea. The only problems I see are templated functions (for which pure, nothrow, etc. are so broken it's not even funny) and finding functions that could be marked as pure if the implicitly pure functions they call were marked as pure. For example: // Module 1: // fun is implicitly pure uint fun(uint num) { return num + 1; } // Module 2: // gun is implicitly pure but the compiler can only flag this // if it realizes fun is implicitly pure. uint gun(uint num) { return fun(num) * 2; }
Apr 11 2011
prev sibling next sibling parent spir <denis.spir gmail.com> writes:
On 04/11/2011 11:27 PM, bearophile wrote:
  From what I am seeing, in a D2 program if I have many (tens or more) pure
functions that call to each other, and I want to add (or activate) a
printf/writeln inside one (or few) of those functions to debug it, I may need
to temporarily comment out the "pure" attribute of many functions (because
printing can't be allowed in pure functions).

 As more and more D2 functions become pure in my code and in Phobos, something
like a -disablepure compiler switch (and printf/writeln inside debug{}) may
allow more handy debugging with prints (if the purity is well managed by the
compiler then I think disabling the pure attributes doesn't change the program
output).
Similar to Adam's idea, I'd like a debug-only func, maybe called 'note' (because 'log' is too ambiguous). 'log' could do the same thing as writeln; or even better: void f (int n) { note(n*n); ... } f(3); // writes: "n*n: 9\n" Meaning, no need to explicitely type: note("n*n: ", n*n); This indeed requires some compiler magic. For simplicity, note could be non-variadic (--> one note per line, both in code and on output). In any case, the point is for note to be considered pure, because debug-output-only. And would not be compiled in -release mode. (nice side-effect: debug output statements can then stay in code as are) Denis -- _________________ vita es estrany spir.wikidot.com
Apr 11 2011
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Adam D. Ruppe:

 Yes. In fact, I view it as better than always seeing it twenty
 times because it reflects what's actually going on.
To avoid some possible troubles I suggest to keep puts pure only in debug builds: debug extern(C) pure void puts(const char*); else extern(C) void puts(const char*); pure void hello() { debug puts("hello world from pure land\n"); } void main() { hello(); } Bye, bearophile
Apr 11 2011
parent Adam D. Ruppe <destructionator gmail.com> writes:
bearophile:
 To avoid some possible troubles I suggest to keep puts pure only in debug
builds:
Definitely. It is a filthy hack, after all!
Apr 11 2011
prev sibling next sibling parent bearophile <bearophileHUGS lycos.com> writes:
dsimcha:

 Interesting (and practical) idea.
It's one example of a third class of compiler messages that I have named compiler tips (beside warnings and errors).
 The only problems I see are templated 
 functions (for which pure, nothrow, etc. are so broken it's not even 
 funny) and finding functions that could be marked as pure if the 
 implicitly pure functions they call were marked as pure.  For example:
C language is simpler than C++/D2 and I presume it's acceptable for the compiler to be conservative and not spot all function that are implicitly pure, but only some of them. Bye, bearophile
Apr 11 2011
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"bearophile" <bearophileHUGS lycos.com> wrote in message 
news:invrod$3182$1 digitalmars.com...
 From what I am seeing, in a D2 program if I have many (tens or more) pure 
 functions that call to each other, and I want to add (or activate) a 
 printf/writeln inside one (or few) of those functions to debug it, I may 
 need to temporarily comment out the "pure" attribute of many functions 
 (because printing can't be allowed in pure functions).

 As more and more D2 functions become pure in my code and in Phobos, 
 something like a -disablepure compiler switch (and printf/writeln inside 
 debug{}) may allow more handy debugging with prints (if the purity is well 
 managed by the compiler then I think disabling the pure attributes doesn't 
 change the program output).
That's a very good idea. I'm a huge fan of printf-debugging (comes from years of developing on platforms that didn't have a good readily-available debugger), so not being able to do that in pure functions would be a very critical roadblock for me for using purity. In fact, it's already been a royal PITA for CTFE.
Apr 11 2011
parent reply spir <denis.spir gmail.com> writes:
On 04/12/2011 04:05 AM, Nick Sabalausky wrote:
 As more and more D2 functions become pure in my code and in Phobos,
  something like a -disablepure compiler switch (and printf/writeln inside
  debug{}) may allow more handy debugging with prints (if the purity is well
  managed by the compiler then I think disabling the pure attributes doesn't
  change the program output).
That's a very good idea. I'm a huge fan of printf-debugging (comes from years of developing on platforms that didn't have a good readily-available debugger), so not being able to do that in pure functions would be a very critical roadblock for me for using purity. In fact, it's already been a royal PITA for CTFE.
Same for me. I'm a fan of printf debugging not because of lack of debuggers, rather because of their "heaviness" & lack of flexibility. Debug output is by me far more direct, quicker & lighter; and agile. Denis -- _________________ vita es estrany spir.wikidot.com
Apr 12 2011
parent reply David Gileadi <gileadis NSPMgmail.com> writes:
On 4/12/11 1:12 AM, spir wrote:
 On 04/12/2011 04:05 AM, Nick Sabalausky wrote:
 As more and more D2 functions become pure in my code and in Phobos,
 something like a -disablepure compiler switch (and printf/writeln
inside
 debug{}) may allow more handy debugging with prints (if the purity
is well
 managed by the compiler then I think disabling the pure attributes
doesn't
 change the program output).
That's a very good idea. I'm a huge fan of printf-debugging (comes from years of developing on platforms that didn't have a good readily-available debugger), so not being able to do that in pure functions would be a very critical roadblock for me for using purity. In fact, it's already been a royal PITA for CTFE.
Same for me. I'm a fan of printf debugging not because of lack of debuggers, rather because of their "heaviness" & lack of flexibility. Debug output is by me far more direct, quicker & lighter; and agile. Denis
I'm not a day-to-day D programmer but it's seemed to me for a while that having a print/log function that would work in normal code, in pure code and in CTFE would be extremely useful.
Apr 12 2011
parent bearophile <bearophileHUGS lycos.com> writes:
David Gileadi:

 I'm not a day-to-day D programmer but it's seemed to me for a while that 
 having a print/log function that would work in normal code, in pure code 
 and in CTFE would be extremely useful.
Vote, if you like :-) This asks for something minimal, a way to print strings at compile-time, like a ctputs() that doesn't print the ending newline: http://d.puremagic.com/issues/show_bug.cgi?id=3952 Bye, bearophile
Apr 12 2011
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 11 Apr 2011 17:27:41 -0400, bearophile <bearophileHUGS lycos.com>  
wrote:

 From what I am seeing, in a D2 program if I have many (tens or more)  
 pure functions that call to each other, and I want to add (or activate)  
 a printf/writeln inside one (or few) of those functions to debug it, I  
 may need to temporarily comment out the "pure" attribute of many  
 functions (because printing can't be allowed in pure functions).

 As more and more D2 functions become pure in my code and in Phobos,  
 something like a -disablepure compiler switch (and printf/writeln inside  
 debug{}) may allow more handy debugging with prints (if the purity is  
 well managed by the compiler then I think disabling the pure attributes  
 doesn't change the program output).
use C linkage, you can do whatever you want. It's how druntime accomplishes a lot of stuff. For example: puredebug.d: import std.stdio; extern(C) void pureprint(string[] values...) { write("[pure debug] "); foreach(value; values) write(value); writeln(); } puredebug.di: extern(C) void pureprint(string[] values...) pure; Should work. -Steve
Apr 12 2011
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/12/2011 8:03 AM, Steven Schveighoffer wrote:
 use C linkage, you can do whatever you want. It's how druntime accomplishes a
 lot of stuff.

 For example:

 puredebug.d:

 import std.stdio;

 extern(C) void pureprint(string[] values...)
 {
 write("[pure debug] ");
 foreach(value; values)
 write(value);
 writeln();
 }

 puredebug.di:

 extern(C) void pureprint(string[] values...) pure;

 Should work.
Yes. But it occurs to me to take the subject title literally - allow impure code inside debug statements, as in: pure void foo() { debug writeln("in foo()"); } Simple and effective.
Apr 12 2011
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 12 Apr 2011 13:18:30 -0400, Walter Bright  
<newshound2 digitalmars.com> wrote:

 On 4/12/2011 8:03 AM, Steven Schveighoffer wrote:
 use C linkage, you can do whatever you want. It's how druntime  
 accomplishes a
 lot of stuff.

 For example:

 puredebug.d:

 import std.stdio;

 extern(C) void pureprint(string[] values...)
 {
 write("[pure debug] ");
 foreach(value; values)
 write(value);
 writeln();
 }

 puredebug.di:

 extern(C) void pureprint(string[] values...) pure;

 Should work.
Yes. But it occurs to me to take the subject title literally - allow impure code inside debug statements, as in: pure void foo() { debug writeln("in foo()"); } Simple and effective.
That works too. I was giving an alternative that should work in the current compiler :) Also, please allow debug(XYZ) writeln("in foo()"); -Steve
Apr 12 2011
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Walter:

 pure void foo()
 {
      debug writeln("in foo()");
 }
 
 Simple and effective.
Very simple designs are sometimes the mark of the genius. But isn't your idea able to lead to debug code that's more buggy than the nondebug code, if some side effect (like modifying a global) is used inside a debug{}? Bye, bearophile
Apr 12 2011
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 12 Apr 2011 15:48:33 -0400, bearophile <bearophileHUGS lycos.com>  
wrote:

 Walter:

 pure void foo()
 {
      debug writeln("in foo()");
 }

 Simple and effective.
Very simple designs are sometimes the mark of the genius. But isn't your idea able to lead to debug code that's more buggy than the nondebug code, if some side effect (like modifying a global) is used inside a debug{}?
Well, yes. So? How does the compiler establish rules to separate "safe debug printing" from "all code that isn't pure"? If you did that, how does the compiler know it's safe? The only way I can think of is to treat writeln specially, which doesn't sound like the right thing to do. Note also, that the code which outputs a custom object via writeln (either toString or writeTo) could modify a global. -Steve
Apr 12 2011
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Steven Schveighoffer:

 Well, yes.  So?  How does the compiler establish rules to separate "safe  
 debug printing" from "all code that isn't pure"?  If you did that, how  
 does the compiler know it's safe?  The only way I can think of is to treat  
 writeln specially, which doesn't sound like the right thing to do.
In the first post in this thread I have suggested a possible solution that avoids that unsafety, a compilation switch to disable all pure annotations in the program/compilation unit. Then you are able to add printing statements in a version{} relative to this compilation switch. Bye, bearophile
Apr 12 2011
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 12 Apr 2011 16:11:41 -0400, bearophile <bearophileHUGS lycos.com>  
wrote:

 Steven Schveighoffer:

 Well, yes.  So?  How does the compiler establish rules to separate "safe
 debug printing" from "all code that isn't pure"?  If you did that, how
 does the compiler know it's safe?  The only way I can think of is to  
 treat
 writeln specially, which doesn't sound like the right thing to do.
In the first post in this thread I have suggested a possible solution that avoids that unsafety, a compilation switch to disable all pure annotations in the program/compilation unit. Then you are able to add printing statements in a version{} relative to this compilation switch.
I think the -debug switch should disable certain pure optimizations (like running multiple calls in parallel on different cores) so issues with unpure code being inside pure functions wouldn't affect them. If you are in debug mode, you shouldn't worry about performance as much. Of course, you'd still see some oddities in other cases of pure optimizations (like refactoring), but I think you'd *want* to see those. In fact, I'd think you want to have most of the pure optimizations apply to see how it actually refactors. -Steve
Apr 12 2011
prev sibling parent spir <denis.spir gmail.com> writes:
On 04/12/2011 09:54 PM, Steven Schveighoffer wrote:
 On Tue, 12 Apr 2011 15:48:33 -0400, bearophile <bearophileHUGS lycos.com>
wrote:

 Walter:

 pure void foo()
 {
 debug writeln("in foo()");
 }

 Simple and effective.
Very simple designs are sometimes the mark of the genius. But isn't your idea able to lead to debug code that's more buggy than the nondebug code, if some side effect (like modifying a global) is used inside a debug{}?
Well, yes. So? How does the compiler establish rules to separate "safe debug printing" from "all code that isn't pure"? If you did that, how does the compiler know it's safe? The only way I can think of is to treat writeln specially, which doesn't sound like the right thing to do. Note also, that the code which outputs a custom object via writeln (either toString or writeTo) could modify a global.
Also naughtily: pure void foo(n) { writeln(iPerformSideEffect(n), " ...in foo"); return n+1; } Denis -- _________________ vita es estrany spir.wikidot.com
Apr 12 2011
prev sibling next sibling parent reply David Nadlinger <see klickverbot.at> writes:
On 4/11/11 11:27 PM, bearophile wrote:
  From what I am seeing, in a D2 program if I have many (tens or more) pure
functions that call to each other, and I want to add (or activate) a
printf/writeln inside one (or few) of those functions to debug it, I may need
to temporarily comment out the "pure" attribute of many functions (because
printing can't be allowed in pure functions).
Related news: https://github.com/D-Programming-Language/dmd/commit/ed8068f5036f88fff1603d98ebe96bb6659bceed David
Apr 15 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
David Nadlinger:

 Related news: 
 https://github.com/D-Programming-Language/dmd/commit/ed8068f5036f88fff1603d98ebe96bb6659bceed
It's a bit disconcerting to see how important things I'm asking and arguing for for three years or more gets ignored, while this that I have barely noted gets worked on already :-) But I am not very good at reading DMD code, so is someone able to translate to me the effects of those changes, and how to use them? I presume this front end change is not following my suggestion (of adding a switch to disable purity), but adds a dirty hack that allows impure debug code inside pure functions. If this is true, then let's now find the bad side effects of this change. Bye, bearophile
Apr 15 2011
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
 Related news: 
 https://github.com/D-Programming-Language/dmd/commit/ed8068f5036f88fff1603d98ebe96bb6659bceed
I have forgotten to add something: thank you Walter. Sorry for criticizing before actually trying out the change. Bye, bearophile
Apr 15 2011
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/15/2011 3:00 PM, bearophile wrote:
 I presume this front end change is not following my suggestion (of adding a
 switch to disable purity), but adds a dirty hack that allows impure debug
 code inside pure functions. If this is true, then let's now find the bad side
 effects of this change.
On the contrary, I think it is the right solution. After all, the reason people want to put impure code in a pure function is for debugging. By putting it under the debug conditional, any logging or printing code can be there without needing the compiler to be aware of what they do.
Apr 15 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Walter:

 On the contrary, I think it is the right solution. After all, the reason people
 want to put impure code in a pure function is for debugging. By putting it
under
 the debug conditional, any logging or printing code can be there without
needing
 the compiler to be aware of what they do.
(Extra note: logging not fully related to debugging. Large programs often keep logs even in release mode.) There is something I don't understand. If your last change allows code like this, isn't it breaking the safety of pure functions in debug mode? Do you think this loss of safety is not important? int some_global; void loggit(int x) { some_global++; writeln(x); } pure nothrow int sqr(in int x) { debug loggit(x); return x * x; } Bye, bearophile
Apr 15 2011
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/15/2011 7:06 PM, bearophile wrote:
 There is something I don't understand. If your last change allows code like
 this, isn't it breaking the safety of pure functions in debug mode? Do you
 think this loss of safety is not important?
Yes, it allows one to break the purity of the function. The alternative is to use casts (which also breaks the purity) or another compiler switch (which also breaks the purity). Any escape from the language rules requires the programmer to know what they're doing, as the compiler can't check it for them. D is a systems programming language, and so it does allow escapes from the rules. It's very useful to allow an I-know-what-I'm-doing escape from the purity rules.
Apr 15 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Walter:

 Yes, it allows one to break the purity of the function. The alternative is to 
 use casts (which also breaks the purity) or another compiler switch (which
also 
 breaks the purity).
A compiler switch to disable purity doesn't break purity. It just turns all pure functions inside the program (or inside the compilation unit) into not pure ones. At this point you are allowed to call writeln too, safely. A problem: if other already compiled parts of the program use the purity of the functions you have just turn into not pure ones with a compiler switch, your program goes bad. So I presume you have to compile the code that uses the not pure anymore functons. Bye, bearophile Bye, bearophile
Apr 16 2011
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/16/2011 6:41 AM, bearophile wrote:
 Yes, it allows one to break the purity of the function. The alternative is
 to use casts (which also breaks the purity) or another compiler switch
 (which also breaks the purity).
A compiler switch to disable purity doesn't break purity. It just turns all pure functions inside the program (or inside the compilation unit) into not pure ones. At this point you are allowed to call writeln too, safely.
Saying it is a safe way to break purity assumes that there was no purpose to the purity. There is no guaranteed safe way to break purity, with or without a compiler switch.
Apr 16 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Walter:

 Saying it is a safe way to break purity assumes that there was no purpose to
the purity.
 There is no guaranteed safe way to break purity, with or without a compiler
switch.
The compiler switch I am talking about doesn't break purity. Its purpose is similar to removing the "pure" attributes from the source code. And doing it is usually safe, if you do it in the whole program. If you take a D2 program, you remove all its pure attributes and you compile it again, the result is generally a program just as correct as before. The compiler just doesn't perform the optimizations that purity allows: a function that's now not pure gets computed each time you call it, it doesn't use the pure GC Don was talking about, the (future) conditionally pure higher order functions just return a not pure result, it keeps not using global mutable state because you have not modified the source code in any other way. If you recompile all the program parts that use the functions that are now not pure, the only things that break are static constraints (or static asserts) that require a function pointer to be pure, and similar things, but I have not used such things so far, they are probably quite uncommon. An example, I have a little buggy strongly pure function sqr that's pure. The smart compiler moves the call to sqr out of the foreach loop because sqr is pure and x doesn't change inside the loop: import std.stdio: writeln; pure int sqr(const int x) { int result = x * x * x; // bug version (mydebug) writeln(result); return result; } void main() { int x = 10; int total; foreach (i; 0 .. 10) total += sqr(x); writeln(total); } To debug sqr I use the -nopure switch, its purpose is just to virtually comment out all the "pure" annotations. I also compile with -version=mydebug (I have avoided debug{} itself just to avoid confusion): import std.stdio: writeln; /*pure*/ int sqr(const int x) { int result = x * x * x; // bug version (mydebug) writeln(result); return result; } void main() { int x = 10; int total; foreach (i; 0 .. 10) total += sqr(x); writeln(total); } Now the writeln() inside sqr works and its purity is not broken, it's just absent, and the compiler just calls sqr ten times because sqr is not pure any more. On the other hand if you have a program like this: import std.stdio, std.traits; pure int sqr(const int x) { int result = x * x * x; // bug version (mydebug) writeln(result); return result; } auto pureApply(TF, T)(TF f, T x) if (functionAttributes!f & FunctionAttribute.PURE) { return f(x); } void main() { int x = 10; writeln(pureApply(&sqr, x)); } If you compile this program with -nopure it breaks, because pureApply() requires f to be pure. I think this kind of code is uncommon. Bye, bearophile
Apr 16 2011
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/16/2011 11:52 AM, bearophile wrote:
 Walter:

 Saying it is a safe way to break purity assumes that there was no purpose
 to the purity. There is no guaranteed safe way to break purity, with or
 without a compiler switch.
The compiler switch I am talking about doesn't break purity. Its purpose is similar to removing the "pure" attributes from the source code. And doing it is usually safe, if you do it in the whole program.
No, it is not. You seem to be thinking that purity is just a bug finding or optimization feature. That is not so. Purity is a guarantee that can be relied upon for a program's behavior. Breaking purity breaks that guarantee. (Think multithreaded programs, for example.)
 If you take a D2 program, you remove all its pure attributes and you compile
 it again, the result is generally a program just as correct as before.
"generally" is not a verifiable characteristic. When we talk about safety, we're talking about a verifiable guarantee.
Apr 16 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Walter:

 No, it is not. You seem to be thinking that purity is just a bug finding or
 optimization feature. That is not so. Purity is a guarantee that can be relied
 upon for a program's behavior. Breaking purity breaks that guarantee.
 
 (Think multithreaded programs, for example.)
I was not thinking about multi-threaded programs, you are right. But I think just "commenting out" the pure attributes doesn't turn a correct multi-threaded program into an incorrect one.
 If you take a D2 program, you remove all its pure attributes and you compile
 it again, the result is generally a program just as correct as before.
 "generally" is not a verifiable characteristic. When we talk about safety,
we're
 talking about a verifiable guarantee.
Your solution too (of allowing impure code inside debug{} is breaking the guarantees. With "generally correct" I meant to say that if you use the -nopure switch then the program is as correct as before, but in some uncommon cases it doesn't compile, because it doesn't satisfy some static requirements of purity that it contains. A not compiled program is safe :-) So while my solution was not perfect, I think your solution is less safe than mine. My purpose was to present a debugging problem I have had, to suggest one solution, and to try to explain why my solution isn't breaking safety (unlike yours). I think you have now understood my ideas. You have more programming experience than me, the design decision is yours. Thank you for giving one solution to the original debug problem, and for your answers in this thread. Bye, bearophile
Apr 16 2011
parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/16/2011 1:21 PM, bearophile wrote:
 Walter:

 No, it is not. You seem to be thinking that purity is just a bug finding
 or optimization feature. That is not so. Purity is a guarantee that can be
 relied upon for a program's behavior. Breaking purity breaks that
 guarantee.

 (Think multithreaded programs, for example.)
I was not thinking about multi-threaded programs, you are right. But I think just "commenting out" the pure attributes doesn't turn a correct multi-threaded program into an incorrect one.
When you combine that with allowing impure code, then yes it does.
 If you take a D2 program, you remove all its pure attributes and you
 compile it again, the result is generally a program just as correct as
 before.
 "generally" is not a verifiable characteristic. When we talk about safety,
 we're talking about a verifiable guarantee.
Your solution too (of allowing impure code inside debug{} is breaking the guarantees.
Yes. It leaves the onus of correctness on the user rather than the compiler. That's what is required when doing, say, a printf.
 My purpose was to present a debugging problem I have had, to suggest one
 solution, and to try to explain why my solution isn't breaking safety (unlike
 yours).
Any solution either breaks safety or is useless. A printf call breaks purity. There is no way around that. A compiler switch cannot change that.
Apr 16 2011
prev sibling parent reply dennis luehring <dl.soluz gmx.net> writes:
On 11.04.2011 23:27, bearophile wrote:
  From what I am seeing, in a D2 program if I have many (tens or more) pure
functions that call to each other, and I want to add (or activate) a
printf/writeln inside one (or few) of those functions to debug it, I may need
to temporarily comment out the "pure" attribute of many functions (because
printing can't be allowed in pure functions).

 As more and more D2 functions become pure in my code and in Phobos, something
like a -disablepure compiler switch (and printf/writeln inside debug{}) may
allow more handy debugging with prints (if the purity is well managed by the
compiler then I think disabling the pure attributes doesn't change the program
output).

 Bye,
 bearophile
sounds a little bit like the need to see an private/protected part of an interface in unittest scenarios - just to be able to test it in a whitebox-testing without changing the attributes of the productive-code we need a solution for both
Apr 17 2011
parent reply Andrew Wiley <debio264 gmail.com> writes:
On Sun, Apr 17, 2011 at 3:30 PM, dennis luehring <dl.soluz gmx.net> wrote:
 On 11.04.2011 23:27, bearophile wrote:
 =A0From what I am seeing, in a D2 program if I have many (tens or more) =
pure
 functions that call to each other, and I want to add (or activate) a
 printf/writeln inside one (or few) of those functions to debug it, I may
 need to temporarily comment out the "pure" attribute of many functions
 (because printing can't be allowed in pure functions).

 As more and more D2 functions become pure in my code and in Phobos,
 something like a -disablepure compiler switch (and printf/writeln inside
 debug{}) may allow more handy debugging with prints (if the purity is we=
ll
 managed by the compiler then I think disabling the pure attributes doesn=
't
 change the program output).

 Bye,
 bearophile
sounds a little bit like the need to see an private/protected part of an interface in unittest scenarios - just to be able to test it in a whitebox-testing without changing the attributes of the productive-code
Isn't this already there because "private" makes things visible to all other code in the same module?
Apr 17 2011
parent reply dennis luehring <dl.soluz gmx.net> writes:
On 17.04.2011 22:45, Andrew Wiley wrote:
 On Sun, Apr 17, 2011 at 3:30 PM, dennis luehring<dl.soluz gmx.net>  wrote:
 On 11.04.2011 23:27, bearophile wrote:
   From what I am seeing, in a D2 program if I have many (tens or more) pure
 functions that call to each other, and I want to add (or activate) a
 printf/writeln inside one (or few) of those functions to debug it, I may
 need to temporarily comment out the "pure" attribute of many functions
 (because printing can't be allowed in pure functions).

 As more and more D2 functions become pure in my code and in Phobos,
 something like a -disablepure compiler switch (and printf/writeln inside
 debug{}) may allow more handy debugging with prints (if the purity is well
 managed by the compiler then I think disabling the pure attributes doesn't
 change the program output).

 Bye,
 bearophile
sounds a little bit like the need to see an private/protected part of an interface in unittest scenarios - just to be able to test it in a whitebox-testing without changing the attributes of the productive-code
Isn't this already there because "private" makes things visible to all other code in the same module?
ok - but what about protected? as a whitebox tester im not able(allowed) to change productive code,but i need to test through all the code (especially when doing code-coverage stuff)
Apr 21 2011
parent Andrew Wiley <wiley.andrew.j gmail.com> writes:
On Fri, Apr 22, 2011 at 12:34 AM, dennis luehring <dl.soluz gmx.net> wrote:

 On 17.04.2011 22:45, Andrew Wiley wrote:

 On Sun, Apr 17, 2011 at 3:30 PM, dennis luehring<dl.soluz gmx.net>
  wrote:

 On 11.04.2011 23:27, bearophile wrote:

  From what I am seeing, in a D2 program if I have many (tens or more)
 pure
 functions that call to each other, and I want to add (or activate) a
 printf/writeln inside one (or few) of those functions to debug it, I may
 need to temporarily comment out the "pure" attribute of many functions
 (because printing can't be allowed in pure functions).

 As more and more D2 functions become pure in my code and in Phobos,
 something like a -disablepure compiler switch (and printf/writeln inside
 debug{}) may allow more handy debugging with prints (if the purity is
 well
 managed by the compiler then I think disabling the pure attributes
 doesn't
 change the program output).

 Bye,
 bearophile
sounds a little bit like the need to see an private/protected part of an interface in unittest scenarios - just to be able to test it in a whitebox-testing without changing the attributes of the productive-code
Isn't this already there because "private" makes things visible to all other code in the same module?
ok - but what about protected? as a whitebox tester im not able(allowed) to change productive code,but i need to test through all the code (especially when doing code-coverage stuff)
As far as I'm aware, all the visibility levels make things visible to code in the same module.
Apr 22 2011