www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: Wish: Variable Not Used Warning

reply Era Scarecrow <rtcvb32 yahoo.com> writes:
 In "C++'ish" / D way, this is normally dealt
 like this:
 
 int isPrime(int number, int[] /*primesList*/)
 {
 	//int cnt;
 
 	return 0;
 }
 
 Hard & ugly? I think warnings are not meant to be used
 to remember you 
 that you have something unfinished. I regularly tag those
 parts with "//
 todo", which is easily grep'd from code.

Maybe in that instance no it isn't hard or ugly. However if i had continued and partially implimented, you need it enabled, but enabled doesn't help much since you can't get to it. //returns true/flase if a prime. bool isPrime(int number, int[] primesList) { int cnt; bool prime = true; primesList = null; //disable for now. When fully implimented, remove if (primesList) //gives an error since it never executes, but logic is there. { foreach (pnum; primesList) { //finish later } } else for (cnt = 2; cnt < number; cnt++) if (number % cnt == 0) prime=false; return prime; } Being partially implimented, i don't really want to comment out large areas of my code, since i want to know if i wrote it wrong, or right. I'll in the middle of my project, make sure all my block openings/closings are good, and then compile the code, which i will never run but instead i use the errors and warnings to find certain bugs and simple problems earlier, rather then do an entire file and then trace all the bugs all at once. Or am i doing it wrong?
 It is not about consuming memory, it's about compiling
 code that won't 
 work. It is not about making intentionally dead code,
 it's about 
 accidentally having dead code.

Agreed. truely dead code should reply an error.
 Because syntactic salts and more pedantic checkings save a
 lots of 
 debugging time.
 
  It was these very things that kept me from learning

  too hard for me to grasp because it was ugly, and i

  something ugly.

Warnings & checkings does not make C++ ugly :)

No, i mean the :: operator, and other details in the language. Sorry for the confusion there.
 Constant conditionals:
 
 const DEBUG = 0;
 
 ..
 
 if (DEBUG) {
     //put debugging information
 }

1) Use static if?

Still learning D, i've seen references of static if's but i haven't read enough on it yet.
 2) Anyway, it is not constant conditional in that way that
 it is normally 
 warned - you have intentionally set the value so, and thus
 the compiler 
 could optimize the dead code away without problem. Normally
 it is warned, 
 if you have an expression:
 
 	for(...; (a + b) < 8; ...) { ... }
 
 ...if the compiler recognizes, that the condition cannot
 never be 
 anything else than true or false, do you think it is
 intentional?

if it was truely intentional, then wouldn't you do..? for (;;){} or while(true){} if it wasn't intentional, then you were trying to actually check for something.
 
 while(1)    //always true
 {
     if (someCondition){
         break;
     }
 }

The same hold here; "while(true)", "for(;;)" are intentionally written to be infinite loops. I regularly define in C/C++:

those are truely intentional, a contition should actually have a chance to change and be true/false at different steps, correct?
 #define forever for(;;)
 
 I really don't mean, that the "warning
 system" should be something like 
 "code smelling analyzing" for refactoring, but I
 think that most of those 
 basic things could easily be catched at compile time (w/
 warnings) 
 without any negative side effects.

Jul 10 2008
parent Markus Koskimies <markus reaaliaika.net> writes:
On Thu, 10 Jul 2008 10:10:49 -0700, Era Scarecrow wrote:

 //returns true/flase if a prime.
 bool isPrime(int number, int[] primesList) {
 	int cnt;
 	bool prime = true;
 
 	primesList = null;	//disable for now.
                               //When fully implimented, remove
 
 	if (primesList)	//gives an error since it never executes,
                       //but logic is there. 
       {
 		foreach (pnum; primesList)
 		{
 		//finish later
 		}
 
 	}
 	else
 		for (cnt = 2; cnt < number; cnt++)
 			if (number % cnt == 0)
 				prime=false;
 
 
 	return prime;
 }

