我一直在研究一个 R 包,它只是一个图形数据库的 REST API 包装器。我有一个函数createNode
,它返回一个带有类node
和的对象entity
:
# Connect to the db.
graph = startGraph("http://localhost:7474/db/data/")
# Create two nodes in the db.
alice = createNode(graph, name = "Alice")
bob = createNode(graph, name = "Bob")
> class(alice)
[1] "node" "entity"
> class(bob)
[1] "node" "entity"
我有另一个函数,createRel
它在数据库中的两个节点之间创建关系。规定如下:
createRel = function(fromNode, type, toNode, ...) {
UseMethod("createRel")
}
createRel.default = function(fromNode, ...) {
stop("Invalid object. Must supply node object.")
}
createRel.node = function(fromNode, type, toNode, ...) {
params = list(...)
# Check if toNode is a node.
stopifnot("node" %in% class(toNode))
# Making REST API calls through RCurl and stuff.
}
允许用户以 key = value的...
形式向关系中添加任意数量的属性。例如,
rel = createRel(alice, "KNOWS", bob, since = 2000, through = "Work")
这会在数据库中创建一个 (Alice)-[KNOWS]->(Bob) 关系,其中包含属性since
及其through
各自的值。from
但是,如果用户使用键或to
在参数中指定属性,R 就会对和...
的类感到困惑。fromNode
toNode
用 key 指定一个属性from
会混淆fromNode
. 它正在使用createRel.default
:
> createRel(alice, "KNOWS", bob, from = "Work")
Error in createRel.default(alice, "KNOWS", bob, from = "Work") :
Invalid object. Must supply node object.
3 stop("Invalid object. Must supply node object.")
2 createRel.default(alice, "KNOWS", bob, from = "Work")
1 createRel(alice, "KNOWS", bob, from = "Work")
类似地,如果用户使用 key 指定属性to
,则会对 的类产生混淆toNode
,并在 处停止stopifnot()
:
Error: "node" %in% class(toNode) is not TRUE
4 stop(sprintf(ngettext(length(r), "%s is not TRUE", "%s are not all TRUE"),
ch), call. = FALSE, domain = NA)
3 stopifnot("node" %in% class(toNode))
2 createRel.node(alice, "KNOWS", bob, to = "Something")
1 createRel(alice, "KNOWS", bob, to = "Something")
我发现明确设置参数createRel
可以正常工作:
rel = createRel(fromNode = alice,
type = "KNOWS",
toNode = bob,
from = "Work",
to = "Something")
# OK
但我想知道我需要如何编辑我的createRel
函数,以便以下语法可以正常工作:
rel = createRel(alice, "KNOWS", bob, from = "Work", to = "Something")
# Errors galore.
打开这个问题的 GitHub 用户提到它很可能与setAs
on dispatch 冲突,它的参数称为from
and to
。一种解决方案是摆脱...
并更改createRel
为以下内容:
createRel = function(fromNode, type, toNode, params = list()) {
UseMethod("createRel")
}
createRel.default = function(fromNode, ...) {
stop("Invalid object. Must supply node object.")
}
createRel.node = function(fromNode, type, toNode, params = list()) {
# Check if toNode is a node.
stopifnot("node" %in% class(toNode))
# Making REST API calls through RCurl and stuff.
}
但是,我想看看在进行此更改之前是否还有其他选择。