[R] Fwd: passing a modified argument to an S3 method

2024-04-20 Thread Bert Gunter
## Neglected to cc to list

-- Forwarded message -
From: Bert Gunter 
Date: Sat, Apr 20, 2024 at 1:26 PM
Subject: Re: [R] passing a modified argument to an S3 method
To: CRAN.r 


Well, my interpretation of your explanation is as follows:

You have a long list of "control" values, named "control" in my
example below with all fixed default values.  You also have an S3
generic, named e.g. "test", with many methods. Your methods all use
the control list and possibly other arguments that will vary from
method to method. Also, some methods may want to change some of the
fixed values of control but leave most of them unaltered. The altered
list can change from method to method. Also, some of a method's
altered values may have a default value that you do not wish to
specify each time for the method.

In my example below, I have shown how this can be done. I hope it
approximates what you want to do. However, I second Jeff's
recommendation that you do some reading on your own and **NOT** rely
on my (probably flawed) interpretation, which just is meant to suggest
what could be done (e.g. via ?modifyList) rather than point you to an
exact or best solution. There are many good tutorials out there in
addition to Jeff's suggestion that you can search for.
--

control <- list (a=2, b=3, c= "hi there")
## list of all control parameters with defaults

## The generic
test <- function(x,...){
   UseMethod("test")
}
## So test will dispatch methods on the 'x' object
##
test.default <- function(x,
  control = control,
  ... ## any additional non control arguments
  )
{
   ## default code here such as:
   cat(control$c, "\n default method result returned\n")
   ..1 ## first argument in ... list
}

## An example:
> test(x =3, control, y = 'abcd')
hi there
 default method result returned
[1] "abcd"

## Now a 'foo' method
test.foo <- function(x, control = control, ## fixed list of defaults again
 change, ## list of changed default values
 ## with no defaults for this method
 special = list(c = "So long"),
 ## list of changes with defaults for this method
 ##  If the method does not use its default change it
 ##  must be given explicitly here.
 y = 0 ## additional parameter for this method
 ## with a default
)
   {
   print(control$c)
   cat("Using x = ", x, "\n")
   before <- with(control, sum(a, b, y)) ## before modifying values
   change <- c(change, special) ## get all the changes to the control list
   control <- modifyList(control, val = change)
   after <- with(control, sum(a, b, y))
   cat("Results are: before = ",before, "  after = ", after, "\n\n")
   print(control$c)
   invisible(list(before, after)) ## return but don't print
}

## construct object of class 'foo'
> x <- structure("method foo", class = "foo")

## Now call the foo method on it.
## Note that the 'special' argument can be omitted, since the default
change to the
## 'c' control parameter will be used
## Note also that the 'a' parameter in the control list is used and so does not
## have to be specified in the change list.

> test(x, control, change = list( b = 100), y = 11)
[1] "hi there"
Using x =  method foo
Results are: before =  16   after =  113

[1] "So long"

## Specify a different 'special' value
> test(x, control, special = list( c="Au revoir"),  change = list( b = 100), y 
> = 11)
[1] "hi there"
Using x =  method foo
Results are: before =  16   after =  113

[1] "Au revoir"


Cheers,
Bert


On Sat, Apr 20, 2024 at 9:03 AM CRAN.r  wrote:
>
> I've got a complicated default value for an argument, basically a "control" 
> argument that's a list with a lot of defaults, and I want to figure out its 
> value before dispatching to a method so I don't need to have the same code 
> repeated at the beginning of every method. None of the default values should 
> be method-dependent, so I don't need or want each method to figure out the 
> value separately. I hope that helps!
>
> Jay
>
>
> On Saturday, April 20th, 2024 at 10:51 AM, Bert Gunter 
>  wrote:
>
> > I do not understand what your goal is here (more context may be helpful, 
> > perhaps to others rather than me). So I doubt this is what you want, but 
> > here is a guess -- no need to respond if it is unhelpful:
> >
> > ## test.default returns NULL if object "y" not found in **calling 
> > environment and enclosures**;
> > ## otherwise y.
> >
> > test <- function(x){
> > UseMethod("test")
> > }
> > test.default <- function(x){
> > tryCatch(y, error = function(e)NULL)
> > }
> >
> > ## y not found
> > test(x=3)
> > NULL
> >
> > ## y found
> > > y <- 'abcd'
> > > test(x = 3)
> > [1] "abcd"
> >
> > Cheers,
> > Bert
> >
> >
> >
> >
> > On Sat, Apr 20, 2024 at 4:23 AM CRAN.r via R-help  
> > wrote:
> >
> > > Is there a way to pass a modified argument from an 

