Why is the Erlang compiler saying that my clause evaluates to false? - if-statement

When I try to compile the following code:
score(_X) -> mysqrt = math:sqrt(_X),
if
mysqrt < 100.0 -> true;
true -> 0
end.
The compiler says:
src/leap.erl:16: the guard for this clause evaluates to 'false'
I think I am assigning a variable mysqrt and then checking its result, which does not necessarily have to be less than 100.0. Evidently that is not what is happening. What am I doing wrong?

In Erlang, variable names begin with a capital letter or an underscore. In your code, mysqrt is not a variable, but an atom.
The line mysqrt = math:sqrt(_X) is thus an assertion that the return value of math:sqrt is equal to this atom, which will fail because that function returns a floating point number - but the compiler doesn't know this.
Then you compare mysqrt to 100.0. In Erlang, numbers always compare as less than atoms, so mysqrt < 100.0 is always false - this is what the compiler is warning you about.
Call your variable MySqrt instead, and your code should work.
(Also, the convention is to use variable names starting with an underscore only when the variable is not used, as such names suppress "unused variable" warnings from the compiler. It would be more idiomatic to just call the argument to this function X instead of _X.)

Related

no comparison in if() judgement but seems give a boolean value

if(!word.size()){
return true;
}
whole code screenshot
how here use string.size() lonely to return a boolean value?
I googled the string.size() method although i already know it returns a int value,but here it works like a true/false method;
Lots of things in C++ can be coerced to Booleans. Off the top of my head.
Booleans are trivially convertible to Booleans
Numbers (int or double) can be converted to Boolean; zero is false and anything else is true
Streams (like fstream instances or cout, for instance) can be converted to Boolean and are true if the stream is in "good" condition or false if there's a problem
As indicated in the comments, you shouldn't use this in real code. if (!word.size()) is silly and confusing an should only be seen in code golf challenges. Coding isn't just about making the computer understand what you mean; it's about making sure future readers (including yourself six months down the line) understand as well. And if (word.empty()) conveys the exact same intent to the computer but is much more understandable to the human reader at a glance.
So why does C++ allow this if it's discouraged? Historical reasons, mostly. In the days of C, there was no dedicated bool type. Comparisons returned an integer, and the convention was that 0 meant "false" and anything else (usually 1) meant true. It was the programmer's job to remember which things were Booleans and which were actual integers. C++ came along and (rightly) separated the two, making a special type called bool. But for compatibility with C, they left in the old trick of using integers as Booleans. Successor languages like Java would go on to remove that capability. if (myInteger) is illegal in Java and will give a compiler error.
The language checks if the condition inside the conditional is true or false. In this case, the int value gets converted into a boolean. If the size returns 0 this will get converted to false, any other value will be converted to true.

Why is the return type of isdigit() int instead of boolean?

I was reading the cplusplus reference for the isdigit() function, where I got this,
int isdigit ( int c );
Return Value: A value different from zero (i.e., true) if indeed c is
a decimal digit. Zero (i.e., false) otherwise.
What does this term "different from zero" indicate, I mean why we can't just stick to 0 or 1.
Also when I tested this function, it is always returning either 1 or 0, then why simply documentation can't say that isdigit function returns 1, instead of saying "different from zero".
The reason is cross compatibility with C.
C itself didn't acquire a Boolean type until C99 and while that was over 20 years ago there's actually little justification for changing the definition of a widely used library function.
A explicit Boolean type has little practical advantage over the conventional use of 0 for false and non-zero for true other than readability.
By different from zero it means 'not zero'. It's near universal computing convention that when encoding Boolean values as numerical values 0 represents 'false' and all other values can be used to represent 'true'.
In general that's not something to worry about because constructs like if(isdigit(c)) will work because if() conforms to the same convention (in C and C++).
But if you're writing something like count+=isdigit(c) to perhaps count the number of digits in a string you may not get the answer you want.
As pointed out in the comments implementations may have reason for not returning 1 as true.

Why doesn't a user defined conditional work?

I am currently studying OCAML, and have a question about a user-defined if-then such as:
let cond (c,t,e) =
match c with
| true -> t
| false -> e
When used in a factorial function:
let rec fact n =
cond (n=0,1, n * fact (n-1))
Intuitively, it seems to be correct, but I know it will throw a stack overflow error. Can someone explain to me why this is, and how this user-defined if-then differs from the builtin if-then?
Basically your user defined conditional is not lazy evaluated. Before the actual match takes place, OCaml tries to evaluate both expressions you pass - for the true and false cases.
Example:
Let's suppose we try to evaluate fact 2.
The return value is the expression cond (2=0,1, 2 * fact (2-1)). Before the 3-tuple is passes to cond, it has to be fully evaluated. To do that Ocaml has to evaluate the function fact (2-1).
Now we evaluate fact 1. The return value is cond (1=0,1, 2 * fact (1-1)). Again, we need to know the value of fact (1-1), so we compute it recursively.
We evaluate fact 0. Here the problem starts to show. The return value is cond (0=0,1, 0 * fact (0-1)), but in order to evaluate the function cond we first have to evaluate its arguments - the 3-tuple. This makes us evaluate fact (0-1)!
Then, we are evaluating fact -1...
... fact -2 ... fact -3 ... and the stack overflows :)
The built-in if-then evaluates its arguments lazily: first, it checks whether the condition is true or false, then it accordingly chooses only one branch to evaluate - this behavior is called lazy evaluation.
Actually OCaml has operations lazy and force you could use to avoid this undesirable behavior, but probably it is better just to stick to traditional if.

