Scala NetLogo 扩展 API:访问全局变量/模型参数
Scala NetLogo Extension API: access globals / model parameters
我正在为我的一个模型构建一个 Scala 扩展。我想尽可能多地使用 Scala。我一直在阅读 API reference.
我想知道是否可以使用扩展 API 访问全局变量。有人做到了吗?
我已经能够设置 breed、turtle 变量,但是,我开始认为(按设计)扩展无法访问全局变量,因为这在本质上使扩展与模型高度耦合。
如果可能的话,请提供 class 其中全局变量可以通过名称引用。
如果不可能,是否有解决方法?我可以创建另一种包含所有全局变量或将全局变量作为参数传递的品种,但是,这些解决方案是最后的手段。
NetLogo 试图将所有事物都视为代理,因此对于全局变量,它们只是 observer
代理的 breeds-own
变量。
可以使用 world
的 observer
属性 的扩展 API 访问它们。这可能最容易从 the org.nlogo.agent.World
. You can see the observer
属性 那里完成,还有一些用于交互 "observer-owns" 变量的便捷方法。
这里有一个更长的获取和设置全局变量作为扩展的例子:
// 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
你会看到这个输出:
observer> test
observer: [["G1" 0] ["G2" 0] ["G3" 0]]
observer: [["G1" 10] ["G2" "hello"] ["G3" nobody]]
我正在为我的一个模型构建一个 Scala 扩展。我想尽可能多地使用 Scala。我一直在阅读 API reference.
我想知道是否可以使用扩展 API 访问全局变量。有人做到了吗?
我已经能够设置 breed、turtle 变量,但是,我开始认为(按设计)扩展无法访问全局变量,因为这在本质上使扩展与模型高度耦合。
如果可能的话,请提供 class 其中全局变量可以通过名称引用。
如果不可能,是否有解决方法?我可以创建另一种包含所有全局变量或将全局变量作为参数传递的品种,但是,这些解决方案是最后的手段。
NetLogo 试图将所有事物都视为代理,因此对于全局变量,它们只是 observer
代理的 breeds-own
变量。
可以使用 world
的 observer
属性 的扩展 API 访问它们。这可能最容易从 the org.nlogo.agent.World
. You can see the observer
属性 那里完成,还有一些用于交互 "observer-owns" 变量的便捷方法。
这里有一个更长的获取和设置全局变量作为扩展的例子:
// 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
你会看到这个输出:
observer> test
observer: [["G1" 0] ["G2" 0] ["G3" 0]]
observer: [["G1" 10] ["G2" "hello"] ["G3" nobody]]