Hmmh, if I would do something like that, I would do it like this: bool isPrime(int number, int[] /* primesList */) { bool prime = true; static if(false) { // Partial implementation; should still be // syntactically valid D foreach(pnum; primesList) { ... } } else { for(int cnt = 2; ...) { ... } } return prime; } In fact, I wouldn't even put that list scanning part there, if I'm working with the loop there. Even when I'm just sketching code, I try to avoid large numbers of unused and incomplete parts there; I mainly sketch the interface, and start from core parts to put things together.
  Being partially implimented, i don't really want to comment out large
  areas of my code, since i want to know if i wrote it wrong, or right.

Yeah, I don't like large out-commented blocks either. But I normally write the code in pieces, so at that case I would first implement that loop and only slightly - if at all - touch to that primesList part. This easily goes to a discussion about how to sketch code, and I try to avoid that. I still see no use to allow unused vars & members and dead code, since they are regularly easily work-arounded in D during sketching phase, and you don't want them to be there at the end.
  I'll in the middle of my project, make sure all my block
  openings/closings are good, and then compile the code, which i will
  never run but instead i use the errors and warnings to find certain
  bugs and simple problems earlier, rather then do an entire file and
  then trace all the bugs all at once.

That's exactly the same way I work with the code. I keep adding blocks and continuously compile to see, if there are warnings or errors. If there would be a situation like above, and I would be just added that list scanning part but being still unsure if it works, I would add there an assert or similar to catch the program immediately if it goes there; bool isPrime(int number, int[] primeList) { if(primeList) { assert(false); // Don't go here at the moment foreach(pnum; primeList) { ... } } else { for(int cnt; ...;) if(!(number%cnt)) return false; return true; } } But anyway, if I would starting to make that part, the build-stoppable warnings about unused code and similar would not be a big issue any more, since I would not be executing the program until I get the errors & warnings away.
  Or am i doing it wrong?

I don't think so, but I feel that warnings and code sketching are not mutually exclusive things :D Anyway, I surfed in the net and found some writings about warnings and D. I'll quote here two things; Walter Bright about Redundancy in Programming Languages: "You can get a feel for where redundancy in a language is lacking by looking at warning diagnostics the compiler implementors tend to add over time. For the designer of a new language, common warnings are a rich source of inspiration for improvements." http://dobbscodetalk.com/index.php?option=com_myblog&show=Redundancy-in- Programming-Languages.html&Itemid=29 D 2.0 Overview, "Who D is Not For"; "Language purists. D is a practical language, and each feature of it is evaluated in that light, rather than by an ideal." http://www.digitalmars.com/d/2.0/overview.html Warnings may indicate imperfectness in language design, but from practical point of view I would accept that and add all practical warnings, although my aim would get rid of them in the future.
  Still learning D, i've seen references of static if's but i haven't
  read enough on it yet.

Static if is something like #if-#endif in C/C++, but since it is in the compiler, it knows all about the constants & types in the code (unlike C preprocessor) \o/
 if you have an expression:
 
 	for(...; (a + b) < 8; ...) { ... }
 
 ...if the compiler recognizes, that the condition cannot never be
 anything else than true or false, do you think it is intentional?

if it was truely intentional, then wouldn't you do..?

Assume, that (a+b) is always smaller than 8, which causes infinite loop. The compiler is able to know that. If the programmer was intentionally making an infinite loop, why didn't he use "for(;;)" or "while(true)"? If the compiler gives an error, that the expression is always true, I think there are two possibilities: 1) The programmer was checking out how smart is the compiler, by expressing an infinite loop in a hard way; to get the code compiled, he should change it to regular "for(;;)" or "while(true)". 2) The programmer didn't notice, that the values he was using are never evaluated greater than the intended loop termination condition. He re- examines the code and probably finds something that he was missing in the first attempt (forgot to add some other value, forgot to change the loop termination condition, ...) Win-win -situation, isn't that?
  if it wasn't intentional, then you were trying to actually check for
  something.

Exactly. That's why I like error-like warnings, that won't pass through suspicious parts.
 while(1)    //always true
 {
     if (someCondition){
         break;
     }
 }

The same hold here; "while(true)", "for(;;)" are intentionally written to be infinite loops. I regularly define in C/C++:

those are truely intentional, a contition should actually have a chance to change and be true/false at different steps, correct?

From this point on, I don't any more use the word warning. Instead I use the word error. I'm not speaking about "Variable Not Used *Warning*", but instead of "Variable Not Used *Error*" and "Unreachable Statement *Error*". Yes, right. Of course, compiler should not give any kind of warning if the loop is clearly intentionally made infinite, or if the condition is clearly intentionally made constant: while(true) ... // No error if(true) ... // No error auto a=file.getSize("myfile.txt"); // ulong ... while( a != -1) ... // Error In fact, I would change the default behavior of the compiler so that it uses all warnings and regards them as errors. For testing out incomplete code, a "--cmon-relax" flag could be used :)
Jul 10 2008