Is there a way to avoid using var in this scala snippet - scala

Below here the code snippet, where I want to avoid using the 'var'. Not sure if there is a good way to do that
var randomInt = Random.nextInt(100)
private def getRandomInt(createNew:Boolean):Int = {
if(createNew){
randomInt = Random.nextInt(100)
}
randomInt
}

Create an "infinite" Iterator of random numbers. Advance to the next() only when needed.
val randomInt = Iterator.continually(Random.nextInt(100)).buffered
private def getRandomInt(createNew:Boolean):Int = {
if (createNew) randomInt.next()
randomInt.head
}

The class below holds the current random value and provides a method to return an instance holding the next random value.
It only uses immutable values, although the Random.nextInt(...) function isn't pure, because it doesn't return the same result for the same input.
The class is a direct translation of your 3 requirements:
to retrieve the previously generated number.
to generate a new number.
avoid using the 'var'.
This shows the basic technique of returning a new immutable instance instead of mutating a variable, although I find the infinite iterator answer by jwvh to be a more elegant solution.
import scala.util.Random
// A random number generator that remembers its current value.
case class RandomInt(size: Int) {
val value = Random.nextInt(size)
def nextRandomInt(): RandomInt = RandomInt(size)
}
// Test case
object RandomInt {
def main(args: Array[String]): Unit = {
val r0 = RandomInt(100)
(0 to 99).foldLeft(r0)((r, i) => {
println(s"[$i] ${r.value}")
r.nextRandomInt()
})
}
}

Not sure what changes you are open too, you can simply just add a parameter
val randomInt = Random.nextInt(100)
private def getRandomInt(createNew:Boolean,previous:Int):Int = {
if(createNew) Random.nextInt(100) else previous
}

Related

How to declare static global values and define them later in Scala?

Primary goal
I want to use some static vals in a class so that I don't have to pass them as function parameters.
My approach
Since I want them to be static, I am declaring them in the companion object. But I cannot assign them values when I declare them, for some reasons. So I am following the below approach.
case class DemoParams(name: String)
class Demo {
def foo = {
println("Demo params name is: ", Demo.demoParams.name) // Works fine
anotherFoo(Demo.demoParams.name) // Throws NPE !
}
def anotherFoo(someName: String) = {
// some code
}
}
object Demo {
var demoParams: DemoParams = _ // Declare here
def apply() = new Demo()
def run = {
demoParams = DemoParams(name = "Salmon") // Define here
val demoObj = Demo()
demoObj.foo
}
def main() = {
run
}
}
Demo.main()
I am able to print Demo.demoParams but surprisingly, this throws a NullPointerException when I pass Demo.demoParams to another function, while running the Spark app on a cluster.
Questions
Firstly, is this the right way of declaring static values and defining them later? I would prefer to not use vars and use immutable vals. Is there a better alternative?
Second, could you think of any reason I would be getting a NPE while passing Demo.demoParams.name to another function?
Your code works fine and doesn't throw anything (after fixing a few compile errors).
But ... Don't do this, it's ... yucky :/
How about passing params to the class as ... well ... params instead?
case class Demo(params: DemoParams) {
def foo() = {
println("Demo params name is: " + params.name)
}
}
object Demo {
def run() = {
val demoParams = DemoParams(name = "Salmon")
val demoObj = Demo(demoParams)
demoObj.foo()
}
}
Not sure this is the best alternative, but consider using a trait, which still keeps you in the FP zone by avoiding the use of var:
case class DemoParams(name: String)
trait Demo {
val demoParams: DemoParams
}
Then just define it where you need it, and it's ready for use:
object MainApp extends App {
val demoObj = new Demo {
override val demoParams: DemoParams = DemoParams(name = "Salmon")
}
println("Demo params name is: ", demoObj.demoParams.name) // (Demo params name is: ,Salmon)
anotherFoo(demoObj.demoParams.name) // Salmon
def anotherFoo(name: String): Unit = println(name)
}
About the second question, without the actual code one can only guess (this sample code does not throw NPE). Probably somewhere you are using it without defining it previously, because var demoParams: DemoParams = _ just initializes demoParams to the default value of the reference type DemoParams, which is null in this case, and you get NPE when you try to access the name value of a null object. This is why using var is discouraged.

Is it possible to declare a val before assignment/initialization in Scala?

