R “通用”;“类”;里弗
我已经编写了一个堆栈“类”,它具有以下功能:R “通用”;“类”;里弗,r,generics,data-structures,stack,R,Generics,Data Structures,Stack,我已经编写了一个堆栈“类”,它具有以下功能:add,push,pop,size,isEmpty,clear(以及更多) 我想在R中使用这个“类”作为泛型,因此我可以在脚本中创建多个堆栈实例。我该怎么做呢 (我用引号括了类,因为我的堆栈函数是用不同的脚本编写的(不一定是类本身的定义) 提前谢谢 list <- "" cursor = 0 #Initializes stack to empty stack <- function(){ list <- c() cursor = -
add
,push
,pop
,size
,isEmpty
,clear
(以及更多)
我想在R中使用这个“类”作为泛型,因此我可以在脚本中创建多个堆栈实例。我该怎么做呢
(我用引号括了类,因为我的堆栈函数是用不同的脚本编写的(不一定是类本身的定义)
提前谢谢
list <- ""
cursor = 0
#Initializes stack to empty
stack <- function(){
list <- c()
cursor = -1
assign("list",list,.GlobalEnv)
assign("cursor",cursor,.GlobalEnv)
}
#Where item is a item to be added to generic list
push <- function(item){
if(size(list) == 0){
add(item, -1)
}else{
add(item, 0)
}
assign("list",list,.GlobalEnv)
}
list由于您专门讨论的是一个带有push和pop方法的堆栈“类”,下面是Jeff Ryan的一个实现,您可以从中阅读对这里发生的事情的解释
new_stack <- function() {
stack <- new.env()
stack$.Data <- vector()
stack$push <- function(x) .Data <<- c(.Data,x)
stack$pop <- function() {
tmp <- .Data[length(.Data)]
.Data <<- .Data[-length(.Data)]
return(tmp)
}
environment(stack$push) <- as.environment(stack)
environment(stack$pop) <- as.environment(stack)
class(stack) <- "stack"
stack
}
> x <- new_stack()
> x$push(1:3)
> x$pop()
[1] 3
> x$pop()
[1] 2
new_stack这是堆栈实现@GSee引用的一个更简单版本,它避免使用R中可用的任何形式的面向对象系统。简化的前提是R中的所有函数都是闭包,并且在函数调用期间创建的函数都绑定到为该调用创建的环境
new_stack <- function() {
stack <- vector()
push <- function(x) stack <<- c(stack, x)
pop <- function() {
tmp<-tail(stack, 1)
stack<<-stack[-length(stack)]
return(tmp)
}
structure(list(pop=pop, push=push), class='stack')
}
x <- new_stack()
x$push(1:3)
x$pop()
# [1] 3
x$pop()
# [1] 2
new\u stack在这个问题上没有太多的内容。一些代码示例会很有用。你试过用谷歌搜索“Rs4类”吗阅读弹出的手册和指南?@DavidRobinson我没有查看S4课程,因为我不确定我是否需要它们。在这种情况下,这种风格是必要的吗?谢谢。这个问题似乎就是你想要的(因此应该作为副本关闭):@laemtao,让这个问题保持开放的最佳方法是提供一些代码。他的实现过于复杂,可能是出于教学原因。我添加了一个简化版本的答案。@MatthewPloudde遗憾的是,那篇关于闭包的文章根本没有谈到闭包:/@hadely你指的是死链接还是文章中缺少关于闭包的实质性信息?在.exit上使用有点笨拙(而且没有必要)@hadley谢谢你的评论。与通常的tmp remove return不同,我想我应该发挥一些创造力。很抱歉,我不高兴。你的意思是它在可读性方面很笨拙吗?我会在较长的函数中阻止这样的操作,但在这里它似乎是无害的。除了on.exit,还有什么替代方法?(仍在学习S4习性和惯例)@laemtao参见stack@push
在@GSee的答案中。@matthewPlourd它很笨拙,因为你通常会看到打开。exit
用于确保在函数带错误退出时发生某些事情-因此当我看到它时,我立即开始尝试找出会抛出错误的原因。
new_stack <- function() {
stack <- vector()
push <- function(x) stack <<- c(stack, x)
pop <- function() {
tmp<-tail(stack, 1)
stack<<-stack[-length(stack)]
return(tmp)
}
structure(list(pop=pop, push=push), class='stack')
}
x <- new_stack()
x$push(1:3)
x$pop()
# [1] 3
x$pop()
# [1] 2
setClass('Stack',
representation(list='list', cursor='numeric'), # type defs
prototype(list=list(), cursor=NA_real_)) # default values
setGeneric('push', function(obj, ...) standardGeneric('push'))
setMethod('push', signature(obj='Stack'),
function(obj, x) {
obj@list <- c(x, obj@list)
obj
})
setGeneric('pop', function(obj, ...) standardGeneric('pop'))
setMethod('pop', signature(obj='Stack'),
function(obj) {
obj@cursor <- obj@list[[1]]
obj@list <- obj@list[-1]
obj
}
)
x <- new('Stack')
# cursor is empty to start
x@cursor
#[1] NA
# add items
x <- push(x, 1)
x <- push(x, 2)
# pop them (move next item to cursor, remove from list)
x <- pop(x)
x@cursor
# [1] 2
x <- pop(x)
x@cursor
# [1] 1