Why doesn't the infix function := from tidyverse need the % around it? - r

If one is to create their own infix function, it needs to have the form %fun_name%. Why isn't that the case with := of tidyverse? Also, the same with the operator !!, also form tidyverse.

These operators are not functions. They are only meaningful when supplied as part of arguments to functions that use non-standard evaluation and know how to handle them. The R interpreter does not treat these operators as functions and you cannot call them directly. If you call !!something outside of a quasiquoted argument the interpreter treats it as:
!(!(something))
If you call := outside of a quasiquoted argument you get an exception.
As an aside, you can always overload base infix functions or define new S3 methods for them without needing %. The interpreter always treats these symbols as infix functions and they are not reserved. e.g:
> `+` <- function(x,y) x - y
> 1 + 2
[1] -1
`/.foo` <- function(x, y) x * y
> my_object <- structure(1, class = "foo")
> 1 / 2
[1] 0.5
> my_object / 2
[1] 2
attr(,"class")
[1] "foo"
For some reason R does allows the definition of a function := and will evaluate the resulting function as an infix function. However, this is not how rlang or data.table actually implement :=. Other symbols that begin with :, e.g. :+, or end with =, e.g. !=, are not interpreted as infix functions; I am not sure why this should be the case, as the symbol := is not used in base R. The interpreter's unique ability to evaluate it as an infix function is unexpected, at least to me.
> `:=` <- function(x,y) x - y
> 5 := 2
[1] 3

Related

What does '[' (left square bracket) do when treated as a function? [duplicate]

