问题标签 [double-dispatch]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
r - R中的双重调度:S4 vs vctrs库
如果我们想在 R 中实现双重调度方法,我们目前有两个选项可供选择:
- S4 方法
- vctrs 库基于 S3 的双重调度
我特别指算术运算符,例如 + 或 *。
它们在性能方面如何比较?他们的间接费用是否具有可比性?
r - 将 vctrs 构建的类放入包中时错误的双重调度方法
我创建了一个新类来使用 vctrs 打印百分比,如 https://vctrs.r-lib.org/articles/s3-vector.html中所述。当我获取 .R 文件时,它运行良好。但是当我使用 devtools 构建包时,使用 vec_arith 实现的基本操作不再起作用:
但是,类似的情况运行良好:转换很好;vec_math 也可以,可以做sum(pct(0.5, 1L) + pct(0.25, 2L))
我制作了一个可重现的示例,其中包含使用 devtools 2.3.2 和 vctrs 0.3.6 加载带有 percent 类的小包所需的代码。
- 我们使用 devtools 创建一个名为 percenterror 的新包:
在这个包的 RStudio 项目内的控制台上,我们声明依赖关系并创建一个新的 .R 文件:
- 让我们在打开的 .R 文件中复制以下代码,并使用 roxygen 标签生成 NAMESPACE :
如果我们这样做library(vctrs)
并获取此文档,
则pct(0.5) + pct(0.25)
可以正常工作。
- 但是,回到控制台,我们创建文档并加载包:
在这里,添加不再起作用:
但是找到了方法:
该方法似乎与正确的泛型相关联:
vec_arith.numeric 方法适用于 pct :
但事实并非如此,vec_arith_pct
方法不适用于 numeric :
当我们使用 rlang::last_trace() 运行错误跟踪时,我们发现该
pct + pct
操作实际上并没有转到正确的方法,甚至不关心上面定义的函数,因为vec_arith.default
用于代替vec_arith.pct
:
出了什么问题,该怎么做才能使它起作用?我已经尝试在没有 vctrs:: 调用的情况下使用 ou,导入或不导入 NAMESPACE 中的几乎所有内容,但无法找到发生了什么。
谢谢
r - 使用 S3 对象进行双重调度,一个泛型与两个泛型
假设您尝试使用 S3 模拟双重调度,并且您正在两种方法之间做出选择:
示例 1:一个泛型f()
示例 2:两个泛型g()
,h()
测试等效性
- 您会说以下哪个示例是更好的选择?
- 一个比另一个更像双重调度,还是它们本质上是等价的?
- 哪个会为用户提供更好的可扩展性/灵活性?
我能说的唯一区别是,在示例 1 中,直接f.foo
调用UseMethod("f.foo", arg2)
,而在示例 2 中,g.foo
调用h
然后调用UseMethod("h", arg2)
. 所以简而言之,第二种方法只有一个额外的函数调用。
也许第二个示例在代码结构中更容易跟踪,但它们本质上是等价的。
当然,最终会更好的是类结构和最适合包的 API 的东西
r - `vec_arith` 包的双重分派错误
我正在尝试实施该vctrs
软件包,但具体而言,我正在尝试使vec_arith
双重调度正常工作。
如果我将它加载到全局环境中,下面的示例代码可以工作,但是如果从它自己的包命名空间中调用,它似乎找不到正确的调度。
如果你只用这个文件构建一个包,有人可以告诉我这是否可以重现吗?
我不知道它是否重要,但描述文件如下所示:
typescript - 如何从映射变量中获取具体类型?
我有以下代码:
我在最后一个最后一个错误:
return colliderFn(s1, s2);
我明白为什么我会收到错误(我认为),但我不知道如何解决它。我基本上是想通过一个映射变量来实现一种干净的双重调度方式,这样每个形状组合都会返回一个有效的函数,我可以调用它来查看它们是否发生冲突。
有没有办法做到这一点?如果是这样,怎么做?
java - 访客模式和双重调度
我知道这是一个很好的领域,但我有一个具体的问题......我保证。
在静态类型、面向对象的世界中花费的时间很少,我最近在阅读Crafting Interpreters时遇到了这种设计模式。虽然我理解这种模式允许在一组定义良好的现有类型(类)上实现可扩展的行为(方法) ,但我并没有完全将其描述为双重分派问题的解决方案,至少在没有一些额外假设的情况下并非如此. 我认为它更多地是对表达式问题进行权衡,您可以将封闭类型换成开放方法。
在我见过的大多数示例中,您最终都会得到这样的结果(无耻地从很棒的Clojure 设计模式中窃取)
在这里,我们有一组类型(消息和活动)可能是关闭的或不经常更改的,还有一组我们希望为扩展而开放的方法(访问者)。现在我感到困惑的是,在大多数示例中,它们将展示如何在不触及现有类的情况下实现其他访问者,例如:
然后毫不客气地暗示这是“双重调度”,但事实并非如此。这里accept
动态分派 的子类型Item
,但在方法内accept
通过visit
方法重载静态分派给传入的访问者。所以我们有一个单独的调度Item
,然后其中的“第二个”静态调度accept
实际上是关于选择一个行为(方法)来调用该Item
类型。只有一种“类型”被发送,而不是两种——第二种是行为。
当我想到双重分派时,我想到了一个按两个参数的类型分派的函数。一种行为,两种类型。
对我来说,这与访问者模式略有不同,访问者模式允许将任何行为集扩展到现有类,但这些行为不一定都代表export
上面四个示例中的相同行为——它们可以是任何东西。如果我们添加另一个访问者,它可能代表导出,但也可能不代表。从 API 层你只是调用accept
方法并相信传入的访问者会做你想做的事,不管它可能是什么。
我看错了吗?