Type: Package
Title: Manipulate Virtual Functions
Version: 1.0
Depends: R (≥ 4.2.0)
Suggests: testthat, knitr, rmarkdown, onion
Maintainer: Robin K. S. Hankin <hankin.robin@gmail.com>
Description: If f <- function(x){x^2} and g <- function(x){x+1} it is a constant source of annoyance that "f+g" is not defined. Package 'vfunc' allows you to do this, and we have (f+g)(2) returning 5. The other arithmetic operators are similarly implemented. A wide class of coding bugs is eliminated.
License: GPL-2
Imports: methods
VignetteBuilder: knitr
NeedsCompilation: no
Packaged: 2025-07-25 10:18:52 UTC; rhankin
Author: Robin K. S. Hankin ORCID iD [aut, cre]
Repository: CRAN
Date/Publication: 2025-07-28 18:50:02 UTC

Manipulate Virtual Functions

Description

If f <- function(x){x^2} and g <- function(x){x+1} it is a constant source of annoyance to me that “f+g” is not defined. Package vfunc allows you to do this.

Details

The package defines a single S4 class, vf. This has a single slot, .Data, of type function which means that vf objects inherit much of the behaviour of functions, but for which new methods (such as the Arith group of S4 generics) may be defined.

Documentation Index

Index of help topics:

Compare-methods         'Compare' methods for 'vf' objects
Math                    Math group generic functions in the 'vfunc'
                        package: trig, exponential, log, etc.
Math-methods            Methods for Function 'Math', 'Arith' in the
                        'vfunc' package
as.vf                   Coerce functions to a virtual function.
pow                     Iterated functions; functional powers
vf-class                Class '"vf"'
vfunc-package           Manipulate Virtual Functions

Author(s)