In general, can you declare a val in scala before assigning it a value? If not, why not? An example where this might be useful (in my case at least) is that I want to declare a val which will be available in a larger scope than when I assign it. If I cannot do this, how can I achieve the desired behavior?
And I want this to be a val, not a var because after it is assigned, it should NEVER change, so a var isn't ideal.
For example:
object SomeObject {
val theValIWantToDeclare // I don't have enough info to assign it here
def main(): Unit = {
theValIWantToDeclare = "some value"
}
def someOtherFunc(): Unit {
val blah = someOperationWith(theValIWantToDeclare)
}
}
object SomeObject {
private var tviwtdPromise: Option[Int] = None
lazy val theValIWantToDeclare: Int = tviwtdPromise.get
private def declareTheVal(v: Int): Unit = {
tviwtdPromise = Some(v)
theValIWantToDeclare
}
def main(args: Array[String]): Unit = {
declareTheVal(42)
someOtherFunction()
}
def someOtherFunction(): Unit = {
println(theValIWantToDeclare)
}
}
It will crash with a NoSuchElementException if you try to use theValIWantToDeclare before fulfilling the "promise" with declareTheVal.
It sounds to me that you need a lazy val.
A lazy val is populated on demand and the result is cached for all subsequent calls.
https://blog.codecentric.de/en/2016/02/lazy-vals-scala-look-hood/
Why not define a SomeObjectPartial that is partially constructed, and class SomeObject(theVal) that takes the value as a parameter?
Then your program has two states, one with the partial object, and another with the completed object.

Scala - Global variable get the value in a function

I am a beginner of Scala.
I immediately get a problem.
Let's say:
I have a Vector variable and 2 functions. The first one function is calling 2nd function. And there is a variable in 2nd function is what I need to get and then append it to Vector. (Without returning the variable in 2nd function.)
The structure looks like this:
def main(args: Array[String]): Unit = {
var vectorA = Vector().empty
}
def funcA(): sometype = {
...
...
...
funcB()
}
def funcB(): sometype = {
var error = 87
}
How can I add error variable in global Vector?
I tried to write vectorA :+ error but in vain.
You could do the following:
def main(args: Array[String]): Unit = {
val vectorA = funcA(Vector.empty)
}
def funcA(vec: Vector): sometype = {
...
...
...
funcB()
}
def funcB(vec: Vector): sometype = {
// Here you could append, which returns a new copy of the Vector
val error = 87
vec :+ error
}
Keep in mind that, it is advisable to use immutable variables. Though not always this might be true, but for most of the applications that just involve doing some CRUD type logic, it is better to use immutable variables.

Scala: Initialize Object with External Parameters

Assume I have a variable x which receives its value from the user at some point. Once that is done, I need to set up an Object which needs the value of x.
Naively, I'd like to write:
Object MyCoolObject(num:Double) {
//code
}
and then somewhere in the code:
val MCO = MyCoolObject(x)
But that's not possible in Scala. So how do I do it?
This is already discussed here: Pass Parameters to Scala Object
You can also use a case class:
case class MyCoolObject(num: Double)
{
//code
}
val n = 10 // external data
val myCoolObject = MyCoolObject(n)
Something like this:
class MyCoolObject(num:Double) {
}
object MyCoolObject{
def apply(x:Double) = new MyCoolObject(x)
}
val x : Double = 56.1
val MCO = MyCoolObject(x)
You can use this article i.e.
https://twitter.github.io/scala_school/basics2.html

Is it possible to know if a default argument was supplied as an actual parameter value (when they are equal) in Scala?

Is it possible to know if a default argument was supplied as an actual parameter value? In other words, assume that I defined a method:
def myMethod(x: Int = 1) = x + 1
Then is it possible to distinguish between these two calls (which return identical results because the parameter in the second method call has the same value as the default value in method definition) within the method body:
myMethod()
myMethod(1)
In other words, I want to know if there is technique to achieve an effect that is similar to -supplied-p feature in Common Lisp function definitions (see http://www.gigamonkeys.com/book/functions.html and http://www.psg.com/~dlamkins/sl/chapter21.html for details and more context).
No, you can't directly know this.
Here's an ugly workaround that relies on the fact that the default parameter can be a method call. It comes with many caveats, the biggest of which is that it is not thread-safe.
private var usedDefault = false
private def default = {
usedDefault = true
1
}
def myMethod(x: Int = default) = {
if (usedDefault) {
println("default")
} else {
println("supplied")
}
usedDefault = false
}
Another more practical workaround is this:
def myMethod(): Unit = myMethod(1, usedDefault = true)
def myMethod(x: Int): Unit = myMethod(x, usedDefault = false)
private def myMethod(x: Int, usedDefault: Boolean) = {
if (usedDefault) {
println("default")
} else {
println("supplied")
}
}
If you have a small number of parameters you could always overload your functions, so that
def myMethod(x: Int) = x + 1
def myMethod() = myMethod(1)