0

我在这里试图解决的问题是需要应用(执行)一个 S3 对象,该对象本质上是一个类似向量的结构。这可能包含在某个阶段我需要评估单个参数的各种公式,以便返回原始形状的类似矢量的对象,其中包含在给定参数处对其组成公式的评估。

这方面的例子(只是为了说明)可能是一个变换矩阵 - 比如说旋转 - 对于给定的旋转,它将采用旋转的角度,并产生一个值矩阵,该矩阵乘以一个点。另一个例子可能是经典力学问题中的状态向量。然后给定tva等,它可以返回s ...

现在,我已经在 S3 中创建了我的容器对象,并且它在大多数方面都可以正常工作,使用通用方法;我还发现 Ops.myClass 运算符重载系统非常有用。

为了完成我的课程,我现在需要的只是一种将其指定为可执行文件的方法。我看到有各种机制可以部分完成我想要做的事情,例如我想这as.function()会将对象转换为我想要的行为,并且类似的东西lapply()可以用于将参数“反向”应用于函数。我不知道该怎么做是将它们全部链接起来,以便我可以做这样的模型:

new_Object <- function(<all my function vector stuff spec>)
vtest <- new_Object(<say, sin, cos, tan>)
vtest(1)
   ==>
myvec(.8414709848078965 .5403023058681398 1.557407724654902)

(是的,我已经指定了一个通用的print()例程,让它看起来不错)

欢迎所有建议、示例代码、示例链接。

PS =====

我根据要求添加了一些基本的示例代码。我不确定多少会太多,所以完整的工作最小示例,包括运算符重载在此要点中。

我只在下面显示构造函数和辅助函数:

# constructor
new_Struct <- function(stype , vec){
  stopifnot(is.character(stype)) # enforce up | down
  stopifnot(is.vector(vec))
  structure(vec,class="Struct", type=stype)
}

# constructor helper functions --- need to allow for nesting!
up <-function(...){
  vec <- unlist(list(...),use.names = FALSE)
  new_Struct("up",vec)
}
down <-function(...){
  vec <- unlist(list(...),use.names = FALSE)
  new_Struct("down",vec)
}

上述代码的行为如下:

> u1 <- up(1,2,3)
> u2 <- up(3,4,5)
> d1 <- down(u1)
> d1
[1] down(1, 2, 3)
> u1+u2
[1] up(4, 6, 8)
> u1+d1
Error: '+' not defined for opposite tuple types
> u1*d1
[1] 14
> u1*u2
     [,1] [,2] [,3]
[1,]    3    4    5
[2,]    6    8   10
[3,]    9   12   15
> u1^2
[1] 14
> s1 <- up(sin,cos,tan)
> s1
[1] up(.Primitive("sin"), .Primitive("cos"), .Primitive("tan"))
> s1(1)
Error in s1(1) : could not find function "s1"

我需要的是它能够做到这一点:

> s1(1)
[1] up(.8414709848078965 .5403023058681398 1.557407724654902)
4

2 回答 2

2

您不能在没有循环的情况下调用函数列表中的每个函数。

我没有完全理解所有要求,但这应该给你一个开始:

new_Struct <- function(stype , vec){
  stopifnot(is.character(stype)) # enforce up | down
  stopifnot(is.vector(vec) || is.function(vec))
  structure(vec,class="Struct", type=stype)
}

# constructor helper functions --- need to allow for nesting!
up <- function(...) UseMethod("up")

up.default <- function(...){
  vals <- list(...)
  stopifnot(all(vapply(vals, is.vector, FUN.VALUE = logical(1))))
  vec <- unlist(vals, use.names = FALSE)
  new_Struct("up",vec)
}

up.function  <- function(...){
  funs <- list(...)
  stopifnot(all(vapply(funs, is.function, FUN.VALUE = logical(1))))
  new_Struct("up", function(x) new_Struct("up", sapply(funs, do.call, list(x))))
}

up(1, 2, 3)
#[1] 1 2 3
#attr(,"class")
#[1] "Struct"
#attr(,"type")
#[1] "up"

up(1, 2, sin)
#Error in up.default(1, 2, sin) : 
#  all(vapply(vals, is.vector, FUN.VALUE = logical(1))) is not TRUE 

up(sin, 1, 2)
#Error in up.function(sin, 1, 2) : 
#  all(vapply(funs, is.function, FUN.VALUE = logical(1))) is not TRUE 

s1 <- up(sin, cos, tan)
s1(1)
#[1] 0.8414710 0.5403023 1.5574077
#attr(,"class")
#[1] "Struct"
#attr(,"type")
#[1] "up"
于 2018-09-04T12:29:15.877 回答
0

经过一番思考,我想出了一种方法来解决这个问题,它并不完美,如果有人能想出一种方法来使函数调用隐式/透明,那就太好了。

所以,现在我只使用call()对象上的机制,这似乎工作正常。这是代码的相关部分,减去检查。我将在与上述相同的要点上提供最新的完整版本。

# constructor
new_Struct <- function(stype , vec){
  stopifnot(is.character(stype)) # enforce up | down
  stopifnot(is.vector(vec))
  structure(vec,class="Struct", type=stype)
}

# constructor helper functions --- need to allow for nesting!
up <- function(...){
  vec <- unlist(list(...), use.names = FALSE)
  new_Struct("up",vec)
}
down <- function(...){
  vec <- unlist(list(...), use.names = FALSE)
  new_Struct("down",vec)
}

# generic print for tuples
print.Struct <- function(s){
  outstr <- sprintf("%s(%s)", attributes(s)$type, paste(c(s), collapse=", "))
  print(noquote(outstr))
}

# apply the structure - would be nice if this could be done *implicitly*
call <- function(...) UseMethod("call")
call.Struct <- function(s,x){
  new_Struct(attributes(s)$type, sapply(s, do.call, list(x)))
}

现在我可以这样做:

> s1 <- up(sin,cos,tan)
> length(s1)
[1] 3
> call(s1,1)
[1] up(0.841470984807897, 0.54030230586814, 1.5574077246549)
> 

不如我的最终目标

> s1(1)
[1] up(0.841470984807897, 0.54030230586814, 1.5574077246549)

但它现在会做......

于 2018-09-04T23:01:55.357 回答