Why doesn't a user defined conditional work? - ocaml

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.

Related

How does Lua check conditions in an IF statement?

I am trying to optimize my IF statement in Lua. When there are two conditions in an IF statement with the AND operator, does Lua read left to right and stop as soon as it reaches one false? That is, if there is a condition which is quick to check and a condition which is slower to check, is it more efficient to put the condition which is quick to check first (i.e. left most)?
For example, assume I have two functions that return true or false, quick_fn() and slow_fn(), and I want to execute code only if both functions return true. In terms of speed, is there a difference between the following two ways of writing this code? If Option #1 is equivalent, should I always be putting the quick_fn() in the leftmost spot?
Option #1:
if quick_fn() AND slow_fn() then
[code]
end
Option #2:
if quick_fn() then
if slow_fun() then
[code]
end
end
This is explained in the Lua documentation (emphasis added):
The negation operator not always returns false or true. The
conjunction operator and returns its first argument if this value is
false or nil; otherwise, and returns its second argument. The
disjunction operator or returns its first argument if this value is
different from nil and false; otherwise, or returns its second
argument. Both and and or use short-circuit evaluation; that is, the
second operand is evaluated only if necessary.
Note that the operator is spelled and, not AND. Lua is case-sensitive.

What is ACTUALLY happening with parenthesis '()' in Clojure?

I'm looking for the technical answer answer here. How is Clojure interpreting these symbols? My current working understanding is that the opening paren '(' is a kind of call that calls the succeeding operator on the operands while the closing paren ')' is a terminate that wraps up the previous evaluation and returns the final value generated (whether function or value).
Any and all details on the truth here would be appreciated. I'm looking to go deep here as well as seeing/knowing every level of abstraction along the way. It bugs me to know that I may have some imaginal thinking going on currently.
(foo x1 x2)
is the syntax for calling a special form or var (function or macro).
So the compiler will analyze the form (foo x1 x2) and will check if foo is a special form (if, try, let*, etc.) and if not, the symbol will be resolved to a var in the context of the current namespace. If that var is macro, then macroexpansion will happen, else the call will be treated as a normal function call.
To prevent treating (foo x1 x2) as a function call you can quote the expression: '(foo x1 x2) and then it will just remain a list of symbols.
More info:
https://clojure.org/reference/special_forms
https://clojure.org/reference/macros
You are trying to do too much at once when you say
'(' is a kind of call that calls the succeeding operator on the operands while the closing paren ')' is a terminate that wraps up the previous evaluation and returns the final value generated
The Clojure evaluation model does not assign semantics to characters directly. Instead, evaluation of a Clojure program goes through two broad phases:
First, read the characters in the source file according to the language's lexical rules, yielding a Clojure data structure
Second, evaluate that data structure, according to the language's evaluation rules, yielding a value
So when we write an expression like (+ (* 4 5) 2), what happens? The reader matches up parentheses to create lists, and yields as its result a list of three elements: the symbol +, another list (containing the symbol * and the numbers 4 and 5), and the number 2.
Next we move to evaluate that expression. Notice, crucially, that at this point there is no trace of parentheses. The textual source of the program is no longer material. We're evaluating a list. Of course, if we printed that list, conventionally we would surround it with parentheses, but that does not concern the evaluator. How do we evaluate this list? Well, the evaluation rule for lists is to, first, evaluate each of the components, and then invoke the first component as a function, passing the remaining components as arguments1. So our list of pending tasks is:
Evaluate +
Evaluate (* 4 5)
Evaluate 2
Invoke the result of (1), passing the results of (2) and (3) as arguments
(1), of course, evaluates to the addition function, (2) evaluates (in a similar manner) to the number 20, and (3) evaluates to the number 2 (since numbers evaluate to themselves). Thus, (4) becomes "Invoke the addition function, passing the numbers 20 and 2 as arguments". Of course, the final result is 22.
1 The rule is actually more complicated than this, because of macros, but for functions this suffices.
The other 2 answers are great. The simple summary is:
foo( x1, x2 ) // Java function call
(foo x1 x2) // Clojure function call
In both cases, the compiler will evaluate any nested function calls in x1 or x2 before calling foo on the resulting values.

Checking null pointer && pointer->member value in the same if statement

