Is it Possible to Create S4 Function Objects?

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Is it Possible to Create S4 Function Objects?

aBBy Spurdle, ⍺XY
Dear All,

I was wondering if it's possible to create S4 function objects?
(Or S4 closures, if you prefer).

i.e.
An R object, that is both an S4 object, and a function.

This would allow one to write:

> f <- constructor4.functionobj ()
> f ()
> [hidden email]

I've searched for this, but I can't find any examples.

If it's possible, then that leads to the question of if/how the body
of f() could directly access the value of the slot?

> f <- function ()
>    [hidden email]

I should note that the more common approach of storing values in a
function's environment, doesn't work well for top-level objects.
This approach is dependent on immutability of the function's data, and
I'm reluctant to create such constraints.

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|

Re: Is it Possible to Create S4 Function Objects?

aBBy Spurdle, ⍺XY
It appears that my previous post may lack clarity.

So, I've created three examples of mathematical function objects.
(One) using a standard closure with lexical scoping, (two) using S3
with an attribute and (three) using S4 with a slot.
Each example constructs the function object via a constructor (of some
form), plots it, then prints the attribute/etc.
However, the third example with S4 is incomplete.

Any suggestions welcome.

----begin code----

plotf <- function (f)
{   x <- seq (-1, 1,, 200)
    plot (x, f (x), type="l")
}

#standard closure, with lexical scoping
quad.lex <- function (p = c (0, 0, 1) )
{   function (x)
        p [1] + p [2] * x + p [3] * x^2
}

#s3-based function object, with attribute
quad.s3 <- function (p = c (0, 0, 1) )
{   f <- function (x)
    {   this <- sys.function ()
        p <- attr (this, "p")
        p [1] + p [2] * x + p [3] * x^2
    }
    attr (f, "p") <- p
    f
}

#s4-based function object, with slot
setClass ("Quad.S4", slots = list (p="numeric") )
Quad.S4 <- function (p = c (0, 0, 1) )
{   #?
}

f.lex <- quad.lex ()
plotf (f.lex)
environment (f.lex)$p

f.s3 <- quad.s3 ()
plotf (f.s3)
attr (f.s3, "p")

f.s4 <- Quad.S4 ()
#plotf (f.s4)
#f.s4@p


On Sat, Feb 13, 2021 at 10:53 AM Abby Spurdle (/əˈbi/)
<[hidden email]> wrote:

>
> Dear All,
>
> I was wondering if it's possible to create S4 function objects?
> (Or S4 closures, if you prefer).
>
> i.e.
> An R object, that is both an S4 object, and a function.
>
> This would allow one to write:
>
> > f <- constructor4.functionobj ()
> > f ()
> > [hidden email]
>
> I've searched for this, but I can't find any examples.
>
> If it's possible, then that leads to the question of if/how the body
> of f() could directly access the value of the slot?
>
> > f <- function ()
> >    [hidden email]
>
> I should note that the more common approach of storing values in a
> function's environment, doesn't work well for top-level objects.
> This approach is dependent on immutability of the function's data, and
> I'm reluctant to create such constraints.

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|

Re: Is it Possible to Create S4 Function Objects?

Hervé Pagès-3
In reply to this post by aBBy Spurdle, ⍺XY
Hi Abby,

Something along the line of:

   setClass("S4Function",
     contains="function",
     representation(name="character", more_stuff="ANY")
   )

seems to do what you want:

   f <- new("S4Function", function(a) a^2, name="square")

   # 'f' is both an S4 object and a function:
   is.object(f)
   # [1] TRUE
   is.function(f)
   # [1] TRUE

   f@name
   # [1] "square"
   f(11)
   # [1] 121

Hope this helps,

H.

On 2/12/21 1:53 PM, Abby Spurdle (/əˈbi/) wrote:

> Dear All,
>
> I was wondering if it's possible to create S4 function objects?
> (Or S4 closures, if you prefer).
>
> i.e.
> An R object, that is both an S4 object, and a function.
>
> This would allow one to write:
>
>> f <- constructor4.functionobj ()
>> f ()
>> [hidden email]
>
> I've searched for this, but I can't find any examples.
>
> If it's possible, then that leads to the question of if/how the body
> of f() could directly access the value of the slot?
>
>> f <- function ()
>>     [hidden email]
>
> I should note that the more common approach of storing values in a
> function's environment, doesn't work well for top-level objects.
> This approach is dependent on immutability of the function's data, and
> I'm reluctant to create such constraints.
>
> ______________________________________________
> [hidden email] 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.
>

--
Hervé Pagès

Bioconductor Core Team
[hidden email]

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|

Re: Is it Possible to Create S4 Function Objects?

aBBy Spurdle, ⍺XY
Oh wow.
Post of the year!
Where's the like button?

Note, I was able to rewrite it without the deprecated args.
(Don't want one of those CRAN emails, in 12 months from now, saying
please change XXXX).

I'll have to come back to this later, to see if I can get the body of
f() to access the slot


On Mon, Feb 22, 2021 at 11:36 AM Hervé Pagès <[hidden email]> wrote:

>
> Hi Abby,
>
> Something along the line of:
>
>    setClass("S4Function",
>      contains="function",
>      representation(name="character", more_stuff="ANY")
>    )
>
> seems to do what you want:
>
>    f <- new("S4Function", function(a) a^2, name="square")
>
>    # 'f' is both an S4 object and a function:
>    is.object(f)
>    # [1] TRUE
>    is.function(f)
>    # [1] TRUE
>
>    f@name
>    # [1] "square"
>    f(11)
>    # [1] 121
>
> Hope this helps,
>
> H.

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|

Re: Is it Possible to Create S4 Function Objects?

aBBy Spurdle, ⍺XY
I've completed the S4 example.
Thank you, Herve, for your assistance.

----begin code----
plotf <- function (f)
{   x <- seq (-1, 1,, 200)
    plot (x, f (x), type="l")
}

#s4-based function object, with slot
setClass ("Quad.S4", contains="function", slots = list (p="numeric") )
Quad.S4 <- function (p = c (0, 0, 1) )
{   f <- function (x)
    {   this <- sys.function ()
        p <- this@p
        p [1] + p [2] * x + p [3] * x^2
    }
    new ("Quad.S4", f, p=p)
}

f.s4 <- Quad.S4 ()
plotf (f.s4)
f.s4@p


On Tue, Feb 23, 2021 at 11:23 AM Abby Spurdle (/əˈbi/)
<[hidden email]> wrote:

>
> Oh wow.
> Post of the year!
> Where's the like button?
>
> Note, I was able to rewrite it without the deprecated args.
> (Don't want one of those CRAN emails, in 12 months from now, saying
> please change XXXX).
>
> I'll have to come back to this later, to see if I can get the body of
> f() to access the slot
>
>
> On Mon, Feb 22, 2021 at 11:36 AM Hervé Pagès <[hidden email]> wrote:
> >
> > Hi Abby,
> >
> > Something along the line of:
> >
> >    setClass("S4Function",
> >      contains="function",
> >      representation(name="character", more_stuff="ANY")
> >    )
> >
> > seems to do what you want:
> >
> >    f <- new("S4Function", function(a) a^2, name="square")
> >
> >    # 'f' is both an S4 object and a function:
> >    is.object(f)
> >    # [1] TRUE
> >    is.function(f)
> >    # [1] TRUE
> >
> >    f@name
> >    # [1] "square"
> >    f(11)
> >    # [1] 121
> >
> > Hope this helps,
> >
> > H.

______________________________________________
[hidden email] 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.