Scala equivalent of c ++ static variable in function

I am new to Scala and came across the following problem:

What is the Scala equivalent of a static function variable?

void foo() { static int x = 5; x++; printf("%d", x); } 

EDIT:

What I want to achieve is a kind of counter of function calls - I want to check how many times my function has been executed, and at the same time limit the visibility of this counter so that it cannot be changed externally.

+6
source share
3 answers

Here is a block of code that has a similar effect:

 scala> object f extends Function0[Unit] { | var x = 0; | def apply = { | x = x + 1; | println(x); | } | } defined module f scala> f() 1 scala> f() 2 

Although I must emphasize that this is a very bad practice, as it kills referential transparency .

If you really need this behavior, think about it:

 type State = Int def f(state: State) = { val newState = state + 1 println(state); newState; } 
+18
source

Scala has no equivalent to C ++ local static variables. In Scala, scoping rules are more consistent than in C ++ or Java - what is defined in the block goes out of scope when the block exits. As others noted, a local static variable will be a side effect, which is undesirable in functional programming.

Scala, being a hybrid OO / functional language, allows you to write in an imperative style, but prefers and encourages a functional style (for example, making immutable collections the default choice). Local static variables, in addition to presenting a side effect as such, are also missing in Java, which is another reason not to provide them in Scala.

+2
source

To get the equivalent of a local C ++ static variable in Scala:

 import scala.collection.parallel.mutable import scala.reflect._ import scala.reflect.runtime.universe._ object StaticLocal { private val classes = new mutable.ParHashSet[String] private val variables = new mutable.ParHashMap[String, AnyVal] } import Numeric._ class StaticLocal[T <: AnyVal](value:T)(implicit tag: TypeTag[T], num: Numeric[T]){ val name = this.getClass + "." + tag.toString() ; private var inited = false if (!inited) { inited = true if (!StaticLocal.classes.contains(name)) { StaticLocal.classes += name StaticLocal.variables += name -> value.asInstanceOf[AnyVal] } } def get():T = {StaticLocal.variables.get(name) match { case x:Some[Int] => (x.get).asInstanceOf[T] ; case None => throw new Exception("Not found:" + name) }} def set(value:AnyVal) { StaticLocal.variables.put(name, value)} def +(v:StaticLocal[T]):T = { num.plus(this.get, v.get) } def +(v:T):T = { num.plus(this.get, v) } def +=(v:T):Unit = { set(num.plus(this.get, v)) } def +=(v:StaticLocal[T]):Unit = { set(num.plus(this.get, v.get)) } override def toString() = { get.toString} implicit def StaticLocalWrapper(s: StaticLocal[T]):T = s.get } 

Then in the method:

 def foo():Unit { object x extends StaticLocal( 5 ) x += 1 println( x ) } 

This will work the same way as in C ++, including when the method or the owner of the class instance goes beyond the scope (albeit with a performance limit). Non-thread safe as it stands.

+1
source

All Articles