在 Scala.js 中,您将如何导航地遍历对象图?

Posted

技术标签:

【中文标题】在 Scala.js 中,您将如何导航地遍历对象图?【英文标题】:In Scala.js, how would you traverse object graphs navigationally? 【发布时间】:2019-07-24 15:04:10 【问题描述】:

假设您想以navigational 的方式遍历对象图,类似于我们遍历文件系统的方式。

例如,假设您有一个支持此表达式的对象图:

var x = objName.foo.bar.baz.fieldName

我们可以将这个数据访问表达式编码为如下路径:

"objName/foo/bar/baz/fieldName"

通过将这条路径分成多个段,我们可以轻松地在 javascript 中遍历对象图,因为除了传统的点表示法之外,它还支持数组访问表示法:objName["foo"]["bar"]["baz"]["fieldName"]

在 Java 或 JVM Scala 中,我们可以使用反射来遍历对象图,但是在 Scala.js 环境中,您将如何遵循这些路径来遍历 Scala 对象的对象图呢?

换句话说,给定一个形式类似于 URI 的路径,您将如何遍历 Scala.js 对象和字段?

【问题讨论】:

Scala 定义的对象,还是 JS 定义的对象?我认为您目前得到不同的答案,具体取决于。 (尽管我认为在 Scala 3 中它可能以任何一种方式工作。)老实说,我不确定如何在 Scala.js 环境中为普通的 Scala 对象做这件事...... 嗨,贾斯汀。这是关于 Scala.js 环境中的普通 Scala 对象,但是如果它不能用于一般的 scala 对象,你能想出一种方法来设计具有这种能力的 Scala 类吗? 【参考方案1】:

您当然可以在编译时使用宏将常量String 表示形式转换为访问器,但我想您希望能够在运行时对任意字符串执行此操作。

如果目标是能够传递部分构造的路径,那么这只是传递访问器函数的问题。你可以用这样的东西让它更漂亮:

class Path[+A](private val value: () => A) 
  def resolve: A = value()
  def /[B](f: A => B): Path[B] = new Path(() => f(resolve))


implicit class PathSyntax[A](val a: A) extends AnyVal 
  def /[B](f: A => B): Path[B] = new Path(() => a) / f



object Foo 
  val bar = Bar


object Bar 
  val baz = Baz


object Baz

语法并不完全漂亮,但现在是类型安全的,而且看起来也不错:

val barPath: Path[Bar.type] = Foo / (_.bar)
val bazPath: Path[Baz.type] = barPath / (_.baz)

反对,这需要更多的工作,例如。 Paths 之间没有适当的相等/比较。

如果您想坚持自己的方法,我不知道有直接的解决方案。但是,我认为使用 ScalaJS 的全部意义在于保持强类型并避免任何可能导致运行时错误的模式,如果你让它完成它的工作,编译器本可以阻止这些模式。

【讨论】:

以上是关于在 Scala.js 中,您将如何导航地遍历对象图?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SpriteKit 场景编辑器中访问导航图的对象

OGNL(对象图导航语言)学习

页面控制导航符号?

导航抽屉如何覆盖操作栏?

一个可以递归遍历对象图的 NSPredicate?

在遍历事件处理程序集合时,如何安全地从回调中移除处理程序?