In R user-defined operators are allowed, but it seems that only % %
like operators are accepted. Is it possible to walk around this restriction to define operators like, for example, >>
, or something that is not like % %
?
The operator must be a real operator so that we can use it like 1 >> 2
and do not have to use it like ">>"(1,2)
.
A user-defined operator is a top-level schema object. In many ways, user-defined operators act like the built-in operators such as <, >, and =; for instance, they can be invoked in all the same situations. They contribute to ease of use by simplifying SQL statements, making them shorter and more readable. User-defined operators are:
If Contains () is used in Example 9-7, the operator invocation Contains (resume, 'Oracle') causes Oracle to execute the function text.contains (resume, 'Oracle') because the signature of the function matches the data types of the operator arguments.
Example 9-1 creates the operator Contains (), binding it to functions that provide implementations in the Text and Spatial domains. To drop an operator and all its bindings, specify its name with the DROP OPERATOR statement. Example 9-2 drops the operator Contains ().
When an operator is invoked, Oracle evaluates the operator by executing a function bound to it. When several functions are bound to the operator, Oracle executes the function whose argument data types match those of the invocation (after any implicit type conversions).
No. R only allows you to
`+`
or, indeed, `<-`
), and%…%
.These are the rules we have to play by. However, inside these rules all is fair game. For instance, we can redefine `+`
for character strings to perform concatenation, without destroying its normal meaning (addition):
`+`
# function (e1, e2) .Primitive("+")
This is the old definition, which we want to preserve for numbers:
`+.default` = .Primitive('+')
`+.character` = paste0`1
`+` = function (e1, e2) UseMethod('+')
1 + 2
# [1] 3
'hello' + 'world'
# [1] "helloworld"
This exploits the S3 class system in R to make `+`
fully generic on the type of its first argument.
The list of operators that can thus be redefined is quite eclectic. At first count, it contains the following operators:
+
,-
,*
,/
,^
,&
,|
,:
,::
,:::
,$
,=
,<-
,<<-
,==
,<
,<=
,>
,>=
,!=
,~
,&&
,||
,!
,?
,@
,:=
,(
,{
,[
,[[
(From the {modules} source code.)
In this list, one particular operator is noteworthy: `:=`
is an overridable operator (and {data.table} for example uses it) but unlike most the other operators in this list it has no default implementation.
Similarly, you can define assignment versions of pretty much every operator, not just those with a predefined assignment (such as `[<-`
). For example, `(<-`
and `{<-`
are also missing a default implementation. This is why the following code fails:
a = 1
(a) = 2
# Error in (a) = 2 : could not find function "(<-"
{a} = 3
# Error in { : could not find function "{<-"
But the code can be made to work by defining the operators:
`(<-` = `{<-` = function (x, value) value
The same works for every function, including almost all operators1, and even control structures (see the comments below this answer).
By contrast, `**`
isn’t a real operator: it’s a syntactic alias for `^`
. Users can define their own `**`
function but it can’t be called via the code a ** b
so it’s not an overridable operator (except via overriding `^`
).
In the same vein, you can override ->
(only) by redefining <-
. This seems like it would rarely make sense — but at least one good example of this exists, to define less verbose lambdas:
> sapply(1 : 4, x -> 2 * x)
[1] 2 4 6 8
Implementation as a gist
1 The only exception are the assignment operators: You cannot change the meaning of a <- b <- c
by redefining `<-<-`
(and the same for `=<-`
, `<<-`
and `:=`
), due to the language’s operator precedence and associativity rules. However, the following code invokes both `(<-`
and `<-<-`
, and fails if either of these is not defined:
(a <- b) <- c
Messed up.
You can do things like this, but you may want to assign these objects to a new environment to be safe.
> "^" <- function(x, y) `-`(x, y) ## subtract y from x
> 5 ^ 3
# [1] 2
> "?" <- function(x, y) sum(x, y) ## add x and y
> 5 ? 5
# [1] 10
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With