Why Is := Allowed as an Infix Operator

Why is := allowed as an infix operator?

It is something that the base R parser recognizes and seems to parse as a left assign (at least in terms or order of operations and such). See the C source code for more details.

as.list(parse(text="a:=3")[[1]])
# [[1]]
# `:=`
#
# [[2]]
# a
#
# [[3]]
# [1] 3

As far as I can tell it's undocumented (as far as base R is concerned). But it is a function/operator you can change the behavior of

`:=`<-function(a,b) {a+b}
3 := 7
# [1] 10

As you can see there really isn't anything special about the ":" part itself. It just happens to be the start of a compound token.

Why does `:=` work as an infix operator?

This is because := is, like <- or <<-, defined as LEFT_ASSIGN for the parser of R.

See http://svn.r-project.org/R/trunk/src/main/gram.y

This means that := is a special case and you may as well not expect that any other options are available.

Use explicit namespace with infix operator

Just import the pipe operator, by adding a line like

importFrom(magrittr, "%>%")

in your NAMESPACE file, or if you're using roxygen2, putting

#' @importFrom magrittr %>%

into one of your .R files to do the same thing.

You may or may not want to export it as well. Do export it with a line like

export("%>%")

in your NAMESPACE file or with roxygen2

#' @export
magrittr::`%>%`

if you want your users to use the pipe operator when they are using your package. Don't export it if you only need it to be available internally.

R: conflict between two definitions of (infix) operator: how to specify package?

Adding from @MrFlick's comment:

Unfortunately you can't use namespaces with infix operators in R; the parser just won't recognize that syntax. You need to create an alias as suggested in the answer below. Or create your own version of the operator that does dispatching based on the classes you expect to see.


Just an idea but: how about redefining the infix function's binding. Suppose the one from ggplot2 is the one you are going to use most often in your code:

library(ggplot2)
`%+c%` <- crayon::`%+%`

This way you are correctly namespacing the ggplot2 library and you just use a different binding for the crayon one.

How can I create an infix %between% operator?

You can define infix operators as functions:

`%between%`<-function(x,rng) x>rng[1] & x<rng[2]
1 %between% c(0,3)
# [1] TRUE
1 %between% c(2,3)
# [1] FALSE

As pointed out by @flodel, this operator is vectorized:

1:5 %between% c(1.5,3.5)
# [1] FALSE TRUE TRUE FALSE FALSE

Explanation of the infix data constructor operator

Full name of type is Data.List.NonEmpty.

You can find details here

There is site https://hoogle.haskell.org/ which is good starting point in searching functions, types, etc. in haskell libraries.

EDIT: If you confuse with what :| mean then here some explanation.

In haskell you can define custom operators like ., $, <*>. Same way you can create infix constructor with custom "names".

So you can define one yourself:

data MyType = Integer :++ Integer

and use them as

someVal :: MyType
someVal = 1 :++ 2

or

foo :: MyType -> Integer
foo (a :++ b) = a

Note that it have to start with : (Thanks to @Ben)

What are the legal names for infix operators?

It's determined by the first symbol of the operator. From the manual:

infix-symbol    ::= (= ∣  < ∣  > ∣  @ ∣  ^ ∣  | ∣  & ∣  + ∣  - ∣  * ∣  / ∣  $ ∣  %) { operator-char }  
∣ # { operator-char }+

prefix-symbol ::= ! { operator-char }
∣ (? ∣ ~) { operator-char }+

operator-char ::= ! ∣ $ ∣ % ∣ & ∣ * ∣ + ∣ - ∣ . ∣ / ∣ : ∣ < ∣ = ∣ > ∣ ? ∣ @ ∣ ^ ∣ | ∣ ~

So, for example, a custom operator defined like this:

let (@?) a b = ...

Would be considered an infix operator since it starts with @, while

let (?@) a b = ...

is a prefix operator because it starts with ?.

There are some additions and exceptions to this, however, described in the manual here:

  • mod, land, lor, lxor, lsl, lsr and asr are keywords treated as infix operators (e.g. 2 mod 4).

  • - and -. can be interpreted as either infix or prefix operators. When prefix thay are translated to ~- and ~-. respectively.

  • && and || are also treated specially, for reasons. See the comments by @octachron below for a bit more of an explanation.

Lastly, you might also want to consider precedence and associativity, which is listed in the table near the top, before the first section here

R: How to best import infix operators like % % into my package?

I'm not sure if there's a single best practice in this case.
Using @importFrom to update the NAMESPACE file is indeed to be a package-wide directive,
but I've never come across a package that had problems with that,
or reasons to avoid it.
You can annotate several functions with the same @importFrom directive if you like,
denoting which functions use which imports,
and it won't cause any conflicts;
it's entirely up to you though,
a single one would suffice.
Using @import might be frowned upon,
but I think it really depends on which package you import.

From your question I gather you use :: explicitly
(which I would personally say is good practice),
and then you don't even need to alter the NAMESPACE.
For most cases that would be just fine,
though there can be very special cases that usually need to be considered individually.
These special cases, at least in my experience, are usually related with S4 generics.

Take for instance the base::rowSums function:
it is not a generic function in base,
but if the Matrix package is attached,
rowSums is "transformed" into an S4 generic,
but the generic is not in the base package.
Why that's the case is beyond the scope of this answer
(see ?Methods_for_Nongenerics for more information),
but it means that if your package uses the notation base::rowSums,
it would not dispatch to methods from Matrix.
The only way to support both cases
(i.e. when Matrix is not used by the user and when it is)
would be to use rowSums without base::.

Now, regarding infix operators,
if you wanted to use ::,
you'd need something like base::`%in%`("a", c("a", "b")),
which essentially entails using it as a function and losing the infix syntax,
something you probably don't want.

So unless you have very specific reasons to avoid one or the other,
just use whatever notation you prefer.
I'd personally stick to :: as much as possible,
but would never use it for infix operators.



Related Topics



Leave a reply



Submit