Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

`quote()` and `call()`: How to distinguish between both outputs?

Motivation

I am programming a function that takes a call as an input. I notice however that R has two different ways to create calls, either through call() or quote(). My code behaves differently depending on which function was called, so I would like to convert both types of objects to a single one to avoid expanding the code.

Example

Consider the following two objects:

call_obj <- "rnorm(5)" |> call()
quote_obj <- rnorm(5) |> quote()

Note that they print different output in the console:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

> call_obj
`mean()`()
> quote_obj
mean()

Yet, they have the same class, type and mode:

> class(call_obj)
[1] "call"
> class(quote_obj)
[1] "call"
> mode(call_obj)
[1] "call"
> mode(quote_obj)
[1] "call"
> typeof(call_obj)
[1] "language"
> typeof(quote_obj)
[1] "language"
> str(call_obj)
 language `mean()`()
> str(quote_obj)
 language mean()

Distinguish

I have been able to distinguish both objects through two approaches.

The simple one is through length(). Since call_obj seems to always return a length of 1, whereas quote_obj returns a length equal to the number of explicit arguments in the call + 1. This approach fails however if the function is one that can take no explicit arguments and runs only with defaults, such as mean(). Is there a more robust concise alternative? Tried alternatives with grepl and backticks but they do not seem to detect them even if they are visible in the str() print output.

The complicated one is leveraging the fact that call_obj can be converted into quote_obj by

> all.equal(call_obj[[1]] |> as.character() |> str2lang(), quote_obj)
[1] TRUE

whereas the same functions applied to an object that is already a quote, will return FALSE:

> all.equal(quote_obj[[1]] |> as.character() |> str2lang(), quote_obj)
[1] "Modes of target, current: name, call"
[2] "target is a subset of current"   

Bonus Question: What is a concise way to convert a quote_obj so it is equal to a call_obj?


If there’s something very non-R of my approach here and there are more idiomatic approaches please comment it so!

>Solution :

Your example call_obj <- "rnorm(5)" |> call() produces a call to a function named "rnorm(5)" with no argument, not a call to "rnorm" with argument 5. If that’s what you really want, then comparing as.character(call_obj[[1]])) to as.character(quote_obj[[1]]) will show the difference.

If you really want both to be calls to rnorm(5), then you need to use

call_obj <- "rnorm" |> call(5)

and the result will be identical to what you get in quote_obj.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading