Forward reference extends over definition of variable in scala - scala

I have a list. For all the numbers in odd position I want to make it 0. And for all the numbers in even position, I want to keep it as it is.I'm trying to do it via map in the following way.
Here's my code
def main(args: Array[String]) {
var l1 = List (1,2,3,4,5,6)
println(l1.map(f(_)))
var c = 0
def f(n:Int):Int =
{
if (c%2 == 0)
{c +=1
return n}
else
{c += 1
return 0}
I want the variable to keep track of the position. But as it seems,I can't forward reference 'c'.
I get the following error
scala forward reference extends over definition of variable c
I can't also declare 'c' inside the function, because it will never increment that way.
What should be the idea way to achieve what I am trying, with the help of map.

I have a list. For all the numbers in odd position I want to make it
0. And for all the numbers in even position, I want to keep it as it is.
Here's an elegant solution of this problem:
l1.zipWithIndex map { case (v, i) => if (i % 2 == 0) v else 0 }
As for the reason, why your code fails: you're trying to access variable c before its declaration in code. Here:
println(l1.map(f(_)))
var c = 0
Your function f is trying to access variable c, which is not declared yet. Reorder these two lines and it will work. But I'd recommend to stick with my initial approach.

Related

Swift Programming Beginner : Why is there an error in my loop when implementing a Variable?

When I try and run my code in Xcode playground I get a warning:
Variable 'n' was never mutated; consider changing to 'let' constant.
First of all, I am changing the variable in the body of the loop so why is it telling me to change it to a let (constant) data type.
func multiples (n : Int) {
var n = 1
for _ in (3 ..< 1000) {
var n = n + 1
let multiple3 = 3 * n
print(multiple3)
}
}
I am changing the variable in the body of the loop
No, you’re not. The one in the body of the loop is a different n.
To fix that, change
var n = n + 1
To
n = n + 1
3 little notes:
a) If you read carefully messages from Xcode, you will understand about vars' lifetime and usage. ("Variable 'n' was never mutated; consider changing to 'let' constant" )
b) you have two var with same name in different scope
c) the you enter "for", n on the left will be computed using N in outer scope, so inner n will always be == 2
d) using debugger You will see as in picture.
Those are two different variables named n. One is unchanged and one is created for each new iteration of the for loop.
The reason you can have two variables with the same name is that they exist in different scopes and the one inside the for loop temporarily overrides the one outside the loop for the duration of the loop but only inside it.

ObservableBuffer giving IndexOutOfBounds in Scala

