I'm trying to assign a different value for each actor to the variable "file" in example class using its object in class A.
class A{
var a1=new Array[example](2)
def starting()= {
for(i <- 0 to 3){
if(i==0){
a1(i).file="L1.txt";
}
else if(i==1){
a1(i).file="L2.txt";
}
a1(i).start
}
}
}
class example extends Actor {
var file="default.txt"
var Handle = new A
def act()= {
loop{
var count=0
react{
//remaining code
}
}
}
This is throwing a nullpointerexception corresponding to the lines :
for(i <- 0 to 3){
if(i==0){
a1(i).file="L1.txt";
}
i'm a beginner in scala.. i somehow am unable to figure out the reason for this exception. Please help.
var a1=new Array[example](2) creates new Array with 2 nulls, so a1(i) is null.
Use var a1 = IndexedSeq.fill(2){ new example }
Off topic:
There is Code Review for such things, but your code is not scala way. Try to rewrite it.
For example:
scala> import actors.Actor._
import actors.Actor._
scala> val as = for ( fileName <- Seq("L1.txt", "L2.txt") )
| yield actor {
| var count = 0
| loop {
| receive {
| case t =>
| count += 1
| println(fileName + " " + count + " " + t)
| }
| }
| }
as: Seq[scala.actors.Actor] = List(scala.actors.Actor$$anon$1#ef82188, scala.actors.Actor$$anon$1#44616f65)
scala> as.foreach{ _ ! 's }
L2.txt 1 's
L1.txt 1 's
Apart from what #senia already diagnosed, you are allocating an array of 2 elements, then trying to iterate through 4 elements of it:
for(i <- 0 to 3){
which is surely going to produce an ArrayIndexOutOfBoundsException once i becomes 2. Loop condition should be for(i <- 0 to 1) or for(i <- 0 until 2) for this to work. Although there are indeed better, more Scala-ish ways to implement this.
probably the file "L1.txt" is not being located!
read this URL Read entire file in Scala?
Related
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)
I have this function that counts the number of adjacent repeated chars inside a String.
def adjacentCount( s: String ) : Int = {
var cont = 0
for (a <- s.sliding(2)) {
if (a(0) == a(1)) cont = cont + 1
}
cont
}
}
But I'm supposed to create a function that does exactly the same, but using only immutable variables or loop instructions, in a "purely" functional way.
You can just use the count method on the Iterator:
val s = "aabcddd"
s.sliding(2).count(p => p(0) == p(1))
// res1: Int = 3
I am at a beginner level in Scala, I am trying the following code:
var i: Int = 0
for (i <- 0 to 10) {
if (i == 2) {
i += 1
}
println(i)
}
When I increment i the compiler says Value += is not member of Int.
You're declaring i twice, one at the outer scope and one in the inner. Your for comprehension looks at the inner i, which is a val, not a var, thus shadowing the external declaration.
Bind to a different name:
var counter: Int = 0
for (i <- 0 to 10) {
if (i == 2) {
counter += 1
}
println(counter)
}
Note you can do this without declaring an outer variable at all, using count:
val count = (0 to 10).count(i => i == 2)
println(count)
Edit:
From your comments, I understand you want to print all numbers other than 2. For that you need to negate your condition:
if (i != 2) {
counter += 1
}
Or if you just want to filter out 2:
(0 to 10).filter(_ != 2).foreach(println)
Edit 2:
From you comments, it looks like a while loop is better for what you're trying to achieve:
var i = 0
while (i < fruits.length) {
if (fruits(i) == "Banana") {
i += 1
println(i + " " + fruits(i))
} else if (fruits(i) == "Orange") {
i += 1
println(i + " " + fruits(i))
}
}
But this code will run into an infinite loop since you're only incrementing i if the conditions are met. Other than that, since your doing i + 1, you might be going out of bounds if the last element equals "Banana" or "Orange", so you might want to rethink what you're doing. You'll probably run into an
As mentioned in Yuval's answer, you're declaring i twice. Not only that, but the inner one is implicitly immutable, therefore making it impossible for you to mutate it (that's why you get a compilation error).
To achieve the same effect you get from mutation you can use a guard in the for comprehension, like this:
for (i <- 0 to 10 if i != 2) {
println(i)
}
This code can be seamlessly translated (and that's what the compiler actually does) to the following
(0 to 10).withFilter(i => i != 2).foreach(i => println(i))
The new error mentioned in the comment looks like:
scala> :pa
// Entering paste mode (ctrl-D to finish)
var i: Int = 0
for(i <- 0 to 10)
{
if (i == 2)
{
i += 1
}
println(i)
}
// Exiting paste mode, now interpreting.
<pastie>:19: error: value += is not a member of Int
Expression does not convert to assignment because receiver is not assignable.
i += 1
^
It should say i instead of receiver for the simple case, where the LHS is not a complex expression, but you get the idea.
Also, nobody mentioned this:
scala> :pa
// Entering paste mode (ctrl-D to finish)
object X {
var i: Int = 0
for(i <- 0 to 10)
{
if (i == 2)
{
this.i += 1
}
println(this.i)
}}
// Exiting paste mode, now interpreting.
defined object X
scala> X
0
0
1
1
1
1
1
1
1
1
1
res3: X.type = X$#1129829c
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
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.