Re: [R] passing a modified argument to an S3 method

2024-04-20 Thread Berry, Charles via R-help


> On Apr 19, 2024, at 1:36 PM, CRAN.r via R-help  wrote:
> 
> Is there a way to pass a modified argument from an S3 generic to a method?  
> Here's a non-working example that I want to return "abcd".
> 

grep-ing the source code is often a good way to answer a question like this.

Particularly, with NextMethod there seem to be plenty of instances in which the 
original arguments are modified before a call to a method.

One such is `t.data.frame` and there seem to be other methods for "data.frame" 
objects that modify the objects before calling NextMethod.

HTH,

Chuck


>  test <- function(x, y = NULL){
>y <- "abcd"
>UseMethod("test")
>  }
>  test.default <- function(x, y = NULL) y
>  test(x = 3)
> 
> Is that possible? I've looked around a lot, but can't find any examples or 
> discussion.
> 
> Jay
> 
> From nobody Sat Apr 20 10:07:59 2024
> Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail
> From: "CRAN.r via R-help" 
> Newsgroups: gmane.comp.lang.r.general
> Subject: passing a modified argument to an S3 method
> Date: Fri, 19 Apr 2024 20:36:22 +
> Approved: n...@gmane.org
> Message-ID: 
> <4pRzEDv__NGDIT68Q6LBK0OcyD9iQs3g6SkZemots3x4noMUQIV8UAfjDEe2UOq6-D4FF6z0T-76bUG0UxqFccqyFKVKw31OB_Iyh0kbzFs=@proton.me>
> Reply-To: "CRAN.r" 
> Mime-Version: 1.0
> Content-Type: text/plain; charset="us-ascii"
> Content-Transfer-Encoding: 7bit
> Injection-Info: ciao.gmane.io; 
> posting-host="blaine.gmane.org:116.202.254.214";
> logging-data="8351"; mail-complaints-to="use...@ciao.gmane.io"
> To: "r-help@r-project.org" 
> Original-X-From: r-help-boun...@r-project.org Sat Apr 20 13:23:27 2024
> Return-path: 
> Envelope-to: gclrg-r-h...@m.gmane-mx.org
> Original-Received: from hypatia.math.ethz.ch ([129.132.119.208])
> by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
> (Exim 4.92)
> (envelope-from )
> id 1ry8oY-0001sq-Bn
> for gclrg-r-h...@m.gmane-mx.org; Sat, 20 Apr 2024 13:23:26 +0200
> Original-Received: from localhost (localhost [127.0.0.1])
> by hypatia.math.ethz.ch (Postfix) with ESMTP id 439F319B4;
> Sat, 20 Apr 2024 13:23:25 +0200 (CEST)
> Authentication-Results: hypatia.math.ethz.ch (amavisd-new);
> dkim=pass (1024-bit key) reason="pass (just generated, assumed good)"
> header.d=r-project.org
> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=r-project.org; h=
> content-transfer-encoding:content-type:content-type:reply-to
> :from:from:list-subscribe:list-help:list-post:list-archive
> :list-unsubscribe:list-id:precedence:subject:subject
> :mime-version:message-id:date:date:received:received:received
> :received:received:received; s=dkim20211220; t=1713612201; x=
> 1716204202; bh=Z6v15ZPk1rn+11Ef9rNBtKr6kCXFKaj/SGL/HXarBWc=; b=H
> O9aWKsrJKBwRK33ySDQjcif0WL28cjIvg6O3iIC0c1aB+fihnMC/BTLjCyUGIorY
> Yx7Um4sp4+sw0nnmvWWBKL1e1YVr5+QfUCkIyDU6NawYEeC8m3VjEQa7KMALgJN5
> awIR6NsAbCK1ewPN2QPNWMxpIftLzbaQOWMWPCqOPU=
> X-Virus-Scanned: amavisd-new at r-project.org
> Original-Received: from hypatia.math.ethz.ch ([127.0.0.1])
> by localhost (hypatia.math.ethz.ch [127.0.0.1]) (amavisd-new, port 10024)
> with LMTP id O5euluMcNO0X; Sat, 20 Apr 2024 13:23:21 +0200 (CEST)
> Original-Received: from hypatia.math.ethz.ch (localhost [127.0.0.1])
> by hypatia.math.ethz.ch (Postfix) with ESMTP id 8C1D44D3;
> Sat, 20 Apr 2024 13:23:21 +0200 (CEST)
> Original-Received: from localhost (localhost [127.0.0.1])
> by hypatia.math.ethz.ch (Postfix) with ESMTP id 1378F1C23
> for ; Fri, 19 Apr 2024 22:36:39 +0200 (CEST)
> X-Virus-Scanned: amavisd-new at r-project.org
> Original-Received: from hypatia.math.ethz.ch ([127.0.0.1])
> by localhost (hypatia.math.ethz.ch [127.0.0.1]) (amavisd-new, port 10024)
> with LMTP id y-CERIWOjFBy for ;
> Fri, 19 Apr 2024 22:36:34 +0200 (CEST)
> Original-Received: from ethz.ch (mc3.ethz.ch [129.132.198.195])
> (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
> (No client certificate requested)
> by hypatia.math.ethz.ch (Postfix) with ESMTPS id 87F5E1B8C
> for ; Fri, 19 Apr 2024 22:36:34 +0200 (CEST)
> Original-Received: from mail-4322.protonmail.ch ([185.70.43.22])
> by ethz.ch stage1 with esmtps (Exim MailCleaner) 
> id 1rxv0v-000253-1n for  
> from ; Fri, 19 Apr 2024 22:39:17 +0200
> X-MailCleaner-SPF: pass
> Feedback-ID: 10121:user:proton
> X-Pm-Message-ID: 1d72f1b23cf9e2d0142aaa1edb9ef8ebccac926b
> X-Newsl: is not newsletter (0.0/5.0) position : 0, not decisive
> X-NiceBayes: is not spam (52.38%) position : 3, not decisive
> X-Spamc: is not spam (0.0/5.0) position : 7, ham decisive
> X-MailCleaner-Information: Please contact serviced...@id.ethz.ch for more
> information
> X-MailCleaner-ID: 1rxv0v-000257-24
> X-MailCleaner: Found to be clean
> X-MailCleaner-SpamCheck: not spam, Newsl (score=0.0, required=5.0, NONE,
> position : 0, not decisive), NiceBayes (52.38%, position : 3,
> not decisive), Spamc (score=0.0, required=5.0,
> RCVD_IN_MSPIKE_H4 -0.0, DKIM_VALID -0.3, RCVD_IN_MSPIKE_WL -0.0,
> MC_SPF_PASS -0.0, BOTNET_IPINHOSTNAME 1.0,
> MC

Re: [R] passing a modified argument to an S3 method

2024-04-20 Thread Jeff Newmiller via R-help
The parameters in a specific call to a function are stored in a special list 
which is used to move/copy data from the calling environment into the 
environment created for a particular function call.

UseMethod does not act like a normal function call... it does a kind of magic 
substitution of the implementation method `test.default` into the call stack 
where the generic function `test` was. The argument list remains, but the 
environment associated with the generic function `test` is discarded in the 
process. The argument list was never actually modified in `test`... just the 
environment.

You are expected to think of `test` as a placeholder... a kind of abstract 
method that doesn't actually do anything other than map from a generic method 
to an implementation method. Your goal of adding shared behavior this way is 
not possible.

I recommend reading Advanced R in book form or online to help you navigate R 
behavior like this.

On April 20, 2024 8:51:23 AM PDT, Bert Gunter  wrote:
>I do not understand what your goal is here (more context may be helpful,
>perhaps to others rather than me). So I doubt this is what you want, but
>here is a guess -- no need to respond if it is unhelpful:
>
>## test.default returns NULL if object "y" not found in **calling
>environment and enclosures**;
>## otherwise y.
>
>test <- function(x){
>   UseMethod("test")
>}
>test.default <- function(x){
>   tryCatch(y, error = function(e)NULL)
>}
>
>## y not found
>test(x=3)
>NULL
>
>## y found
>> y <- 'abcd'
>> test(x = 3)
>[1] "abcd"
>
>Cheers,
>Bert
>
>
>
>
>On Sat, Apr 20, 2024 at 4:23 AM CRAN.r via R-help 
>wrote:
>
>> Is there a way to pass a modified argument from an S3 generic to a
>> method?  Here's a non-working example that I want to return "abcd".
>>
>>   test <- function(x, y = NULL){
>> y <- "abcd"
>> UseMethod("test")
>>   }
>>   test.default <- function(x, y = NULL) y
>>   test(x = 3)
>>
>> Is that possible? I've looked around a lot, but can't find any examples or
>> discussion.
>>
>> Jay
>>
>> __
>> R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see
>> https://stat.ethz.ch/mailman/listinfo/r-help
>> PLEASE do read the posting guide
>> http://www.R-project.org/posting-guide.html
>> and provide commented, minimal, self-contained, reproducible code.
>>
>
>   [[alternative HTML version deleted]]
>
>__
>R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see
>https://stat.ethz.ch/mailman/listinfo/r-help
>PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
>and provide commented, minimal, self-contained, reproducible code.

-- 
Sent from my phone. Please excuse my brevity.

__
R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.


Re: [R] passing a modified argument to an S3 method

2024-04-20 Thread Bert Gunter
I do not understand what your goal is here (more context may be helpful,
perhaps to others rather than me). So I doubt this is what you want, but
here is a guess -- no need to respond if it is unhelpful:

## test.default returns NULL if object "y" not found in **calling
environment and enclosures**;
## otherwise y.

test <- function(x){
   UseMethod("test")
}
test.default <- function(x){
   tryCatch(y, error = function(e)NULL)
}

## y not found
test(x=3)
NULL

## y found
> y <- 'abcd'
> test(x = 3)
[1] "abcd"

Cheers,
Bert




On Sat, Apr 20, 2024 at 4:23 AM CRAN.r via R-help 
wrote:

> Is there a way to pass a modified argument from an S3 generic to a
> method?  Here's a non-working example that I want to return "abcd".
>
>   test <- function(x, y = NULL){
> y <- "abcd"
> UseMethod("test")
>   }
>   test.default <- function(x, y = NULL) y
>   test(x = 3)
>
> Is that possible? I've looked around a lot, but can't find any examples or
> discussion.
>
> Jay
>
> __
> R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide
> http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
>

[[alternative HTML version deleted]]

__
R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.


[R] passing a modified argument to an S3 method

2024-04-20 Thread CRAN.r via R-help
Is there a way to pass a modified argument from an S3 generic to a method?  
Here's a non-working example that I want to return "abcd".

  test <- function(x, y = NULL){
y <- "abcd"
UseMethod("test")
  }
  test.default <- function(x, y = NULL) y
  test(x = 3)

Is that possible? I've looked around a lot, but can't find any examples or 
discussion.

Jay

__
R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.