I've seen the function lapply used in R to extract elements from matrices that exist in a list of matrices.
E.g. I have a list of 3 (2x2) matrices, and I want to extract element [1,2] from each of those 3 matrices.
The code: list1 = lapply(mylist, '[', 1,2) works just fine. It returns a list with those 3 elements.
I am trying to research what this is exactly doing. Google hasn't helped and using ?'[' in the R help isn't too explanatory. I don't see how '[' is a function in R, so the code is not intuitive.
The square brackets are in fact a function whose first argument is the object being subsetted. Subsequent arguments are the index to that subset.
# For example, if M is a matrix
M[1, 2] # extracts the element at row 1, col 2
# is the same as
`[`(M, 1, 2)
# Try them!
Now, Have a look at the arguments to lapply:
args(lapply)
# function (X, FUN, ...)
Everything represented in those dots gets passed on to the function FUN as arguments.
Thus, when FUN="[", the first argument to "[" is the current element of the list (being iterated over), ie, the object being subsetted. While the subsequent arguments are the indexes to "["
Operators in R are just functions.
These are equivalent:
> x <- list(a=1,b=2)
> x[1]
$a
[1] 1
> `[`(x,1)
$a
[1] 1
The backticks are necessary only to prevent interpretation by the parser (e.g. to tell it it's a function name not to start interpreting the [ prematurely).
Being a function, it follows the same object-oriented rules (in this case, S3) as everything else.
> methods(`[`)
[1] [.acf* [.arrow* [.AsIs [.bibentry* [.cluster* [.data.frame [.data.table*
[8] [.Date [.difftime [.envlist* [.factor [.formula* [.fractions* [.getAnywhere*
[15] [.gList* [.gpar* [.gtable* [.hexmode [.idf* [.indexed* [.insensitive*
[22] [.ITime* [.listof [.noquote [.numeric_version [.octmode [.pdf_doc* [.person*
[29] [.POSIXct [.POSIXlt [.quoted* [.raster* [.roman* [.shingle* [.simple.list
[36] [.split* [.terms* [.trellis* [.ts* [.tskernel* [.uneval* [.unit*
[43] [.unit.arithmetic* [.unit.list* [.vpPath*
Non-visible functions are asterisked
+, =, etc. and other operators all work this way as well.

Use of lapply after splitting a string in R [duplicate]

I've seen the function lapply used in R to extract elements from matrices that exist in a list of matrices.
E.g. I have a list of 3 (2x2) matrices, and I want to extract element [1,2] from each of those 3 matrices.
The code: list1 = lapply(mylist, '[', 1,2) works just fine. It returns a list with those 3 elements.
I am trying to research what this is exactly doing. Google hasn't helped and using ?'[' in the R help isn't too explanatory. I don't see how '[' is a function in R, so the code is not intuitive.
The square brackets are in fact a function whose first argument is the object being subsetted. Subsequent arguments are the index to that subset.
# For example, if M is a matrix
M[1, 2] # extracts the element at row 1, col 2
# is the same as
`[`(M, 1, 2)
# Try them!
Now, Have a look at the arguments to lapply:
args(lapply)
# function (X, FUN, ...)
Everything represented in those dots gets passed on to the function FUN as arguments.
Thus, when FUN="[", the first argument to "[" is the current element of the list (being iterated over), ie, the object being subsetted. While the subsequent arguments are the indexes to "["
Operators in R are just functions.
These are equivalent:
> x <- list(a=1,b=2)
> x[1]
$a
[1] 1
> `[`(x,1)
$a
[1] 1
The backticks are necessary only to prevent interpretation by the parser (e.g. to tell it it's a function name not to start interpreting the [ prematurely).
Being a function, it follows the same object-oriented rules (in this case, S3) as everything else.
> methods(`[`)
[1] [.acf* [.arrow* [.AsIs [.bibentry* [.cluster* [.data.frame [.data.table*
[8] [.Date [.difftime [.envlist* [.factor [.formula* [.fractions* [.getAnywhere*
[15] [.gList* [.gpar* [.gtable* [.hexmode [.idf* [.indexed* [.insensitive*
[22] [.ITime* [.listof [.noquote [.numeric_version [.octmode [.pdf_doc* [.person*
[29] [.POSIXct [.POSIXlt [.quoted* [.raster* [.roman* [.shingle* [.simple.list
[36] [.split* [.terms* [.trellis* [.ts* [.tskernel* [.uneval* [.unit*
[43] [.unit.arithmetic* [.unit.list* [.vpPath*
Non-visible functions are asterisked
+, =, etc. and other operators all work this way as well.

Raise to power in R

This is a beginner's question.
What's the difference between ^ and **?
For example:
2 ^ 10
[1] 1024
2 ** 10
[1] 1024
Is there a function such as power(x,y)?
1: No difference. It is kept around to allow old S-code to continue to function. This is documented a "Note" in ?Math?Arithmetic
2: Yes: But you already know it:
`^`(x,y)
#[1] 1024
In R the mathematical operators are really functions that the parser takes care of rearranging arguments and function names for you to simulate ordinary mathematical infix notation. Also documented at ?Math.
Edit: Let me add that knowing how R handles infix operators (i.e. two argument functions) is very important in understanding the use of the foundational infix "[[" and "["-functions as (functional) second arguments to lapply and sapply:
> sapply( list( list(1,2,3), list(4,3,6) ), "[[", 1)
[1] 1 4
> firsts <- function(lis) sapply(lis, "[[", 1)
> firsts( list( list(1,2,3), list(4,3,6) ) )
[1] 1 4

What is the reason to add quotation marks around R function names?

What is the difference between defining a function called myfunction as
"myfunction" <- function(<arguments>){<body>}
and
myfunction <- function(<arguments>){<body>}
furthermore: what about the comments which are usually placed around such a function, i.e.
#myfunction{{{
"myfunction" <- function(<arguments>){<body>}
#}}}
are they just for documentation or are they really necessary (if so for what)?
EDIT: I have been asked for an example where comments like
#myfunction{{{
are used: For example here https://github.com/cran/quantmod/blob/master/R/getSymbols.R
The quoted version allows otherwise illegal function names:
> "my function" <- function() NULL
> "my function"()
NULL
Note that most people use backticks to make it clear they are referring to a name rather than a character string. This allows you to do some really odd things as alluded to in ?assign:
> a <- 1:3
> "a[1]" <- 55
> a[1]
[1] 1
> "a[1]"
[1] "a[1]"
> `a[1]`
[1] 55

R - Get formals from call object

How can I get the formals (arguments) from a call object? formals() only seems to work with functions.
Well, a call does not have formals, only actual arguments... The difference being that a function like foo <- function(x, y, ..., z=42) can be called with actual arguments like foo(42, bar=13).
...But getting the arguments can be done like this:
a <- call('foo', a=42, 13)
as.list(a)[-1]
#$a
#[1] 42
#
#[[2]]
#[1] 13
...on the other hand, you can usually (not always) find the actual function and find the formals for it:
a <- quote(which(letters=='g'))
formals(match.fun(a[[1]]))
#$x
#
#$arr.ind
#[1] FALSE
#
#$useNames
#[1] TRUE
Here you'd need to add some error handling if the function can't be found (as with the call to foo above)...

Resources