Возможна ли ассоциативность справа налево в R?
Я новичок в R, и я только что обнаружил, что страдаю от Bracket Phobia (см. комментарий в ссылке). Мне нравится способ обозначения magrittr
%>%
, потому что он избегает вложенных скобок в некоторых ситуациях и делает код более читаемым. Я пришел из Mathematica
, где есть очень похожая натурная нотация //
, которая делает то, что делает %>%
. Вот некоторые сравнения R и Mathematica:
#R Notation
c(1.5,-2.3,3.4) %>% round %>% abs %>% sum
#Mathematica Notation
{1.5,-2.3,3.4}//Round//Abs//Total
Пока все хорошо, но, мой вопрос:
Есть ли способ подражать Mathematica @notation, с ассоциативностью справа налево в R
?
Вот как это работает в Mathematica, чтобы решить тот же код выше:
[email protected]@[email protected]{1.5,-2.3,3.4}
В Mathematica он также может быть записан как:
Total[Abs[Round[{1.5,-2.3,3.4}]]]
как и в R
, это будет:
sum(abs(round(c(1.5,-2.3,3.4))))
Но было бы намного чище (и прохладно) иметь в R
что-то вроде этого:
[email protected]@[email protected](1.5,-2.3,3.4)
PS: Я знаю, что @
используется в классах S4, и это не очень хорошая идея. Это просто иллюстративное сравнение.
Ответы
Ответ 1
Для этой цели был разработан и создан пакет backpipe. Он обеспечивает оператора обратной связи (справа налево) для magrittr, pipeR и вообще для любого оператора прямой трубы. backpipe можно найти на github и CRAN.
library(magrittr) # or library(pipeR)
library(backpipe)
x <- c(1.5,-2.3,3.4)
sum %<% abs %<% round %<% x
all.equal( # TRUE
x %>% round %>% abs %>% sum,
sum %<% abs %<% round %<% x
)
backpipe также не ограничена дополнительными параметрами, как в случае с решением @BenBolker. Это, например, работает с backpipe:
mean(na.rm=TRUE) %<% c(1:3,NA)
См. также обсуждение проблемы magrittr github, которая обсуждает это.
Ответ 2
Я вообще не тестировал/не думал об этом, но определение состава функции с помощью оператора (как показано ниже), похоже, работает в нескольких тестовых случаях:
library(magrittr)
## operator defined as "left-pointing arrow" at the
## suggestion of @ClausWilke:
"%<%" <- function(x,y) { if (is(y,"function"))
function(z) x(y(z))
else x(y) }
x <- c(1.5,-2.3,3.4)
all.equal(x %>% round %>% abs %>% sum,
sum %<% abs %<% round %<% x)
x <- rnorm(1000)
all.equal(x %>% round %>% abs %>% sum,
sum %<% abs %<% round %<% x)
Синтаксис не так хорош, как возможность использовать один символ (например, @
) для оператора композиции, но даже если вы можете найти неиспользуемый (все очевидные [[email protected]#$%^&*~|]
приняты и маскирование их было бы ужасной идеей) существует ограничение парсера: пользовательские двоичные операторы в R должны иметь вид %?%
.
Ответ 3
Как насчет использования compose
из пакета hadley purrr
?
compose(sum,abs,round,c)(1.5,-2.3,3.4)