Robin K. S. Hankin [aut, cre] (ORCID: <https://orcid.org/0000-0001-5982-0415>)

Maintainer: Robin K. S. Hankin <hankin.robin@gmail.com>

Examples

f <- as.vf(function(x){x^2})

f + Sin

as.function(f*Sin + Exp)(1:4)

Compare methods for vf objects

Description

Wouldn't it be nice to say (f > g)(x) rather than the terrible, tedious and error-prone f(x) > g(x)? Well, now you can!

Methods

signature(e1 = "ANY", e2 = "vf")
signature(e1 = "function", e2 = "vf")
signature(e1 = "vf", e2 = "ANY")
signature(e1 = "vf", e2 = "function")
signature(e1 = "vf", e2 = "vf")

Examples

x <- seq(from=0, to=2*pi, len=100)
(Sin > Cos*Tan)(x)

Math group generic functions in the vfunc package: trig, exponential, log, etc.

Description

The S4 Math group contains 35 functions including sin(), log(), etc. The vfunc equivalents are capitalized, as in Sin(), Log(), etc.

Usage

Abs(x)
Sign(x)
Sqrt(x)
Ceiling(x)
Floor(x)
Trunc(x)
Cummax(x)
Cummin(x)
Cumprod(x)
Cumsum(x)
Log(x)
Log10(x)
Log2(x)
Log1p(x)
Acos(x)
Acosh(x)
Asin(x)
Asinh(x)
Atan(x)
Atanh(x)
Exp(x)
Expm1(x)
Cos(x)
Cosh(x)
Cospi(x)
Sin(x)
Sinh(x)
Sinpi(x)
Tan(x)
Tanh(x)
Tanpi(x)
Gamma(x)
Lgamma(x)
Digamma(x)
Trigamma(x)

Arguments

x

Generally take a single argument of class numeric, function, or vf

Details

The reason for this rather untransparent device is that primitive functions such as sin() behave somewhat differently from other functions. We have:

Sin <- as.vf(function(x){sin(x)})
setMethod("sin", "vf", function(x){as.vf(function(o){Sin(x(o))})})

We define Sin() to be an object of class vf; the call to setMethod() ensures that Sin(f) operates as intended.

Value

Given a numeric, return a numeric; given a vf, return a vf

Note

Note that “sin <- as.vf(sin)” does not work as desired, giving a runtime error; trying to get round this with things like “sin <- as.vf(function(x)sin)” and similar means that “sin(3)” does not work.

There is no way to inform all vf objects that, if used as a function with an argument of a primitive such as sin, to return another vf object—and not to try and evaluate “f(sin)”, which fails:

f <- as.vf(function(x){x^2 + 1})
f(Sin)
#> An object of class "vf"
#> function (...) 
#> {
#>     e1(...) + e2
#> }
#> <bytecode: 0x6065e7c8a900>
#> <environment: 0x6065e7c8a548>
f(sin)
#> Error in x^2: non-numeric argument to binary operator

Above, we see f(sin) returning an error (it tries to evaluate “sin^2 + 1”). Observe that “Sin^2 + 1” is perfectly OK, for Sin is a virtual function.

Author(s)

Robin K. S. Hankin

Examples


Sin + Exp

c((Sin + Exp)(.02232) ,sin(0.02232) +  exp(0.02232))

Methods for Function Math, Arith in the vfunc package

Description

Various S4 methods to work with vf objects. Comparison methods are documented at Compare-methods.


Coerce functions to a virtual function.

Description

Coerce objects to a virtual function. Numeric or complex arguments are coerced to a constant function.

Usage

as.vf(x)

Arguments

x

Generally, a function or numeric

Value

Returns an object of class vf.

Note

It is rarely necessary to coerce objects such as vectors or matrices to class vf because the Arith methods operate on objects of class ANY directly.

Author(s)

Robin K. S. Hankin

Examples

as.vf(\(x)x^2)
Sin + as.vf(\(p){p^3})

as.vf(1:10)(1e99)


Iterated functions; functional powers

Description

Given a function f\colon X\longrightarrow X, we define

f^0 = \mathrm{id_X}

f^{n+1} = f\circ f^n=f^n\circ f,\qquad n\geqslant 0

This gives us f^{n+m}=f^n\circ f^m and \left(f^m\right)^n=f^{mn}, which motivates the notation. For example, \sin^3=\sin\circ\sin\circ\sin, so \sin^3(x)=\sin(\sin(\sin x)).

The operator is well-defined due to the power associativity of function composition.

Usage

pow(x, n)

Arguments

x

Object of class vf

n

Non-negative integer

Value

Returns an object of class vf

Note

There are possibly more efficient methods requiring fewer compositions, e.g. pow(f,9) (which would require 8 function compositions) could be evaluated by pow(pow(f,3),3) (which requires only four). But I am not sure that this would actually be any faster, and I have not got round to thinking about it yet.

Also, package idiom for the caret “^” is reserved for arithmetic exponentiation [so, for example, (f^3)(x) == f(x)*f(x)*f(x)]. I believe this is sub-optimal but was unable to overload the caret to implement functional iteration.

Author(s)

Robin K. S. Hankin

Examples


pow(Sin,5)
Sin^5

f <- as.vf(function(x){x^2+1})

pow(f + Sin,4)
pow(f + Sin,4)(2)

Class "vf"

Description

Class vf stands for “virtual function”

Objects from the Class

Objects can be created by calls of the form new("vf", ...).

Slots

.Data:

Object of class "function"

Methods

Arith

signature(e1 = "function", e2 = "vf"): ...

Arith

signature(e1 = "ANY", e2 = "vf"): ...

Arith

signature(e1 = "vf", e2 = "function"): ...

Arith

signature(e1 = "vf", e2 = "missing"): ...

Arith

signature(e1 = "vf", e2 = "ANY"): ...

Arith

signature(e1 = "vf", e2 = "vf"): ...

as.function

signature(x = "vf"): ...

as.vf

signature(x = "vf"): ...

coerce

signature(from = "function", to = "vf"): ...

coerce

signature(from = "ANY", to = "vf"): ...

coerce

signature(from = "vf", to = "function"): ...

Compare

signature(e1 = "function", e2 = "vf"): ...

Compare

signature(e1 = "ANY", e2 = "vf"): ...

Compare

signature(e1 = "vf", e2 = "function"): ...

Compare

signature(e1 = "vf", e2 = "ANY"): ...

Compare

signature(e1 = "vf", e2 = "vf"): ...

Math

signature(x = "vf"): ...

Author(s)

Robin K. S. Hankin

Examples

showClass("vf")