C++靜態變量的我是很新的Scala和跨以下問題跌跌撞撞:斯卡拉相當於一個功能
什麼是Scala的功能的靜態變量的相同呢?
void foo()
{
static int x = 5;
x++;
printf("%d", x);
}
編輯:
我想實現的是一種函數調用計數器 - 我要檢查多少次,我的功能已被執行,並在同一時間限制該計數器的可視性使其不能從外部修改。
C++靜態變量的我是很新的Scala和跨以下問題跌跌撞撞:斯卡拉相當於一個功能
什麼是Scala的功能的靜態變量的相同呢?
void foo()
{
static int x = 5;
x++;
printf("%d", x);
}
編輯:
我想實現的是一種函數調用計數器 - 我要檢查多少次,我的功能已被執行,並在同一時間限制該計數器的可視性使其不能從外部修改。
這裏是代碼,也有類似的效果塊:
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
雖然我必須強調,這是一個非常不好的做法,因爲它殺死referential transparency。
如果你真的需要這種行爲可以這樣考慮:
type State = Int
def f(state: State) = {
val newState = state + 1
println(state);
newState;
}
這個(第一個例子)實際上更像是一個C++函數,但它的行爲的確如'f()'有一個局部靜態變量。 –
這並不一定要殺死參照透明度。記憶在腦海中浮現。 – ebruchez
Scala沒有等價於C++的本地靜態變量。在Scala中,範圍規則比C++或Java更加一致 - 在塊中定義的內容在塊被退出時超出範圍。正如其他人所指出的,本地靜態變量將是副作用,這在函數式編程中是不可取的。作爲一種混合OO /函數式語言,Scala使寫入命令式風格成爲可能,但更喜歡和鼓勵功能風格(例如通過使不可變集合成爲默認選擇)。除了代表副作用本身之外,本地靜態變量在Java中也不存在,這是在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++中一樣工作,包括當方法或擁有的類實例超出範圍時(儘管w表現懲罰)。 現在不是線程安全的。
你能描述一下爲什麼讓'x'靜態?它可以從'foo'之外訪問嗎? 'foo'可能是遞歸的?我對C++並不是很熟悉,並且知道你的意圖會更容易想出一個相應的Scala代碼片段。 –
純粹的函數式編程避免了這種可變變量,因爲它導致了一個不「透明」的函數。 – Mik378
C++方面:這被稱爲局部靜態,變量是* global *,因爲整個程序中只存在一個實例,但它的可見性(詞法範圍)限制在函數的主體中。例如,這個習語可以用來實現單身人士。 –