9

私はScalaにまったく慣れておらず、次の問題に遭遇しました。

関数の静的変数に相当するScalaとは何ですか?

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

編集:

私が達成したいのは、一種の関数呼び出しカウンターです。関数が実行された回数を確認すると同時に、このカウンターの表示を制限して、外部から変更できないようにします。

4

3 に答える 3

20

同様の効果を持つコードのブロックは次のとおりです。

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;
}
于 2013-01-07T13:27:58.353 に答える
3

Scalaには、C++のローカル静的変数に相当するものはありません。Scalaでは、スコープ規則はC ++やJavaよりも一貫性があります。ブロック内で定義されているものは、ブロックが終了するとスコープ外になります。他の人が指摘したように、ローカル静的変数は副作用であり、関数型プログラミングでは望ましくありません。

ハイブリッドOO/関数型言語であるScalaは、命令型スタイルでの記述を可能にしますが、関数型スタイルを好み、奨励します(たとえば、不変のコレクションをデフォルトの選択にすることによって)。ローカル静的変数は、それ自体が副作用を表すことは別として、Javaにも存在しません。これが、Scalaでそれらを提供しないもう1つの理由です。

于 2013-01-07T13:27:05.787 に答える
1

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
}

次に、メソッドで:

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

これは、メソッドまたは所有するクラスインスタンスがスコープ外になる場合を含め、C ++の場合と同じように機能します(ただし、パフォーマンスが低下します)。現状ではスレッドセーフではありません。

于 2015-11-20T08:57:49.597 に答える