Shortcut for null operator check and assignment in coffeescript - coffeescript

What is the shortcut for the following in coffeescript
if x then x += 1 else x = 0

since x += 1 if x would leave x as whatever falsey value it was (which could be null or undefined or false), if you want to set x to 0, you'll need to be more specific.
in coffeescript, an if/else statement is an expression, so you can just assign it that way:
x = if x then x + 1 else 0
This is the equivalent of the javascript ternary expression:
x = x ? x + 1 : 0

When I read the title of your question, I thought you may be looking for x ?= 1, which compiles to x != null ? x : x = 1;. But this is not what you want.

Related

Nested pattern matching in Scala

I'm new to Scala and I'm trying to understand how pattern matching works. So I wrote this basic code, which returned the expected result:
def test(choice: Int): String = choice match {
case x if x > 0 && x%2 == 0 => "positive even number"
case x if x > 0 && x%2 != 0 => "positive odd number"
case 0 => "null"
case x if x < 0 && x%2 == 0 => "negative even number"
case x if x < 0 && x%2 != 0 => "negative odd number"
}
Now I'm trying to do something a little more elaborate:
def test(choice: Int): String = choice match {
case x if x%2 == 0 => x match {
case y if y > 0 => "even and positive number"
case y if y < 0 => "even and negative number"
}
case 0 => "null"
case x if x%2 != 0 => x match {
case y if y > 0 => "odd and positive number"
case y if y < 0 => "odd and negative number"
}
}
But it failed. Here's the error message on the console:
scala> def test(choice: Int): String = choice match {
|
| case x if x%2 == 0 => x match {
| case y if y > 0 => "even and positive number"
| Display all 600 possibilities? (y or n)
[...]
| if y < 0 => "even and negative number"
<console>:5: error: '(' expected but identifier found.
if y < 0 => "even and negative number"
^
[...]
Can somebody tell me what I'm doing wrong and give me some details about what I misunderstand about Scala in general and the match method in particular.
It compiles for me. The order of cases doesn't matter for the success of compilation (however, the case 0 branch will never match, because case x if x%2==0 matches x=0. You may want to make the case 0 branch the first one)
I believe your problem is because of using tabs instead of spaces in the terminal.
If you use this code in a file in a project, it'll compile just as well. If you want it to work in the console, you can either:
convert the tabs to spaces before pasting the code
enter paste mode in the REPL using the :paste command, paste the code and exit paste mode with Ctrl-D (or whatever the REPL tells you the combination is - that's the one on Mac).
In your first code, you test for x>0 in the first 2 cases, then for 0 itself.
In the second code, you don't test for x>0, but x%2 == 0 which already matches for x = 0, and a second, outer match isn't considered.
If you put the explicit 0 match on top, it might work, but I didn't look for a second error and only matched for the first error I could find. :)

Adding elements to a list in a for loop

var locations: List[Location] = List[Location]()
for (x <- 0 to 10; y <- 0 to 10) {
println("x: " + x + " y: " + y)
locations ::: List(Location(x, y))
println(locations)
}
The code above is supposed to concatenate some lists. But the result is an empty list. Why?
Your mistake is on the line locations ::: List(Location(x, y)). This is concatenating the lists, but the doing nothing with the result. If you replace it with locations = locations ::: List(Location(x, y)) you would have your desired result.
However there are more idiomatic ways to solve this problem in Scala. In Scala, writing immutable code is the preferred style (i.e. use val rather than var where possible).
Here's a couple of ways to do it:
Using yield:
val location = for (x <- 0 to 10; y <- 0 to 10) yield Location(x, y)
Using tabulate:
val location = List.tabulate(11, 11) { case (x, y) => Location(x, y) }
Even shorter:
val location = List.tabulate(11, 11)(Location)
Edit: just noticed you had 0 to 10 which is inclusive-inclusive. 0 until 10 is inclusive-exclusive. I've changed the args to tabulate to 11.

Calculating the sum of integers from x to y with a while loop

I'm trying to write a code in Scala to calculate the sum of elements from x to y using a while loop.
I initialize x and y to for instance :
val x = 1
val y = 10
then I write a while loop to increment x :
while (x<y) x = x + 1
But println(x) gives the result 10 so I'm assuming the code basically does 1 + 1 + ... + 1 10 times, but that's not what I want.
One option would be to find the sum via a range, converted to a list:
val x = 1
val y = 10
val sum = (x to y).toList.sum
println("sum = " + sum)
Output:
sum = 55
Demo here:
Rextester
Here's how you would do it using a (yak!) while loop with vars:
var x = 1 // Note that is a "var" not a "val"
val y = 10
var sum = 0 // Must be a "var"
while(x <= y) { // Note less than or equal to
sum += x
x += 1
}
println(s"Sum is $sum") // Sum = 55 (= 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10)
Here's another, more functional, approach using a recursive function. Note the complete lack of var types.
val y = 10
#scala.annotation.tailrec // Signifies add must be tail recursive
def add(x: Int, sum: Int): Int = {
// If x exceeds y, then return the current sum value.
if(x > y) sum
// Otherwise, perform another iteration adding 1 to x and x to sum.
else add(x + 1, sum + x)
}
// Start things off and get the result (55).
val result = add(1, 0)
println(s"Sum is $result") // Sum is 55
Here's a common functional approach that can be used with collections. Firstly, (x to y) becomes a Range of values between 1 and 10 inclusive. We then use the foldLeft higher-order function to sum the members:
val x = 1
val y = 10
val result = (x to y).foldLeft(0)(_ + _)
println(s"Sum is $result") // Sum is 55
The (0) is the initial sum value, and the (_ + _) adds the current sum to the current value. (This is Scala shorthand for ((sum: Int, i: Int) => sum + i)).
Finally, here's a simplified version of the elegant functional version that #TimBiegeleisen posted above. However, since a Range already implements a .sum member, there is no need to convert to a List first:
val x = 1
val y = 10
val result = (x to y).sum
println(s"Sum is $result") // Sum is 55
(sum can be thought of as being equivalent to the foldLeft example above, and is typically implemented in similar fashion.)
BTW, if you just want to sum values from 1 to 10, the following code does this very succinctly:
(1 to 10).sum
Although you can use Scala to write imperative code (which uses vars, while loops, etc. and which inherently leads to shared mutable state), I strongly recommend that you consider functional alternatives. Functional programming avoids the side-effects and complexities of shared mutable state and often results in simpler, more elegant code. Note that all but the first examples are all functional.
var x = 1
var y = 10
var temp = 0
while (x < y) {
temp = temp+x
x = x + 1
}
println(temp)
This gives required result

scala foreach of a 2-D List/Array in chisel with types issue

Can "foreach" can be used for each element of the 2-D List/Array?
I tried the code:
val n_vec = (0 to 2).map(i=>
(0 to 2).map(j=>
Wire(UInt(3.W))
)
)
n_vec.foreach((i:Int)=>(
n_vec(i).foreach((j:Int)=>{
n_vec(i)(j) := i.U + j.U
})
))
the error message is
top.scala:24: error: type mismatch;
found : Int => Unit
required: chisel3.core.UInt => ?
n_vec(i).foreach((j:Int)=>{
^
Could you enlight me whether it can be used in such a way, even how?
It would be cleaner to write like this:
n_vec.foreach { i=>
i.foreach { j=>
j := x.U + y.U
y = y + 1
}
y = 0
x = x + 1
}
But you don't need to increment x and y manually, just iterate over indices instead:
n_vec.indices.foreach { x =>
n_vec(x).indices.foreach { y =>
n_vec(x)(y) := x.U + y.U
}
}
or better (and this translates exactly to the above)
for {
x <- n_vec.indices
y <- n_vec(x).indices
} {
n_vec(x)(y) := x.U + y.U
}
Yes it can be used this way.
solution:
var x = 0
var y = 0
n_vec.foreach(i=>{
i.foreach(j=>{
j := x.U + y.U
y = y + 1
})
y = 0
x = x + 1
})
x = 0
y = 0

Block statements in anonymous Scala function

I've created this simple anonymous function
var b = (x : Int) => if(x % 2 == 0) x + 1 else x
and it works great. After that I tried to add another statement after the if and before the x+1 statement.
var b = (x : Int) => if(x % 2 == 0) println(x) x + 1 else x
and a that point I received the following compiler error
Cannot resolve symbol x
Please can anyone let me know why this happen?
The reason this happens is that although Scala does not require the use of semi-colons most of the time (unlike Java), since the compiler is more equipped to infer where statements/expressions end, if you have 2 statements/expressions on 1 line then you need to separate them for the compiler.
Your first anonymous function works since if(x % 2 == 0) x + 1 else x is 1 expression.
The compiler is complaining with the second one though since if(x % 2 == 0) println(x) is considered 1 statement. Hence, the next statement starts and there is now no context for x.
Other posters have given you a solution to break the right-side of the function down into separate statements so I won't duplicate - just adding an explanation of why the compilation error occurs since you said you are learning the language. Google about the use of semi-colons in Scala to find out more.
Use this. You need the braces to indicate these are multiple lines:
var b = (x : Int) => if(x % 2 == 0) {
println(x)
x + 1
} else x
Or you can do this.. you need to put that semi colon to indicate to compiler they are separate statements:
var b = (x : Int) => if(x % 2 == 0) { println(x); x + 1 } else x