What's the point of issuing a compiler warning for "while(true)" and not issuing one for "for(;;)"?

When I compile C++ code with Visual C++ 9 with "warning level 4" the following:
while( true ) {
//loop body with break on certain condition
}
and the following:
for( ; true; ) {
//same loop body
}
both trigger C4127: conditional expression is constant warning but the following:
for( ; ; ) {
//same loop body
}
compiles without warning.
Why this difference, especially between the second and the third variant?
The reason for warning the user of constant conditional expressions is to help avoid bugs where the expression ends up being constant (for example, due to a typo). In the last case, there is no expression, so there is no risk of it accidentally being constant.
The reason is simple, though stupid.
It is important to diagnose infinite loop, but such might not be evident:
while(i >= 0) { --i; } // infinite if i unsigned
while(SOME_MACRO(i)) // err, depends on the expansion of macros
It is a great feature of a compiler to produce a warning for a tautological test, that is a test that turns out to be either always true or always false, because it's not obvious when it comes from a macro expansion or within a dependent context.
It just seems that VC++ pushed a bit too far here, and instead of considering tautological conditions warns for all true or false conditions it can find, even when they are already clearly stated in the code.
The for ( ;; ) construct is the canonical way to intentionally code an "endless" loop. I could imagine the compiler designers didn't want to generate a warning for that.
No point. After all, the langauge specification says ($6.5.3/2),
Either or both of the condition and
the expression can be omitted. A
missing condition makes the implied
while clause equivalent to
while(true).
So for ( ; ; ) is equivalent to while(true) even according to the Standard. Therefore, I don't see any reason why the compiler should give warning in one case but not in the other!
--
If the compiler decides to give warning, then in my opinion, the compiler should give warning when the condition is missing as opposed to when it's present, so that the warning would be interpreted as hint for programmer to mention his intention clearly and explicitly.
I mean, for ( ;; ) is more likely to be a typo than the explicit mention of condition in for ( ;true; ). The latter tells programmer's clear and explicit intent. As Steve says in comment:
For an int value y, char x = y is
equivalent to char x = (char)y, but
you might want a warning for an
implicit narrowing conversion on the
first but not the second.
So explicit intention should not receive warning, while implicit intention should receive!
Compiler warning are here to help catch potential bugs. Using an always true condition in a while loop is probably an error. For exemple, in the following code, this is probably a bug, and I'd like the compiler to warn me about it:
unsigned int x;
// ...
while (x >= 0) {
// ...
}
In such a situation, in optimized build the compiler will probably deduce that the condition is always true (since an unsigned integer cannot be smaller than 0). So there is a need for detection of an always true condition in while loop. I think that whoever wrote the detection of such an error didn't special case the while (true) case, as there is a simple way to do a infinite loop with for (;;).
You can read here, how the decision to add a warning or not in Visual Studio, is taken (the exemple are about C# but I suppose that the team has the same rule of thumb for warning in C++).

Fortran return statement

I'm trying to get some code compiled under gfortran that compiles fine under g77. The problem seems to be from a return statement:
ffuncs.f:934.13:
RETURN E
1
Error: Alternate RETURN statement at (1) requires a SCALAR-INTEGER return specifier
In the code anything E was specified as real*8:
IMPLICIT REAL*8 ( A - H , O -Z )
However, E was never given a value or anything in fact you never see it until the return statement. I know almost nothing about fortran. What is the meaning of a return statement with an argument in fortran?
Thanks.
In FORTRAN (up to Fortran 77, which I'm very familiar with), RETURN n is not used to return a function value; instead, it does something like what in other languages would be handled by an exception: An exit to a code location other than the normal one.
You'd normally call such a SUBROUTINE or FUNCTION with labels as arguments, e.g.
CALL MYSUB(A, B, C, *998, *999)
...
998 STOP 'Error 1'
998 STOP 'Error 2'
and if things go wrong in MYSUB then you do RETURN 1 or RETURN 2 (rather than the normal RETURN) and you'd be hopping straight to label 998 or 999 in the calling routine.
That's why normally you want an integer on that RETURN - it's not a value but an index to which error exit you want to take.
RETURN E sounds wrong to me. Unless there's a syntax I'm unaware of, the previous compiler should have flagged that as an error.
In a Fortran function one returns the value, by assigning the value to a fake variable which is the same name as the function. Once you do that, simply return.
I think #Carl Smotricz has the answer. Does argument list of ffuncs has dummy arguments that are asterisks (to match the asterisk-label in the calls)? Or was this used without there being alternative returns? If there were no alternative returns, just delete the "E". If there are alternative returns, the big question is what the program was doing before at run time since the variable was of the wrong type and uninitialized. If the variable didn't have an integer value matching one of the expected branches, perhaps the program took the regular return branch -- but that's just a guess -- if so, the easy fix is to again to delete the "E".
The "alternate return" feature is considered "obsolescent" by the language standard and could be deleted in a future standard; compilers would likely continue to support it if it were removed because of legacy code. For new code, one simple alternative is to return an integer status variable and use a "select case" statement in the caller.