If statement, throw an error

Anything that doesn't fit elsewhere.
Post Reply
JimH
Posts: 54
Joined: Tue Apr 10, 2007 3:36 pm
Location: Duke University

If statement, throw an error

Post by JimH »

It seems that it is possible to create an assignment in an if statement. I think it would be better if a compiler error were thrown instead and if this behavior were not allowed.

For example:

Code: Select all

test = 1
if(test == 0){
	print "I didn't print"
}

if(test = 0){
	print "I won't print because of the assignment"
}

if(test == 1){
	print "I didn't print but I should have"
}

if(test == 0){
	print "I'll print"
}
The output, as the code suggests, is:

Code: Select all

I'll print
I'm using Neuron 6.0.3 for reference. To clarify, the main problem in the above code is that if(test = 0) sets test equal to zero, instead of throwing an error. Perhaps other people have used for this type of code but instead it seems like this should be a bug, not a feature.
ted
Site Admin
Posts: 6299
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Be fastidious about = vs. ==

Post by ted »

hoc is patterned after C, which was invented ~35 years ago. In both,
the result of an assignment statement is the value that was assigned.
For example

Code: Select all

i = 9
while ((i = i+1) < 20) print i
prints the integers 10 . . . 19.

Lots of working code depends on this property of the assignment statement,
so it isn't going to be changed, even though it is a common error to type

Code: Select all

if (a = b)
when one meant to type

Code: Select all

if (a == b)
Brad

Post by Brad »

I've seen a trick to combat this problem.

Code: Select all

if (0==test) {...}
That way, if you inadvertently omit the second equals sign of the comparison,

Code: Select all

if (0=test) {...}     // syntax error
hoc will fail at the resulting assignment.

A possible drawback is that it often looks aesthetically backwards.

With regard to the opening post, I find it strange that we don't see, "I won't print because of the assignment" on the command line because the variable test is successfully assigned. My copy of Stroustrup (3rd ed.) seems to indicate that declarations in conditionals cause the conditional to evaluate to true, but I don't know if this is one of those instances where C++ is different from C. At any rate, hoc does not execute the block of an IF statement if the conditional contains an assignment, at least for the test case here.
csh
Posts: 52
Joined: Mon Feb 06, 2006 12:45 pm
Location: University College London
Contact:

Post by csh »

Brad wrote:With regard to the opening post, I find it strange that we don't see, "I won't print because of the assignment" on the command line because the variable test is successfully assigned.
The assignment operator (=) returns the result of the assignment in hoc, C and C++ so that you can use chainings such as "x = y = z". This is particularly important when overloading the assignment operator in C++ because you have to make sure that it actually returns a value to comply with this rule. I tested this with these programs:
In C:

Code: Select all

#include <stdio.h>
int main() {
	int k = 0, l = 0;
	int m = (k = 1);
	int n = (l = 0);
	printf("k = %d\nl = %d\nm = %d\nn = %d\n", k, l, m, n);
}
In C++:

Code: Select all

#include <iostream>
int main() {
	int k = 0, l = 0;
	int m = (k = 1);
	int n = (l = 0);
	std::cout << "k = " << k << std::endl;
	std::cout << "l = " << l << std::endl;
	std::cout << "m = " << m << std::endl;
	std::cout << "n = " << n << std::endl;

	bool m_bool = (k = 1);
	bool n_bool = (l = 0);
	std::cout << "m_bool is " << (m_bool ? "true" : "false") << std::endl;
	std::cout << "n_bool is " << (n_bool ? "true" : "false") << std::endl;
}
In hoc:

Code: Select all

k = 0
l = 0
m = (k = 1)
n = (l = 0)
printf("k = %d\nl = %d\nm = %d\nn = %d\n", k, l, m, n)
As expected, all of these programs printed:

Code: Select all

k = 1
l = 0
m = 1
n = 0
Brad wrote:My copy of Stroustrup (3rd ed.) seems to indicate that declarations in conditionals cause the conditional to evaluate to true, but I don't know if this is one of those instances where C++ is different from C.
To my knowledge, a variable declaration without a definition in an if-condition (such as "if (int n) {}") is illegal in both C and C++.
Brad

Post by Brad »

The assignment operator (=) returns the result of the assignment
That makes total sense. Indeed,

Code: Select all

if (test=1) {...}
executes the block. At any rate, I realized that it might be overly verbose to explicitly compare what are practically boolean values when one could just supply the variable itself

Code: Select all

if (test) {...}    // or
it (!test) {...}
Any common-case reasons not to do so besides being explicit? That would be another way of avoiding the original unintended consequence.
...a variable declaration without a definition in an if-condition (such as "if (int n) {}") is illegal..
I was being imprecise; I meant variable definition when I said declaration.
JimH
Posts: 54
Joined: Tue Apr 10, 2007 3:36 pm
Location: Duke University

Post by JimH »

Oops, correction.

Code: Select all

if(test = 0){
   print "I won't print because of the assignment"
} 
This would normally run if test had been set to anything besides zero as an if statement evaluates true if not 0 (could be any other number).

Code: Select all

if(test = 0){
   print "I won't print because the variable has been assigned to zero"
}

     if(test = 2){
   print "I will print because the variable has been assigned a non-zero value"
} 

Any common-case reasons not to do so besides being explicit? That would be another way of avoiding the original unintended consequence.
The original code that I noticed the problem with did not test whether variables were equal to one or zero, but other integer values in a pseudo case statement. I wasn't sure whether or not hoc code supported case statements so instead I just used a few if statements, in which I cared whether or not my variable was equal to 2, or 3, not just that it wasn't zero.

Regarding Ted's code:

Code: Select all

i = 9
while ((i = i+1) < 20) print i
I think that makes a lot of sense in a loop, although some Matlab habits would lend me to changing the value of "i" inside the loop, and even then I would use a for loop in the above case as I typically only use while loops when there is some condition inside of the loop that would lead to alterations in the order. Overall though, I agree.
Lots of working code depends on this property of the assignment statement,so it isn't going to be changed
I'll buy that. I'll just have to be more careful. Although, I still think it is poor code, and shouldn't be included in any language to allow assignment of a variable in an if statement.
Post Reply