是否可以在没有%%的情况下定义运算符?

时间:2014-07-11 12:02:34

标签: r operator-keyword

在R中允许使用用户定义的运算符,但似乎只接受% %个类似的运算符。是否可以绕过此限制来定义运算符,例如>>或某些不像% %的运算符?

运算符必须是真正的运算符,以便我们可以像1 >> 2一样使用它,而不必像">>"(1,2)那样使用它。

2 个答案:

答案 0 :(得分:17)

没有。 R只允许你

  1. 重新定义现有运营商(例如`+`或实际上`<-`)和
  2. 通过使用%…%
  3. 包围新的中缀运算符来定义它们

    这些是我们必须遵守的规则。但是,在这些规则中,一切都是公平的。例如,我们可以为字符串重新定义`+`以执行连接,而不会破坏其正常含义(添加):

    `+`
    # function (e1, e2)  .Primitive("+")
    

    这是旧的定义,我们希望为数字保留:

    `+.default` = .Primitive('+')
    `+.character` = paste0`1
    `+` = function (e1, e2) UseMethod('+')
    1 + 2
    # [1] 3
    'hello' + 'world'
    # [1] "helloworld"
    

    这利用了R中的S3类系统,使`+`在其第一个参数的类型上完全通用。

    可以重新定义的运算符列表非常折衷。首先,它包含以下运算符:

      

    +-*/^&|::::::$=<-<<-==<,{ {1}},<=>>=!=~&&||,{{1 }},!?@:=({

         

    (来自{modules} source code。)

    在此列表中,一个特定的运算符值得注意:[是一个可覆盖的运算符(例如{data.table}使用它)但与此列表中的大多数其他运算符不同,它没有默认实现。< / p>

    同样,您可以定义几乎所有运算符的赋值版本,而不仅仅是具有预定义赋值的赋值版本(例如[[)。例如,`:=``[<-`也缺少默认实现。这就是以下代码失败的原因:

    `(<-`

    但是可以通过定义运算符来使代码工作:

    `{<-`

    每个函数都有相同的功能,包括几乎所有的运算符 1 ,甚至是控制结构(参见本答案下面的注释)。

    相比之下,a = 1 (a) = 2 # Error in (a) = 2 : could not find function "(<-" {a} = 3 # Error in { : could not find function "{<-" 不是真正的运算符:它是`(<-` = `{<-` = function (x, value) value 的语法别名。用户可以定义自己的`**`函数,但不能通过代码`^`调用它,因此它不是可覆盖的运算符(除了通过覆盖`**`)。

    同样,您可以通过重新定义a ** b来覆盖`^`(仅限)。这似乎很少有意义 - 但至少有一个很好的例子,定义较少冗长的lambdas:

    ->

    Implementation as a gist


    1 唯一的例外是赋值运算符:您不能通过重新定义<-来更改> sapply(1 : 4, x -> 2 * x) [1] 2 4 6 8 的含义(对于a <- b <- c也是如此,{{ 1}}和`<-<-`),由于语言operator precedence and associativity rules。但是,以下代码调用`=<-``<<-`,如果未定义其中任何一个,则会失败:

    `:=`

    搞砸了。

答案 1 :(得分:4)

您可以执行此类操作,但您可能希望将这些对象分配到新环境以确保安全。

> "^" <- 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