I am mesmerized. The below code is giving me an indexoutofbound error. But if I were to delete the slashes enabling for(j <- i until tmpArray.length) it would work. I really do not understand why it is happening, and would appreciate an explanation.
for(i <- 0 until tmpArray.length)
{
// for(j <- i until tmpArray.length)
// {
if( date.getValue != null && tmpArray(i).date != date.getValue )
{
tmpArray.remove(i)
}
// }
}
You're modifying the array as you "iterate" over it.
You are actually iterating over the range 0 until tmpArray.length, which is calculated up front. At some point, you reduce the length of the array (or, I assume so, as I can't find remove on the Array class). But it's still going to continue the iteration up to whatever the last index was when you created the range.
When you uncomment the inner for block, you're making it recompute the range for each step of the outer for. And it just so happens that the j range will simply have nothing in it if i >= tmpArray.length. So it inadvertently guards against that failure.
This is very C-style (imperative) code. It looks like all you're trying to do is remove some items from an array. That's what filter is for.
val result = tmpArray.filter { d =>
if(date.getValue != null && d != date.getValue) false else true
}
This creates a new array (result) by passing an anonymous function to tmpArray.filter. It will pass each item in the array to your "predicate", and if it returns true, it'll keep that item in result, otherwise it will omit it.
You should note that I avoided saying "loop". Scala's for isn't for making loops. It's actually syntax sugar for calling methods like foreach and map. Google "scala for comprehensions" for more detail.
If you insist on creating a C-style loop using indexes and a loop variable, you'll want to use while, so that you can check if i < tmpArray.length each time.

Scala: accessing shadowed parameter/variable

I have the following code, and 2 situations
Inside the
if in the method hideVariableFromOuterBlock I am declaring a
variable k which shadows the one defined in the outer
block.
inside the second method hideParameterName I am declaring a variable k which shadows the parameter with the same name.
object Test extends App {
def hideVariableFromOuterBlock() = {
var k = 2457
if (k % 2 != 0) {
var k = 47
println(k) // this prints 47
//println(outer k)
}
println(k) // - this prints 2457 as expected
}
def hideParameterName(k: Int) = {
var k = 47
println(k) // this prints 47
//println(parameter k)
}
hideVariableFromOuterBlock()
hideParameterName(2457)
}
Is there any way in the blocks where I have shadowed the variable or parameter k to access the shadowed value (the variable from the outer block)?
I am aware that this is not a good practice, and I will never do that. I am asking the question for educational purposes.
I did a bit of research and failed to find a clear explanation. I could clearly find/see that shadowing occurs, but found no clear explanation that the variable from the outer block can't be accessed anymore.
I am newbie in Scala.
This answer talks about why shadowing is allowed in the first place.
As for a way to access the shadowed value, the simplest thing to do as far as I know is to rename the inner variable and the problem goes away. I suppose, for the sake of the exercise, if you really don't want to rename anything, you could assign the outer variable to a new one with a different name.
var k = 2457
val outer_k = k
if (k % 2 != 0) {
var k = 47
println(k) // this prints 47
println(outer_k)
}

Assigning last array element to a variable in Swift

I have this very simple line of code
var dblArray : [Double] = [0.01]
var x = dblArray.last
println(x * x)
The '.last' module returns the last element of the array, which is 0.01. However, based on the playground assistant view, it shows that the actual assignment to var x is (Some 0.01). And doing a println will lead to "Optional 0.01"
What I'm hoping to accomplish is merely capturing the value of the last element and placing it in x.
What am I doing wrong here?
I'm pretty certain .last would have to be an optional, if only to handle the edge case of an empty array, where .last would make no sense as a "solid" value.
In any case, if you're sure the array won't be empty, just unwrap the value. If you're not sure then you'll need to check intelligently such as with:
var x = 0
if let junk = dblArray.last {
x = junk
}
I think that's the correct syntax, I don't have my Mac with me at the moment, but it should hopefully be close enough to show the concept.

scala assignment of value vs. reference types

I thought I had a firm grasp of Scala's treatment of reference types (i.e., those derived from AnyRef), but now I am not so sure.
If I create a simple class like this
class C(var x: Int = 0) {}
and define a few instances
var a = new C
var b = new C(1)
var c = new C(2)
and then I assign
a = b
I do not get a (shallow) copy, but rather the original reference to the instance to a is lost forever, and a and b are essentially "aliases" for the same object. (This can be seen by looking at the addresses of these items.) This is fine and sensible. It is also clear that these are references (as opposed to values), since I can do
c = null
and this does not generate an error.
Now, suppose I do this
import scala.math.BigInt
var x = BigInt("12345678987654321")
var y = BigInt("98765432123456789")
var z = x + y
This creates three BigInts, with x, y and z, as, I suppose, references to these. In fact, I can do
z = null
and again get no error. However,
y = x
x += 1
does not cause y to change, i.e., it appears that in this case assignment did not simply create another "name" for the object referred to by x, but made a copy of it.
Why does this happen? I cannot find any mechanism (e.g., akin to the "copy constructor" of C++) that would be silently invoked by (what appears to be) straightforward reference assignment.
Any explanation would be greatly appreciated, as two days of web search has proved fruitless.
x += 1 will be expanded into x = x + 1 so it's not only assignment.
If you will look at the source of bigInt you'll see that + creates new instance:
def + (that: BigInt): BigInt = new BigInt(this.bigInteger.add(that.bigInteger))
in fact it uses java's BigInteger underneath whose add operations leaves both arguments untouched.
So what basically happens at the end of the day is reference reassignment of result of copy constructor of immutable addition
y = x
x += 1
BigInt is immutable so +1 creates new BigInt that's why y does not change. y still points to previous object while x points to new BigInt object.
I suppose its related to the immutability of BigInt and similar classes, you always get a new immutable object.