这个问题不是特定于编程语言的(越一般越好),但我在Scala中工作(不一定在JVM上)。是否有通过呼叫位置引用计数的方法,而不是总呼叫的数量?特别是,能够检测是否从多个呼叫位置调用给定方法将是很好的。
我想我可以通过对函数进行引用相等性检查来在某种程度上伪造它,但是这可以通过使用global-ish标记轻松滥用,甚至可以在同一范围内多次调用该函数:
sealed case class Token();
class MyClass[A] {
var tokenOpt: Option[Token] = None
def callMeFromOnePlace(x: A)(implicit tk: Token) = {
tokenOpt match {
case Some(priorTk) => if (priorTk ne tk) throw new IllegalStateException("")
case None => tokenOpt = Some(tk)
}
// Do some work ...
}
}
然后这应该可以正常工作:
val myObj = new MyClass[Int]
val myIntList = List(1,2,3)
implicit val token = Token()
myIntList.map(ii => myObj.callMeFromOnePlace(ii))
但不幸的是,这也是:
val myObj = new MyClass[Int]
implicit val token = Token()
myObj.callMeFromOnePlace(1)
myObj.callMeFromOnePlace(1) //oops, want this to fail
答案 0 :(得分:1)
当您谈论呼叫位置时,它可以由调用堆栈跟踪表示。这是一个简单的例子:
// keep track of calls here (you can use immutable style if you want)
var callCounts = Map.empty[Int, Int]
def f(): Unit = {
// calculate call stack trace hashCode for more efficient storage
// .toSeq makes WrappedArray, that knows how to properly calculate .hashCode()
val hashCode = new RuntimeException().getStackTrace.toSeq.hashCode()
val callLocation = hashCode
callCounts += (callLocation -> (callCounts.getOrElse(callLocation, 0) + 1))
}
List(1,2,3).foreach(_ =>
f()
)
f()
f()
println(callCounts) // Map(75070239 -> 3, 900408638 -> 1, -1658734417 -> 1)
答案 1 :(得分:1)
我不完全清楚你想要做什么但是你的// oops ..例子失败你需要检查PriorTk不是None。 (请注意,它不是一个线程安全的解决方案)
答案 2 :(得分:1)
为了完整性,从类型系统角度强制执行这些约束需要线性类型。