I have the following bit of code in scala which is not working:
var tacTable : List[List[TACList]] = List(List())
def gen(p: Program) = {
for (i <- 0 to p.classes.length){
for (j <- 0 to p.classes(i).methods.length){
var tacInstr = new TACList()
tacTable(i)(j) = tacInstr //error: application does not take parameters
}
}
}
Apparently, it has to do with the fact that I'm using j to access the list and j is used in for...how can I solve this?
For convenience you can work with this other example which gives the same error:
var l : List[List[Int]] = List(List(1,2),List(3,4))
for (i <- 0 to l.length) {
for (j <- 0 to l.length) {
l(i)(j) = 8
}
}
Lists are immutable.
Try this instead:
val tacTable = p.classes.map { _.methods.map { _ =>
new TACList()
}
since I cannot comment on the initial post a sidenote here:
in a scala for-comprehension you can use multiple generators in a single for. so the nesting that you used is not necessary since you can use this:
for (i <- 0 to l.length; j <- 0 to l.length) {
// your code
}
furthermore, this does not seem to apply in your case but if you had a flat mapped result you should use the yield of the for comprehension instead of a mutation in the body
Related
I am having a mutableList and want to take sum of all of its rows and replacing its rows with some other values based on some criteria. Code below is working fine for me but i want to ask is there any way to get rid of nested for loops as for loops slows down the performance. I want to use scala higher order methods instead of nested for loop. I tried flodLeft() higher order method to replace single for loop but can not implement to replace nested for loop
def func(nVect : Int , nDim : Int) : Unit = {
var Vector = MutableList.fill(nVect,nDimn)(math.random)
var V1Res =0.0
var V2Res =0.0
var V3Res =0.0
for(i<- 0 to nVect -1) {
for (j <- i +1 to nVect -1) {
var resultant = Vector(i).zip(Vector(j)).map{case (x,y) => x + y}
V1Res = choice(Vector(i))
V2Res = choice(Vector(j))
V3Res = choice(resultant)
if(V3Res > V1Res){
Vector(i) = res
}
if(V3Res > V2Res){
Vector(j) = res
}
}
}
}
There are no "for loops" in this code; the for statements are already converted to foreach calls by the compiler, so it is already using higher-order methods. These foreach calls could be written out explicitly, but it would make no difference to the performance.
Making the code compile and then cleaning it up gives this:
def func(nVect: Int, nDim: Int): Unit = {
val vector = Array.fill(nVect, nDim)(math.random)
for {
i <- 0 until nVect
j <- i + 1 until nVect
} {
val res = vector(i).zip(vector(j)).map { case (x, y) => x + y }
val v1Res = choice(vector(i))
val v2Res = choice(vector(j))
val v3Res = choice(res)
if (v3Res > v1Res) {
vector(i) = res
}
if (v3Res > v2Res) {
vector(j) = res
}
}
}
Note that using a single for does not make any difference to the result, it just looks better!
At this point it gets difficult to make further improvements. The only parallelism possible is with the inner map call, but vectorising this is almost certainly a better option. If choice is expensive then the results could be cached, but this cache needs to be updated when vector is updated.
If the choice could be done in a second pass after all the cross-sums have been calculated then it would be much more parallelisable, but clearly that would also change the results.
Recently, I've started learning Scala for school project. The assignment says that we have to delete elements of an unsorted array, without leaving "holes" in the array. I've made the following code:
private var _list = new Array[NAW](20)
private var _highestIndex = 0;
def removeAllbyName(name : String): Unit = {
for(i <- 0 until _highestIndex){
if(_list(i).name == name)
deleteByIndex(i)
}
}
def deleteByIndex(i : Int) : Unit = {
if(i != -1){
for(x <- i until _highestIndex){
_list(x) = _list(x + 1)
}
_highestIndex -= 1
}
}
I filled the array with 10 instances, the highestIndex will be 10 and after the first removal 9. But the for-loop still keeps counting to 9, which results in a null-pointer exception, even though we use "until". The debugger does recognise that _highestIndex is 9. Can somebody please explain why this is happening?
Thanks in advance!
0 until _highestIndex only gets evaluated once.
for (i <- 0 until _highestIndex) {
if (_list(i).name == name)
deleteByIndex(i)
}
Is equivalent to:
val range = 0 until _highestIndex
for (i <- range) {
if (_list(i).name == name)
deleteByIndex(i)
}
You can see that the range is determined only once.
You could try using a while loop instead, or a guard in your if statement.
Change your for-loop inside deleteByIndex like this to avoid exception
for(
x <- i until highestIndex
if (x + 1) < highestIndex
)
list(x) = list(x + 1)
when I work on some task using scala , I wrote some code as follows:
object He {
def main(args: Array[String]): Unit = {
var myMatrix = Array.ofDim[String](3,3)
// build a matrix
for (i <- 0 to 1) {
for ( j <- 0 to 1) {
myMatrix(i)(j) = "faf";
}
}
var eventbuffer = for(i <- myMatrix) yield for(j <- i) yield j
var eventArray = for(i <- eventbuffer) yield i.toArray
var eventpool:Array[(String, Array[String])] = eventArray.toArray.map(son => (son(0), son))
}
}
I want to ask the question ,what's the differece between the eventbuffer and eventArray?Last,what will the eventpool be like? I am really confused,Thank for
helping me for that
In Scala an Array is just a JVM Array, while the various Buffers are actual classes.
An Array[String] ist the same as a String[] in Java.
You can think of an ArrayBuffer as an ArrayList in Java (they're very similar, but not equivalent) and of the ListBuffer as a Java LinkedList (again, similar, but not the same).
One should note however, that in your example eventbuffer is not a Buffer, but an Array of Arrays. In fact it is pretty much an exact copy of myMatrix, so the call to the toArray method is actually redundant.
I was working with Project Euler Problem 4 (finding the largest palindrome formed from the product of two three-digit numbers), and produced the solution euler4_1, which uses a variable cand. The function runs as expected, iterating through all pairs (i, j) and only replacing cand with a bigger palindrome.
def euler4_1(): Int = {
var cand=0
for(i <- 100 until 999){
for(j <- 100 until i){
if (((i*j).toString.reverse == (i*j).toString)&&(i*j>cand)){
cand=i*j
println(cand)
}
}
}
return cand
}
/**
...
666666
678876
696696
749947
819918
824428
828828
861168
888888
906609
*/
However, initializing cand as a var instead of a val seems to mess things up - a number of palindromes which are smaller than the current best are also printed out.
def euler4_2(): Int = {
val cand=0
for(i <- 100 until 999){
for(j <- 100 until i){
if (((i*j).toString.reverse == (i*j).toString)&&(i*j>cand)){
val cand=i*j
println(cand)
}
}
}
return cand
}
/**
...
601106
650056
853358
141141
282282
119911
906609
514415
580085
*/
What's happening in the second code sample, labelled euler4_2?
[Comments on how to make the code more idiomatic in scala are also appreciated].
As n.m. pointed out in the comments, the problem is that you have two different val's named cand. If you want to write this in functional style, without any var's, use foldLeft and pass cand through each iteration:
(100 until 999).foldLeft(0) { (cand, i) =>
(100 until i).foldLeft(cand) { (cand, j) =>
val product = i * j
val productS = product.toString
if (productS.reverse == productS && product > cand) {
println(product)
product
} else cand
}
}
scala> (for (i <- 100 until 999 ;
| j <- 100 until i;
| ij = i * j;
| ijs = ij.toString if ijs == ijs.reverse
| ) yield ij
| ).max
res0: Int = 906609
would be the most obvious (to me) idiomatic functional-style implementation using comprehensions. Not sure about efficiency though.
I would like to change all values in a multidimensional array but I'm receiving the "reassignment to val" error.
Scala code:
var cal = Array.ofDim[Double](300, 10000000);
cal.foreach(x => {
x.foreach({o => o = 5.1} //here it'll be more complicated code
)});
Does any body knows how to reassign the values in Array ?
Thanks
There is in-place modification bulk operation is transform on mutable sequences.
for (y <- 0 until cal.length) {
cal(y).transform(x => 5.1)
}
You can also do:
for (y <- 0 until cal.length) {
val row = cal(y)
for (x <- 0 until row.length) {
row(x) = 5.1
}
}
I am not sure whether this is the best way but it works:
val cal = Array.ofDim[Double](300, 10000000)
(0 until cal.length).foreach(rowIndex => {
val row = cal(rowIndex)
(0 until row.length).foreach(colIndex => {
row(colIndex) = 5.1 //here it'll be more complicated code
})
})
The reason for the error you got is that you are trying to assign a value to the immutable function parameter o in o => o = 5.1.
Since your using var you can simply
var cal = Array.ofDim[Double](300, 10000000);
cal = cal.map{
a=>a.map{
o=> 1.5 \\complex calculations
}
}
NB: This is not idiomatic scala or even functional, but it works.