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
andasr
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
Finding Overlapping Ranges Between Two Interval Data
Understanding Element Wise Clearing of R's Workspace
How to Order Bars Within All Facets
Split Character Columns and Get Names of Field in String
Best Practice: Should I Try to Change to Utf-8 as Locale or Is It Safe to Leave It as Is
Given Value of Matrix, Getting It's Coordinate
Count Number of Non-Na Values by Group
Sum Object in a Column Between an Interval Defined by Another Column
Get Monthly Means from Dataframe of Several Years of Daily Temps
R, Find Duplicated Rows , Regardless of Order
Convert/Export Googleway Output to Data Frame
Update a Dataset After Putting a New Value in the Dt::Datatable
R Subset with Condition Using %In% or ==. Which One Should Be Used
Different Axis Limits Per Facet in Ggplot2