C++ C+的Scala等价物+;函数中的静态变量

C++ C+的Scala等价物+;函数中的静态变量,c++,scala,static-variables,C++,Scala,Static Variables,我是Scala的新手,偶然发现以下问题: 什么是函数的静态变量的Scala等价物? void foo() { static int x = 5; x++; printf("%d", x); } 编辑: 我想实现的是一种函数调用计数器——我想检查函数的执行次数,同时限制这个计数器的可见性,使它不能从外部修改。< /P> < P>斯卡拉没有等价于C++的局部静态变量。在斯卡拉,范围规则比C++或java更一致——在块中定义的内容在退出块时超出范围。正如其他人所指出的,局部

我是Scala的新手,偶然发现以下问题:

什么是函数的静态变量的Scala等价物?

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

编辑:


我想实现的是一种函数调用计数器——我想检查函数的执行次数,同时限制这个计数器的可见性,使它不能从外部修改。< /P> < P>斯卡拉没有等价于C++的局部静态变量。在斯卡拉,范围规则比C++或java更一致——在块中定义的内容在退出块时超出范围。正如其他人所指出的,局部静态变量会产生副作用,这在函数式编程中是不可取的


Scala是一种混合的OO/函数式语言,可以使用命令式风格编写,但更喜欢并鼓励使用函数式风格(例如,通过将不可变集合作为默认选择)。除了表示副作用本身之外,Java中也没有局部静态变量,这也是Scala中不提供它们的另一个原因。

下面是一段具有类似效果的代码:

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
尽管我必须强调,这是一种非常糟糕的做法,因为它会导致死亡

如果你真的需要这种行为,考虑一下:

type State = Int

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

在Scala中获得C++局部静态变量的等价性:

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
}

这将像C++一样工作,包括当方法或拥有类实例超出范围时(尽管还存在性能损失)。


不是线程安全的。

您能描述一下为什么要将
x
设置为静态吗?可以从
foo
外部访问它吗?
foo
可能是递归的吗?我对C++不太熟悉,知道你的意图会让你更容易想出相应的Scala代码片段。纯函数编程避免了这种可变的变量,因为它导致了一个不透明的函数。C++侧:这被称为局部静态,该变量是全局变量,因为整个程序中只存在一个实例,但其可见性(词法范围)仅限于函数体。这个习语可以用来实现单例,例如,这个副本(第一个例子)实际上更像是C++的函子,但是它确实表现为“代码> f*())/Case>有一个本地静态变量。这不一定要杀死引用的透明度。我想到了回忆录。
def foo():Unit
{
  object x extends StaticLocal( 5 )
  x += 1
  println( x )
}