我正在为我的一个模型构建一个Scala扩展。我想尽可能多地利用Scala。我一直在阅读API reference。
我想知道是否可以使用扩展API访问全局变量。有人做到了吗?
我已经能够设置品种,乌龟变量,但是,我开始认为(通过设计)扩展不能访问全局变量,因为这本质上将扩展与模型耦合在一起。
如果可能的话,请提供可以通过名称引用全局变量的类。
如果不可能,是否有解决方法?我可以创建另一个包含所有全局变量或将全局变量作为参数传递的品种,但是,这些解决方案是不得已的选择。
答案 0 :(得分:2)
NetLogo尝试将所有内容都视为代理,因此对于全局变量,它们只是breeds-own
代理的observer
变量。
可以从observer
的{{1}}属性使用扩展API访问它们。这很容易从the org.nlogo.agent.World
完成。您可以在此处看到the observer
属性,以及一些与“观察者拥有”变量进行交互的便捷方法。
以下是获取和设置全局变量作为扩展的更长示例:
world
如果将它们作为// will return a list of lists with global names and values
object GetGlobals extends api.Reporter {
override def getSyntax = reporterSyntax(ret = ListType)
def report(args: Array[api.Argument], context: api.Context): AnyRef = {
import org.nlogo.agent.World
import org.nlogo.api.ScalaConversions.toLogoList
val world = context.world.asInstanceOf[World]
val globals = world.observer.variables
val results = (0 until globals.length).map( (i) => {
val globalName = world.observerOwnsNameAt(i)
val globalValue = world.observer.getVariable(i)
Seq( globalName, globalValue ).toLogoList
})
results.toLogoList
}
}
// expects a list of lists with global names and values to set
object SetGlobals extends api.Command {
override def getSyntax = commandSyntax(right = List(ListType))
def perform(args: Array[api.Argument], context: api.Context) {
import org.nlogo.agent.World
import org.nlogo.core.LogoList
val world = context.world.asInstanceOf[World]
val newGlobals = args(0).getList
newGlobals.foreach( (newGlobalAny) => {
val newGlobal = newGlobalAny.asInstanceOf[LogoList]
val globalName = newGlobal(0).asInstanceOf[String]
val newValue = newGlobal(1)
world.setObserverVariableByName( globalName, newValue )
})
}
}
添加到扩展名中,并且将get-globals
添加到名为set-globals
的扩展名中,则可以这样使用它们:
sample-scala
您将看到以下输出:
extensions [ sample-scala ]
globals [ g1 g2 g3 ]
to test
show sample-scala:get-globals
sample-scala:set-globals [ [ "g1" 10 ] [ "g2" "hello" ] [ "g3" nobody ] ]
show sample-scala:get-globals
end