Please help me to make my code work. Here I'm trying to create an S3 template which can take different formulas and numeric vectors as arguments. Also I want to add a plot method, drawing the resulting figure. For now it throws an error:
Error in do.call(f, list(x, y)) : 'what' must be a function or character string
How to correctly use do.call here?
# template
chart <- function(x, y, f, ...) {
list(x, y,
do.call(f, list(x, y)),
class = "myChart")
}
# plot method
plot.myChart <- function(obj, ...) {
persp(x, y, z = outer(x, y, f))
}
# new object
c <- chart(seq(-6, 6, length = 100),
seq(-6, 6, length = 100),
f=sqrt(x^2 y^2))
c
plot.myChart(c)
CodePudding user response:
There are a couple of tweaks you could make.
- Using
do.call(f, list(x, y))
is the same as doingf(x, y)
, so you could just use that, but... - ...you probably don't want to call the function at all during object creation, since that will just create an unnamed data member that you don't seem to use.
- You need to keep a copy of the function
f
for theprint
method. You can just store the function as a function. - It would be best to name the elements of your object, and wrap it in
structure
to apply the class attribute properly. - To access the objects inside the
print
method, you need to refer to them using the$
or[[
operators - You only need to call
plot
, notplot.chart
f
needs to be a function during object creation. You are passing a function call.
chart <- function(x, y, f, ...) {
structure(list(x = x, y = y, f = f), class = "myChart")
}
# plot method
plot.myChart <- function(obj, ...) {
persp(obj$x, obj$y, z = outer(obj$x, obj$y, obj$f), ...)
}
# new object
ch <- chart(x = seq(-6, 6, length = 100),
y = seq(-6, 6, length = 100),
f = function(x, y) sqrt(x^2 y^2))
plot(ch)
Created on 2022-05-10 by the reprex package (v2.0.1)