The following Statement causes a compiler error:Type '()' does not conform to protocol 'LogicValue'. In the second line
var b=1
if b!=0
{
println("not 0")
}
But
var b=1
if (!(b==0))
{
println("not 0")
causes no compiler error.
For what reason 0 can't be compared using the != Operator, but can be compared using the == Operator ?What is the best way to deal with this?
This is probably due to the lack of whitespace around your != operator - Swift is quite fussy about whitespace, and interprets operators differently depending on their surrounding whitespace.
The language specification describes the various rules, although it is not particularly obvious from these that b!=0 should be invalid.
So you probably need to say b != 0 rather than b!=0
See also: Is this response from the compiler valid?
What's wrong with a nice and simple b != 0? It's easy to read and easy to implement.
The reason why the second option works is because the ! here means "not". So if b equalled 0, the statement would be "not True", or "False".
It's a case of missing whitespace:
var b=1
if b != 0 {
println("not 0")
}
compiles fine.
Related
I am trying to understand why my code doesn't work! I am trying to solve the classic balance parentheses problem and Im getting a no such element on my third if statement which doesn't make sense to me because I thought my second if statement would avoid that case but I dont think my second if statement is returning?
def balance(chars: List[Char]): Boolean = {
def check(left: Int,right: List[Char]): Boolean = {
if (left < 0) false
if (right.isEmpty) left == 0
if (right.head == ')') check(left + 1, right.tail)
else check(left - 1, right.tail)
}
check(0,chars.filter(x => (x == ')') || (x == '(')))
}
Following up on my comment. I don't believe that you are actually getting a Null Pointer exception. Scala doesn't encourage the use of nulls and I don't know of any case where the standard library will return a null. Nulls are encapsulated by Option.None in Scala (or see upcoming explicit nulls in Scala 3) and even when you are integrating with a Java library, it is recommended that you wrap the null behavior in an option.
That being said, under the assumption that you are getting a No Such Element Exception in reality, let's look at you code.
Understanding the return behavior in Scala
A Scala function will take the last value in it's body as it's return value. In your case it is this block
if (right.head == ')') check(left + 1, right.tail)
else check(left - 1, right.tail)
Since the previous if blocks are not conditionally linked together all 3 of them will be evaluated. Even if one of the first two evaluates the true, Scala will NOT return and continue to evaluate because it sees more code in the function body it has not computed yet.
So in this case even if the second condition is true, the third one still gets evaluated.
Use the full ternary syntax and add else
if (left < 0) false else
if (right.isEmpty) left == 0 else
if (right.head == ')') check(left + 1, right.tail)
else check(left - 1, right.tail)
More on ternary syntax here
Let us desugar check definition a little bit:
def check(...) =
{
if (left < 0) false else (); // expression 1
if (right.isEmpty) left == 0 else (); // expression 2
return if (right.head == ')') check(...) else check(...); // expression 3 (last expression)
}
Note how the semicolons ; make it clear we have three separate expressions in the expression block, and only the last one is passed to return. Now the two key concepts to understand are
conditional expressions if (𝑒1) 𝑒2 else 𝑒3 are first-class values (and not control statements)
the "returned" value of the whole block expression is only the value of the last expression in the block
Hence to fix the issue, as suggested by others, we need to connect the three separate expressions into a single expression of the form if...else if ... else if ... else.
I've been told to avoid use of return in Scala, although I'm not sure why.
I've got the following code, and it doesn't seem to return the proper thing unless I put the return keyword in there. Why do I need to put return?
def nextParen(chars: List[Char]): List[Char] =
for(i <- 0 to chars.size - 1) {
if(chars(i) == '(' || chars(i) == ')') {
return chars.slice(i, chars.size) // return HERE!
}
}
List.empty
}
The argument for avoiding return is that it leads to code that is less readable, and not refactor-safe. It's not an absolute rule, if you find an algorithm that's best expressed that way, but usually code can be made clearer by writing it as an expression.
This particular code looks to be equivalent to:
def nextParen(chars: List[Char]) =
chars.dropWhile{c => c != '(' && c != ')'}
In general, try to focus on writing expressions rather than procedures; rather than telling the compiler what steps it should take, tell it what the value is. Even if you didn't know about dropWhile, you could write the loop as a fold (e.g. foldLeft) that says what to do at each element of the list, and then the case where the list is empty at the end would fall out naturally, rather than needing two different branches for where there is a match and where there isn't.
There's nothing wrong with using return when it clearly expresses your intent in a good algorithm. However, you should be cautious about using it because it isn't necessary, and most things you want to do already have decent implementations in the collections library.
So, for example, your code works but is O(n^2) in the size of the list because you're indexing into a linear data structure. It's much better to use
chars.dropWhile(c => c != '(' && c != ')')
or if you don't know about that, any of a huge number of alternatives:
val i = chars.indexWhere(c => c == '(' || c == ')')
if (i < 0) chars take 0 else chars drop i
var found = false
chars.filter(c => found || { found = (c == '(' || c == ')'); found })
You can probably come up with half a dozen more without trying too hard. (Fold with an indicator, for/yield with an if clause, span, etc.)
So the best reason to not use return is that you should know your library. Usually you don't need it; it's better to use a stock method that computes what you want.
You are using a for in the imperative sense above. You don't have to use a return if you use it in a more functional sense i.e., as a for-yield or fold or takeWhile.
I think one of the biggest thing to wrap your head around when you move from imperative to functional (side-effect free) is the notion that you can express your code a sequence of expressions, each of which evaluates to a value. For example, a for-yield expression evaluates to a value. So in an imperative world you are executing a sequence of statements that is changing the state (data structures, console etc) around you.
PS: I've used a lot of terms (e.g., side-effect, for-yield, value) that may sound unfamiliar to a new Scala programmer. But with more experience they will make more sense. I would highly recommend this book - Structure and Interpretation of Computer Programs
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Return in Scala
I have just started using Scala and have come across some behavior that I don't really understand, and I'm hoping the stackoverflow community can shed some light.
Using this test:
example(1,List(1))
This code works as I would expect - 0 is returned on the second iteration:
def example(value: Int, list: List[Int]): Int = {
if (list.isEmpty)
return 0
else
return 1
example(value - list.head, list.tail) + example(value, list.tail);
}
However, this code does not - it throws a NoSuchElementException("head of empty list") on the second iteration:
def example(value: Int, list: List[Int]): Int = {
if (list.isEmpty)
0
else
1
example(value - list.head, list.tail) + example(value, list.tail);
}
The difference appears to be that in the second example, Scala is assuming "0" and "1" are not return values but expressions to be evaluated because there is another expression at the end of the function. It makes sense that the first example would return as expected due to the explicit "return" keyword.
However, given the syntax of the if statement in second example, I would think the compiler would realize that "0" is not an expression to be evaluated, but rather a return value. Why is this not the case?
You should read the answer here for information about implicit returning since that part of your question is an exact duplicate.
But I'll answer specifically your point about "I would think the compiler would realize that "0" is not an expression to be evaluated, but rather a return value", since it's an interesting observation.
The simple answer is that 0 is an expression... it just happens to be the case that its evaluation is pretty simple. Scala doesn't make a distinction between "expressions that require effort" and "expressions that are easy" when it decides how to process your code. It just processes it the way it's told.
More importantly, if the Scala compiler did get into the business of guessing your intent, that would get pretty crazy, and would make coding a lot more challenging!
To see why we do not want this, let's look at your code that you posted:
def example(value: Int, list: List[Int]): Int = {
if (list.isEmpty)
0
else
1
example(value - list.head, list.tail) + example(value, list.tail);
}
As you mentioned, the 0 and 1 bits aren't really doing anything. So maybe this hypothetical compiler would say "Hey! The only interesting thing I can do with these is to return them!" and thus makes them return. We'll now we've got an if/else in which both sides return. In other words, if list is empty, we return, and if it's not empty, we return. So we always return, and the function ends.
But wait!! There's another line after the if/else expression! So our hypothetical compiler says "Hey! If I return here, then I won't ever execute that line! And that line looks pretty important. Maybe I shouldn't return, so that I can execute it." But then it realizes "Oh no! If i don't return the 0 or 1, then they are pointless! I have to return them!". "But that last line is still there!". "Ahhhhhhh!!!!1!!".
So maybe it's better that the compiler doesn't try to guess what we want and instead just does what we tell it.
I have hack I need to employ under these conditions:
It's the last page of data.
It's not the first page, either.
There's not a page-size-even number of data items.
So I tried this code:
my $use_hack =
$last_page_number == $current_page_number and
$page_number != 1 and
$total_items % $items_per_page != 0;
And I keep getting this warning Useless use of numeric ne (!=) in void context about the last condition and it's evaluating true when $total_items % $items_per_page = 0.
say 'NOT EVEN' if $total_items % $items_per_page != 0; #works properly, though...
I've tried various combinations of parentheses to get it right, but nothing seems to work.
Okay, operator precedence. and has almost the lowest precedence of any operator in Perl, so Perl was evaluating the expression in a weird order. Switching to && instead got me correct results. Blarg.
The More You Know.
EDIT:
As Philip Potter pointed out below, Perl Best Practices (p.70) recommends always using &&,||, ! for boolean conditions - limiting and or and not for control flow because of their low precedence. (And it even goes so far as to say to never use and and not, only or for fallback logic.)
Thanks, everybody!
Enclose the RHS in parenthesis:
my $use_hack = (
$last_page_number == $current_page_number and
$page_number != 1 and
$total_items % $items_per_page != 0);
Assignment (=) is having higher precedence when compared to and operator. You can take a look at the Perl Operator Precedence.
On compiling the following code with Scala 2.7.3,
package spoj
object Prime1 {
def main(args: Array[String]) {
def isPrime(n: Int) = (n != 1) && (2 to n/2 forall (n % _ != 0))
val read = new java.util.Scanner(System.in)
var nTests = read nextInt // [*]
while(nTests > 0) {
val (start, end) = (read nextInt, read nextInt)
start to end filter(isPrime(_)) foreach println
println
nTests -= 1
}
}
}
I get the following compile time error :
PRIME1.scala:8: error: illegal start of simple expression
while(nTests > 0) {
^
PRIME1.scala:14: error: block must end in result expression, not in definition
}
^
two errors found
When I add a semicolon at the end of the line commented as [*], the program compiles fine. Can anyone please explain why does Scala's semicolon inference fail to work on that particular line?
Is it because scala is assuming that you are using the syntax a foo b (equivalent to a.foo(b)) in your call to readInt. That is, it assumes that the while loop is the argument to readInt (recall that every expression has a type) and hence the last statement is a declaration:
var ntests = read nextInt x
wherex is your while block.
I must say that, as a point of preference, I've now returned to using the usual a.foo(b) syntax over a foo b unless specifically working with a DSL which was designed with that use in mind (like actors' a ! b). It makes things much clearer in general and you don't get bitten by weird stuff like this!
Additional comment to the answer by oxbow_lakes...
var ntests = read nextInt()
Should fix things for you as an alternative to the semicolon
To add a little more about the semicolon inference, Scala actually does this in two stages. First it infers a special token called nl by the language spec. The parser allows nl to be used as a statement separator, as well as semicolons. However, nl is also permitted in a few other places by the grammar. In particular, a single nl is allowed after infix operators when the first token on the next line can start an expression -- and while can start an expression, which is why it interprets it that way. Unfortunately, although while can start a expression, a while statement cannot be used in an infix expression, hence the error. Personally, it seems a rather quirky way for the parser to work, but there's quite plausibly a sane rationale behind it for all I know!
As yet another option to the others suggested, putting a blank newline between your [*] line and the while line will also fix the problem, because only a single nl is permitted after infix operators, so multiple nls forces a different interpretation by the parser.