So for binary operators on booleans, Java has &, |, ^, && and ||.
Let's summarize what they do briefly here:
JLS 15.22.2 Boolean Logical Operators &, ^, and |
JLS 15.23 Conditional-And Operator &&
JLS 15.24 Conditional-Or Operator ||
For &, the result value is true if both operand values are true; otherwise, the result is false.
For |, the result value is false if both operand values are false; otherwise, the result is true.
For ^, the result value is true if the operand values are different; otherwise, the result is false.
The && operator is like & but evaluates its right-hand operand only if the value of its left-hand operand is true.
The || operator is like |, but evaluates its right-hand operand only if the value of its left-hand operand is false.
Now, among all 5, 3 of those have compound assignment versions, namely |=, &= and ^=. So my question is obvious: why doesn't Java provide &&= and ||= as well? I find that I need those more than I need &= and |=.
And I don't think that "because it's too long" is a good answer, because Java has >>>=. There must be a better reason for this omission.
From 15.26 Assignment Operators:
There are 12 assignment operators; [...] = *= /= %= += -= <<= >>= >>>= &= ^= |=
A comment was made that if &&= and ||= were implemented, then it would be the only operators that do not evaluate the right hand side first. I believe this notion that a compound assignment operator evaluates the right hand side first is a mistake.
From 15.26.2 Compound Assignment Operators:
A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.
As proof, the following snippet throws a NullPointerException, not an ArrayIndexOutOfBoundsException.
int[] a = null;
int[] b = {};
a[0] += b[-1];
Reason
The operators &&= and ||= are not available on Java because for most of the developers these operators are:
error-prone
useless
Example for &&=
If Java allowed &&= operator, then that code:
bool isOk = true; //becomes false when at least a function returns false
isOK &&= f1();
isOK &&= f2(); //we may expect f2() is called whatever the f1() returned value
would be equivalent to:
bool isOk = true;
if (isOK) isOk = f1();
if (isOK) isOk = f2(); //f2() is called only when f1() returns true
This first code is error-prone because many developers would think f2() is always called whatever the f1() returned value. It is like bool isOk = f1() && f2(); where f2() is called only when f1() returns true.
If the developer wants f2() to be called only when f1() returns true, therefore the second code above is less error-prone.
Else &= is sufficient because the developer wants f2() to be always called:
Same example but for &=
bool isOk = true;
isOK &= f1();
isOK &= f2(); //f2() always called whatever the f1() returned value
Moreover, the JVM should run this above code as the following one:
bool isOk = true;
if (!f1()) isOk = false;
if (!f2()) isOk = false; //f2() always called
Compare && and & results
Are the results of operators && and & the same when applied on boolean values?
Let's check using the following Java code:
public class qalcdo {
public static void main (String[] args) {
test (true, true);
test (true, false);
test (false, false);
test (false, true);
}
private static void test (boolean a, boolean b) {
System.out.println (counter++ + ") a=" + a + " and b=" + b);
System.out.println ("a && b = " + (a && b));
System.out.println ("a & b = " + (a & b));
System.out.println ("======================");
}
private static int counter = 1;
}
Output:
1) a=true and b=true
a && b = true
a & b = true
======================
2) a=true and b=false
a && b = false
a & b = false
======================
3) a=false and b=false
a && b = false
a & b = false
======================
4) a=false and b=true
a && b = false
a & b = false
======================
Therefore YES we can replace && by & for boolean values ;-)
So better use &= instead of &&=.
Same for ||=
Same reasons as for &&=:
operator |= is less error-prone than ||=.
If a developer wants f2() not to be called when f1() returns true, then I advice the following alternatives:
// here a comment is required to explain that
// f2() is not called when f1() returns false, and so on...
bool isOk = f1() || f2() || f3() || f4();
or:
// here the following comments are not required
// (the code is enough understandable)
bool isOk = false;
if (!isOK) isOk = f1();
if (!isOK) isOk = f2(); //f2() is not called when f1() returns false
if (!isOK) isOk = f3(); //f3() is not called when f1() or f2() return false
if (!isOK) isOk = f4(); //f4() is not called when ...
Probably because something like
x = false;
x &&= someComplexExpression();
looks like it ought to be assigning to x and evaluating someComplexExpression(), but the fact that the evaluation hinges on the value of x isn't apparent from the syntax.
Also because Java's syntax is based on C, and no one saw a pressing need to add those operators. You'd probably be better off with an if statement, anyway.
It is this way in Java, because it is this way in C.
Now the question why it is so in C is because when & and && became different operators (sometime preceding C's descent from B), the &= variety of operators was simply overlooked.
But the second part of my answer does not have any sources to back it up.
Largely because Java syntax is based on C (or at least the C family), and in C all those assignment operators get compiled to arithmetic or bitwise assembly instructions on a single register. The assignment-operator version avoids temporaries and may have produced more efficient code on early non-optimising compilers. The logical operator (as they are termed in C) equivalents (&&= and ||=) don't have such an obvious correspondence to single assembly instructions; they usually expand to a test and branch sequence of instructions.
Interestingly, languages like ruby do have ||= and &&=.
Edit: terminology differs between Java and C
One of Java's original aims was to be "Simple, Object Oriented, and Familiar." As applied to this case, &= is familiar (C, C++ have it and familiar in this context meant familiar to someone who knows those two).
&&= would not be familiar, and it would not be simple, in the sense that the language designers were not looking to think of every operator they could add to the language, so less extra operators are simpler.
For Boolean vars, && and || would use short circuit evaluation while & and | don't, so you would expect &&= and ||= to also use short circuit evaluation. There is a good use case for this. Especially if you are iterating over a loop, you want to be fast, efficient and terse.
Instead of writing
foreach(item in coll)
{
bVal = bVal || fn(item); // not so elegant
}
I want to write
foreach(item in coll)
{
bVal ||= fn(item); // elegant
}
and know that once bVal is true, fn() will not be called for the remainder of the iterations.
'&' and '&&' are not the same as '&&' is a short cut operation which will not do if the first operand is false while '&' will do it anyway (works with both number and boolean).
I do agree that it make more sense to exist but it is not that bad if it is not there. I guess it was not there because C does not have it.
Really can't think of why.
Brian Goetz (Java Language Architect at Oracle) wrote:
https://stackoverflow.com/q/2324549/ [this question] shows that there is interest in having these operators and there
are no clear arguments why they don't exist yet.
The question is therefore: Has the JDK team discussed adding these operators in the past and if so
what where the reasons against adding them?
I'm not aware of any specific discussion on this particular issue, but
if someone were to propose it, the answer would likely be: it's not an
unreasonable request, but it doesn't carry its weight.
"Carrying its weight" needs to be judged by its costs and benefits, and
by its cost-benefit ratio relative to other candidate features.
I think you are implicitly assuming (by the phrase "there is interest")
that the cost is near zero and the benefit is greater than zero, so it
seems an obvious win. But this belies an incorrect understanding of
cost; a feature like this affects the language spec, the implementation,
the JCK, and every IDE and Java textbook. There are no trivial language
features. And the benefit, while nonzero, is pretty small.
Secondarily, there are infinitely many features we could do, but we
only have capacity to do a handful every few years (and users have a
limited capacity to absorb new features.) So we have to be very careful
as to which we pick, as each feature (even a trivial-seeming one)
consumes some of this budget, and invariably takes it away from others.
It's not "why not this feature", but "what other features will we not do
(or delay) so we can do this one, and is that a good trade?" And I
can't really imagine this being a good trade against anything else we're
working on.
So, it clears the bar of "not a terrible idea" (which is already pretty
good, a lot of feature requests don't even clear that), but seems
unlikely to ever clear the bar of "a better use of our evolution budget
than anything else."
It is allowed in Ruby.
If I were to guess, I would say that it is not frequently used so it wasn't implemented. Another explanation could be that the parser only looks at the character before the =
I cannot think of any better reason then 'It looks incredible ugly!'
&
verifies both operands, it's a bitwise operator. Java defines several bitwise operators, which can be applied to the integer types, long, int, short, char, and byte.
&&
stops evaluating if the first operand evaluates to false since the result will be false, it's a logical operator. It can be applied to booleans.
The && operator is similar to the & operator, but can make your code a bit more efficient. Because both expressions compared by the & operator must be true for the entire expression to be true, there’s no reason to evaluate the second expression if the first one returns false. The & operator always evaluates both expressions. The && operator evaluates the second expression only if the first expression is true.
Having a &&= assignment operator wouldn't really add new functionality to the language. The bitwise operator's arithmetic is much more expressive, you can do integer bitwise arithmetic, which includes Boolean arithmetic. The logical operators can merely do Boolean arithmetic.
Funny I came across this question.
The operators ||= and &&= do not exist as their semantics are easily misunderstood;
if you think you need them, use an if-statement instead.
Ely (post just above) got the gist right:
||
stops evaluating if the first operand evaluates to true since the result will be true, it's a logical operator.
So imagine what will happen if b == true;
b ||= somethingreturningaboolean(); // !!??
this will not invoke somethingreturningaboolean(), if b == true.
This behavior is more obvious in the long form:
b = b || somethingreturningaboolean();
That's why ||= and &&= ops do not exist. The explanation should be given as:
The operators ||= and &&= do not exist as their semantics are easily misunderstood;
if you think you need them, use an if-statement instead.
Related
I was working on this easy problem to practice basic Kotlin, and I ran into a stack overflow with the following code on the recursive return line:
class Solution {
fun isPalindrome(s: String): Boolean {
val cleaned = s.toLowerCase().replace(Regex("[^a-z0-9]"), "")
tailrec fun isPalindrome(start: Int, end: Int): Boolean {
if (start >= end) return true
return cleaned[start] == cleaned[end] && isPalindrome(start+1, end-1)
}
return isPalindrome(0, cleaned.length-1)
}
}
My understanding of tailrec is that it's supposed to convert my recursive function into an iterative one, which wouldn't be susceptible to this sort of crash. If I didn't implement tail recursion correctly, the compiler is supposed to issue an error.
Can someone explain to me why this crashes on large inputs, just like a standard recursive call would?
This behavior looks like a missing optimization of tail calls in short circuiting operators, where the fact that the last operand is being evaluated means that the expression result doesn't depend anymore on the previous operands.
Meanwhile you can rewrite your return statement as
return if (cleaned[start] != cleaned[end]) false else isPalindrome(start+1, end-1)
to get the same result + tail call optimization.
let list p = if List.contains " " p || List.contains null p then false else true
I have such a function to check if the list is well formatted or not. The list shouldn't have an empty string and nulls. I don't get what I am missing since Check.Verbose list returns falsifiable output.
How should I approach the problem?
I think you don't quite understand FsCheck yet. When you do Check.Verbose someFunction, FsCheck generates a bunch of random input for your function, and fails if the function ever returns false. The idea is that the function you pass to Check.Verbose should be a property that will always be true no matter what the input is. For example, if you reverse a list twice then it should return the original list no matter what the original list was. This property is usually expressed as follows:
let revTwiceIsSameList (lst : int list) =
List.rev (List.rev lst) = lst
Check.Verbose revTwiceIsSameList // This will pass
Your function, on the other hand, is a good, useful function that checks whether a list is well-formed in your data model... but it's not a property in the sense that FsCheck uses the term (that is, a function that should always return true no matter what the input is). To make an FsCheck-style property, you want to write a function that looks generally like:
let verifyMyFunc (input : string list) =
if (input is well-formed) then // TODO: Figure out how to check that
myFunc input = true
else
myFunc input = false
Check.Verbose verifyMyFunc
(Note that I've named your function myFunc instead of list, because as a general rule, you should never name a function list. The name list is a data type (e.g., string list or int list), and if you name a function list, you'll just confuse yourself later on when the same name has two different meanings.)
Now, the problem here is: how do you write the "input is well-formed" part of my verifyMyFunc example? You can't just use your function to check it, because that would be testing your function against itself, which is not a useful test. (The test would essentially become "myFunc input = myFunc input", which would always return true even if your function had a bug in it — unless your function returned random input, of course). So you'd have to write another function to check if the input is well-formed, and here the problem is that the function you've written is the best, most correct way to check for well-formed input. If you wrote another function to check, it would boil down to not (List.contains "" || List.contains null) in the end, and again, you'd be essentially checking your function against itself.
In this specific case, I don't think FsCheck is the right tool for the job, because your function is so simple. Is this a homework assignment, where your instructor is requiring you to use FsCheck? Or are you trying to learn FsCheck on your own, and using this exercise to teach yourself FsCheck? If it's the former, then I'd suggest pointing your instructor to this question and see what he says about my answer. If it's the latter, then I'd suggest finding some slightly more complicated function to use to learn FsCheck. A useful function here would be one where you can find some property that should always be true, like in the List.rev example (reversing a list twice should restore the original list, so that's a useful property to test with). Or if you're having trouble finding an always-true property, at least find a function that you can implement in at least two different ways, so that you can use FsCheck to check that both implementations return the same result for any given input.
Adding to #rmunn's excellent answer:
if you wanted to test myFunc (yes I also renamed your list function) you could do it by creating some fixed cases that you already know the answer to, like:
let myFunc p = if List.contains " " p || List.contains null p then false else true
let tests =
testList "myFunc" [
testCase "empty list" <| fun()-> "empty" |> Expect.isTrue (myFunc [ ])
testCase "nonempty list" <| fun()-> "hi" |> Expect.isTrue (myFunc [ "hi" ])
testCase "null case" <| fun()-> "null" |> Expect.isFalse (myFunc [ null ])
testCase "empty string" <| fun()-> "\"\"" |> Expect.isFalse (myFunc [ "" ])
]
Tests.runTests config tests
Here I am using a testing library called Expecto.
If you run this you would see one of the tests fails:
Failed! myFunc/empty string:
"". Actual value was true but had expected it to be false.
because your original function has a bug; it checks for space " " instead of empty string "".
After you fix it all tests pass:
4 tests run in 00:00:00.0105346 for myFunc – 4 passed, 0 ignored, 0
failed, 0 errored. Success!
At this point you checked only 4 simple and obvious cases with zero or one element each. Many times functions fail when fed more complex data. The problem is how many more test cases can you add? The possibilities are literally infinite!
FsCheck
This is where FsCheck can help you. With FsCheck you can check for properties (or rules) that should always be true. It takes a little bit of creativity to think of good ones to test for and granted, sometimes it is not easy.
In your case we can test for concatenation. The rule would be like this:
If two lists are concatenated the result of MyFunc applied to the concatenation should be true if both lists are well formed and false if any of them is malformed.
You can express that as a function this way:
let myFuncConcatenation l1 l2 = myFunc (l1 # l2) = (myFunc l1 && myFunc l2)
l1 # l2 is the concatenation of both lists.
Now if you call FsCheck:
FsCheck.Verbose myFuncConcatenation
It tries a 100 different combinations trying to make it fail but in the end it gives you the Ok:
0:
["X"]
["^"; ""]
1:
["C"; ""; "M"]
[]
2:
[""; ""; ""]
[""; null; ""; ""]
3:
...
Ok, passed 100 tests.
This does not necessarily mean your function is correct, there still could be a failing combination that FsCheck did not try or it could be wrong in a different way. But it is a pretty good indication that it is correct in terms of the concatenation property.
Testing for the concatenation property with FsCheck actually allowed us to call myFunc 300 times with different values and prove that it did not crash or returned an unexpected value.
FsCheck does not replace case by case testing, it complements it:
Notice that if you had run FsCheck.Verbose myFuncConcatenation over the original function, which had a bug, it would still pass. The reason is the bug was independent of the concatenation property. This means that you should always have the case by case testing where you check the most important cases and you can complement that with FsCheck to test other situations.
Here are other properties you can check, these test the two false conditions independently:
let myFuncHasNulls l = if List.contains null l then myFunc l = false else true
let myFuncHasEmpty l = if List.contains "" l then myFunc l = false else true
Check.Quick myFuncHasNulls
Check.Quick myFuncHasEmpty
// Ok, passed 100 tests.
// Ok, passed 100 tests.
I'm working my way through the Data Science courses at DataCamp. (Not a plug.) One of the practice lessons has the following completed solution:
# logs is available in your workspace
extract_info <- function(x, property = "success", include_all = TRUE) {
info <- c()
for (log in x) {
if (include_all || !log$success) {
info <- c(info, log[[property]])
}
}
return(info)
}
# Call extract_info() on logs, no additional arguments
extract_info(logs)
# Call extract_info() on logs, set include_all to FALSE
extract_info(logs, include_all = FALSE)
The first call (extract_info(logs)) works as I would expect it to: it returns a vector containing all the log entries (regardless of the value of log$success).
The second call (extract_info(logs, include_all = FALSE)) does not return the results I would expect. It returns a vector containing only those results where log$success evaluates to FALSE.
It seems to me that the use of the || operator should cause the if block to short-circuit, and the second call should return nothing. From what I can tell, R evaluates expressions from left to right; but this looks like it's evaluating from right to left.
Can someone explain what's going on here?
(According to the site, this is the correct solution, and there's nothing wrong with the code. I want to know why it works the way it does. Even if the answer is that I'm overlooking something painfully obvious and stupid.)
Well || is the "or" operator. You don't short circuit the "or" operator with a FALSE value; you basically ignore that parameter and just look at the next one because you are looking for any TRUE value.
Assume a is a boolean value. These should be equivalent (<==>).
# or
FALSE || a <==> a
TRUE || a <==> TRUE
# and
TRUE && a <==> a
FALSE && a <==> FALSE
It seems like this was a temporary confusion.
|| is OR and so if either condition evaluates to TRUE, the compound expression evaluates to TRUE. If include_all was TRUE, you could short-circuit the expression, but when include_all is FALSE, you must wait to see what the other part is.
I am currently learning sml but I have one question that I can not find an answer for. I have googled but still have not found anything.
This is my code:
fun diamond(n) =
if(n=1) then (
print("*")
) else (
print("*")
diamond(n-1)
)
diamond(5);
That does not work. I want the code to show as many * as number n is and I want to do that with recursion, but I don't understand how to do that.
I get an error when I try to run that code. This is the error:
Standard ML of New Jersey v110.78 [built: Thu Aug 20 19:23:18 2015]
[opening a4_p2.sml] a4_p2.sml:8.5-9.17 Error: operator is not a
function [tycon mismatch] operator: unit in expression:
(print "*") diamond /usr/local/bin/sml: Fatal error -- Uncaught exception Error with 0 raised at
../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
Thank you
You can do side effects in ML by using ';'
It will evaluate whatever is before the ';' and discard its result.
fun diamond(n) =
if(n=1)
then (print "*"; 1)
else (print "*"; diamond(n-1));
diamond(5);
The reason for the error is because ML is a strongly typed language that although you don't need to specify types explicitly, it will infer them based on environmental factors at compile time. For this reason, every evaluation of functions, statements like if else need to evaluate to an unambiguous singular type.
If you were allowed to do the following:
if(n=1)
then 1
else print "*";
then the compiler will get a different typing for the then and else branch respectively.
For the then branch the type would be int -> int whereas the type for the else branch would be int -> unit
Such a dichotomy is not allowed under a strongly typed language.
As you need to evaluate to a singular type, you will understand that ML does not support the execution of a block of instructions as we commonly see in other paradigms which transposed to ML naively would render something like this:
....
if(n=1)
then (print "1"
print "2"
)
else (print "3"
diamond(n-1)
)
...
because what type would the then branch evaluate to? int -> unit? Then what about the other print statement? A statement has to return a singular result(even it be a compound) so that would not make sense. What about int -> unit * unit? No problem with that except that syntactically speaking, you failed to communicate a tuple to the compiler.
For this reason, the following WOULD work:
fun diamond(n) =
if(n=1)
then (print "a", 1) /* A tuple of the type unit * int */
else diamond(n-1);
diamond(5);
As in this case you have a function of type int -> unit * int.
So in order to satisfy the requirement of the paradigm of strongly typed functional programming where we strive for building mechanisms that evaluate to one result-type, we thus need to communicate to the compiler that certain statements are to be executed as instructions and are not to be incorporated under the typing of the function under consideration.
For this reason, you use ';' to communicate to the compiler to simply evaluate that statement and discard its result from being incorporated under the type evaluation of the function.
As far as your actual objective is concerned, following is a better way of writing the function, diamond as type int -> string:
fun diamond(n) =
if(n=1)
then "*"
else "*" ^ diamond(n-1);
print( diamond(5) );
The above way is more for debugging purposes.
A theoretical question here about the base or halting case in a recursive method, what's its standards?
I mean, is it normal not to have body in it, just a return statement?
Is it always like the following:
if (input operation value)
return sth;
Do you have different thoughts about it?
The pattern for recursive functions is that they look something like this:
f( value )
if ( test value )
return value
else
return f( simplify value )
I don't think you can say much more than that about general cases.
The base case is to terminate the loop (avoid becoming an infinite recursion). There's no standard in the base case, any input that is simple enough to be solved exactly can be chosen as one.
For example, this is perfectly valid:
int factorial (int n) {
if (n <= 5) {
// Not just a return statement
int x = 1;
while (n > 0) {
x *= n;
-- n;
}
return x;
} else {
return n * factorial(n-1);
}
}
In some cases, your base case is
return literal
In some cases, your base case is not simply "return a literal".
There cannot be a "standard" -- it depends on your function.
The "Syracuse Function" http://en.wikipedia.org/wiki/Collatz_conjecture for example,
doesn't have a trivial base case or a trivial literal value.
"Do you have different thoughts about it??" Isn't really a sensible question.
The recursion has to terminate, that's all. A trivial tail recursion may have a "base case" that returns a literal, or it may be a calculation. A more complex recursion may not have a trivial "base case".
It depends entirely on the particular recursive function. In general, it can't be an empty return; statement, though - for any recursive function that returns a value, the base case should also return a value of that type, since func(base) is also a perfectly valid call. For example, a recursive factorial function would return a 1 as the base value.