This is a pretty basic question, but I could not find a clear answer:
is it allowed to check that a pointer is not null and (&&) to also check one of its members value in the same if statement?
Rephrased: is the right part of the condition in the example below even evaluated if f is null?
I know this works in VS current version, but what I need to know is if this is allowed by the C++ standard (or if it's UB).
Also, if I write it as 2 separate if to make it more readable, can I expect the compiler to optimize it into a single if?
struct foo
{
bool bar;
};
void main(){
foo *f;
// DO THINGS
if (f != null && f->bar == true)
{
// DO THINGS
}
}
Edit: the question is different from this one because it's not obvious that it's simply a matter of order: the proof is I did not end on that SO answer when I googled my question.
...is it allowed to check that a pointer is not null and (&&) to also check one of its members value in the same if statement?
It's perfectly valid, it is not UB, the expression is evaluated from left to right, if the left part of the expression evaluates to false the right part is not evaluated. This is usually called operator short circuit.
The rationale is that if the first part is false, there is no possibilty of the whole expression being true, false && false is false, false && true is also false.
...if I write it as 2 separate if to make it more readable, can I expect the compiler to optimize it into a single if?
In light of the above answer, you wouldn't need two ifs, I would argue that it will not make your code more readable, I prefer the way you have it right know, in any case this is only my opinion. About the compiler, I wouldn't think that there will be much difference either way, as sampled in this live demo.
is it allowed to check that a pointer is not null and (&&) to also check one of its members value in the same if statement?
Yes.
is the right part of the condition in the example below even evaluated if f is null?
No.
what I need to know is if this is allowed by the C++ standard
Yes.
(or if it's UB)
No.
Also, if I write it as 2 separate if to make it more readable, can I expect the compiler to optimize it into a single if?
I would expect it. Seems like a trivial optimisation. Note that in cases where the && operator is overloaded (which never is in the case of pointers), such change can change the meaning of the program.
Standard quote (latest draft):
[expr.log.and]
The && operator groups left-to-right.
The operands are both contextually converted to bool.
The result is true if both operands are true and false otherwise.
Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false.

Confusion while evaluating conditions with more than one logical NOT operator

I'm confused when code includes more than one NOT operator like:
if (!x != !0)
;
or similar. I can read it as: if NOT x is NOT equal to NOT zero,
but in my mind I'm totally confused about what it actually means.
Do you have any advice regarding this? I.e. how to understand such code, where to start reading or etc.
Another example:
if(!x == !1)
You can use truth table if you are not sure. For instance
x | 0 | x!=0 | !x | !0 | !x != !0
0 | 0 | 0 | 1 | 1 | 0
1 | 0 | 1 | 0 | 1 | 1
If have problems with many && and ||, use de Morgan's laws
to make things simpler, evaluate the operator! first then read L->R.
Things to remember:
!0 = 1 // true
!1 = 0 // false
so your condition can be simplified to:
if (!x != true) // !0
if (!x == false) // !1
Now, any non-zero value when inverted will be zero.
int x = 10;
!x // zero
Zero when inverted is true.
int x = 0;
!x // one
In C or C++, true is 1 and false is 0
I got troubled as well with simalar syntax when I started developing on PowerBuilder, then I realized I just need to imagine it as a nested if checking false.
For example !x become if(x)=false so it makes more clear that is true when x is false or zero.
In C 0 is false, whatever is not zero is true.
In the same logic !1 is always false and !0 is always true, despite I cannot see the reason to type it in this confusing way, maybe the code you are looking at is coming out from a sort of automatic generator / converter.
First take a look at operator precedence. You will see that logical operators like ! take precedence over relational operators like !=.
Secondly, what is !0 - this suspiciously sounds like there is an implicit conversion from int to bool there - otherwise !0 would make no sense at all.
In your example, you need to evaluate the logical operators first (i.e. !x and !0), then check if they are not equal !=. That said, this kind of code is really bad as it is really hard to read - avoid writing code like this, if possible (and consider refactoring it - while covered by unit tests - if you encounter it in "the wild")
I assume that the question is about C, and therefore I will give the answer in C.
You need to know the precedence rules - the ! binds stronger than the !=. Therefore the expression can be clarified using parentheses as (!x) != (!0). Now, the next thing is to know what ! will do - the result will be 0 if the operand is non-zero, 1 if it is zero. Therefore, !0 can be constant-folded to 1.
Now we have (!x) != 1. Since the !x is 1 iff x is zero, the result of this entire expression will be 1 iff x is non-zero, 0 otherwise.
We can therefore reduce this expression into the more idiomatic double-negation: !!x. However, the if clause in itself tests whether the expression is non-zero, therefore the entire if statement can be changed to if (x) ; (and since the expression does guard only a null-statement, it can be elided altogether)
This kind of code is designed to trick you. Your brain have difficulty to process double-negation or triple negation (and you are not the only one).
You need to know what are the priority rules, and apply it:
(!x == !1) is equal to ((!x) == (!1))
If you see this kind of code during a code review, you should definitely highlight it, and ask for an update.
Please note that in C++ you can also use not instead of !. It can makes things easier to understand:
(!x == !1) is equal to ((not x) == (not 1))
In C and C++, a value of zero is considered "false", and a nonzero value is considered "true". But it can occasionally be confusing, and occasionally causes minor problems, that two different values can both be considered true even though they're, well, different.
For example, suppose you had a function is_rich() that told you whether a person was rich or not. And suppose you wrote code like this:
int harry_is_rich = is_rich("Harry");
int sally_is_rich = is_rich("Sally");
Now the variable harry_is_rich is zero or nonzero according to whether Harry is poor or rich, and sally_is_rich is zero or nonzero according to whether Sally is poor or rich.
Now suppose you're interested in knowing whether Harry and Sally are both rich, or both poor. Your first thought might be
if(harry_is_rich == sally_is_rich)
But wait. Since any nonzero value is considered "true" in C, what if, for some reason, the is_rich() function returned 2 when Harry was rich, and returned 3 when Sally was rich? That wouldn't be a bug, per se -- the is_rich() function perfectly meets its specification of returning nonzero if the person is rich -- but it leads to the situation that you can't write
if(harry_is_rich == sally_is_rich)
(Well, of course you can write it, but like any buggy code, it might not work right.)
So what can you do instead? Well, one possibility is to write
if(!harry_is_rich == !sally_is_rich)
You can read this as "If it's not the case that Harry is rich has the same truth value as not the case that Sally is rich". And, while it's obviously a little contorted, you can kind of convince yourself that it "means" the same thing.
And, although it's a little confusing, it has the advantage of working. It works because of the other confusing aspect of true/false values in C and C++.
Although, as I said, zero is considered false and any nonzero value is considered true, the built-in operators that generate true/false values -- the ones like &&, ||, and ! -- are in fact guaranteed to give you exactly 0 or 1. (That is, the built-in functions are significantly different that functions like is_rich() in this regard. In general, is_rich() might return 2, or 3, or 37 for "true". But &&, ||, and ! are guaranteed to return 1 for true, and 0 for false.)
So when you say !harry_is_rich, you'll get 0 if Harry is rich, and 1 if Harry is not rich. When you say !sally_is_rich, you'll get 0 if Sally is rich, and 1 if Sally is not rich. And if you say
if(!harry_is_rich == !sally_is_rich)
you'll correctly discover whether Harry and Sally are both rich, or both poor, regardless of what values is_rich() chooses to return.
One more thing, though. In all of this I've been considering integers (or other types that might have lots of values). But both C and C++ have bool types, that more succinctly represent true/false values. For a bool type, there are exactly two values, true and false (which are represented as 1 and 0). So for a bool type, you can't have a true value that's anything other than 1. So if the is_rich() function was declared as returning bool, or if you declared your variables as bool, that would be another way of forcing the values to 0/1, and in that case the condition
if(harry_is_rich == sally_is_rich)
would work fine. (Furthermore, when I said that operators like &&, ||, and ! are guaranteed to return exactly 1 or 0, that's basically because these operators don't "return" arbitrary integers, but instead "return" bools.)
See also the C FAQ list, question 9.2.
(Oh, wait. One more thing. The opposite of "rich" isn't necessarily "poor", of course. :-) )

Evaluating order 'and' for C++ in relation with null pointers

Please consider the following block of C++-code.
call * pCall; // Make a pointer to private variable call.
pCall = NULL; // We are sure that it is a null pointer.
aMemberFuntionThatMayChangeTheValueOfpCall();
if (pCall != NULL and pCall->isDelivered() == false){
doSomething();
}
I would like to execute some lines of code, here represented by doSomething(), if and only if pCall is not a null pointer and pCall->isDelivered() is false.
However, I read that the order of evaluation is unspecified. So theoretically the compiler may evaluate pCall->isDelivered() first, and run into a run time exception. However, in the debugging sessions it seems to evaluate the and-operator left to right. Can someone please shine a light on this? I don't want any failures of the code when it gets into a production environment or when it gets executed on another machine.
Of course it is possible to make it into two nested if-statements, but this makes the source far more unreadable because I need this kind of code multiple times.
Can anyone tell me how to do this evaluation in one if-statement such that there is no misevaluation?
Your and operator is more commonly written in C++ as &&, but they are both the same "logical and" operator. For this operator the order of evaluation is specified and evaluation is executed from left to right, guaranteed. (Otherwise millions of existing programs would fail).
The exception - not applicable to your code - is when the && operator is overloaded. In this case the left-to-right rule does not work. BTW it is a main reason why it is recommended not to overload this operator.
Your code below will work (I've changed 'and' to '&&' and added parentheses):
if ( (pCall != NULL) && (pCall->isDelivered() == false) ) {
doSomething();
}
because the logical-AND && will 'short circuit'; i.e. if the first expression is false, the second will not be evaluated. Evaluation order is from left to right in this case.
The following relates to the Miscosoft C++ compiler in VS2013:
Logical operators also guarantee evaluation of their operands from
left to right. However, they evaluate the smallest number of operands
needed to determine the result of the expression. This is called
"short-circuit" evaluation. Thus, some operands of the expression may
not be evaluated. For example, in the expression x && y++ the second
operand, y++, is evaluated only if x is true (nonzero). Thus, y is not
incremented if x is false (0).