0
votes

Anyone know if the following can be achieved in R specifically S4

foo <- setClass("foo", contains = "matrix")
foo <- function(m = matrix(1:9, nrow = 3)) new("foo", m)

setMethod("dim", signature = "foo", 
  function(x) {
       dd <- dim([email protected])
       cat("foo dims: ")
       return(dd)
}
)

# followed by  
bar <- foo()

How or can it be achieved to distinguish between ...

dim(bar)
# which gives
foo dims: [1] 3 3 
# and calling dim to assign the return value to a variable 
# ie this call
bardims <- dim(bar)
# which does 
foo dims: 
# but I don't want it to produce any cat output to the console/screen

in the second case I would like to suppress the cat(....) part of the original "dim,foo-method". I would not mind defining something like setMethod('<-dim', 'foo', function(.... but I guess that is not available? Info: I am using R-4.0.5 here

1
It is perfectly possible to create assignment methods, but the function is called dim<- rather than <-dim. - JDL
I know; but the goal here is a different one ... I am trying to find a way to be able to change the output based on: if I am calling dim just to see the dims and then being verbose in its output and a "silent" version of it, when I am assigning the value of dim(object) to a DIFFERENT variable - ie I am not 'assigning' a value to the dimensions of the object itself but using that value somewhere later on and don't want verbosity at the Console or anywhere else; MrFlick's answer achieves exactly that -> which is quite cool - GWD

1 Answers

1
votes

It's generally not a great idea to use cat() to spit out messages in function. It gives users very little control over how they display and makes it very difficult to grab those values should they ever want them.

A possible alternative is to annotate the response with a custom class that will output a message only when print()-ed. Hence it will not show up during assignment because those results are returned invisibly.

Here's an S3 class that can help

annotate_value <- function(val, msg) {
  attr(val, "message") <- msg
  class(val) <- c("annotated", class(val))
  val
}
print.annotated <- function(x) {
  class(x) <- setdiff(class(x), "annotated")
  cat(attr(x, "message"))
  attr(x, "message") <- NULL
  print(x)
}

And then you use it like


setMethod("dim", signature = "foo", 
          function(x) {
            dd <- dim([email protected])
            annotate_value(dd, "foo dims:")
          }
)

Then when you run your code, you get the desired output

bar <- foo()
dim(bar)
# foo dims:[1] 3 3
bardims <- dim(bar)
#