HenrikBengtsson / R.rsp

:page_facing_up: R package: Dynamic generation of scientific reports
https://henrikbengtsson.github.io/R.rsp/
31 stars 6 forks source link

Usage of R.rsp with magrittr? #23

Open AndreMikulec opened 7 years ago

AndreMikulec commented 7 years ago

How would I write/escape the R magrittr function %>% ( if possible ) inside R.rsp?

For example

library(R.rsp)
library(magrittr)
rstring('<%  rnorm(5) %>% print %>')

Note: I can not alias i.e. :

Funct <- magrittr:`%>%` 

The way magrittr is written, Funct would not work.

AndreMikulec commented 7 years ago

For example, output resulting from the use of magritter and R.rsp is the following.

> library(R.rsp)
R.rsp v0.40.0 (2016-12-05) successfully loaded. See ?R.rsp for help.

Attaching package: 'R.rsp'

The following objects are masked from 'package:base':

    parse, write

> library(magrittr)
> rstring('<%  rnorm(5) %>% print %>')
[1] "% print %>"

The result is not correct.

In contrast, output resulting from the use of magritter alone is the following.

> library(magrittr)
> rnorm(5) %>% print
[1] -0.5036753 -2.3572792  0.9902699  0.1383998  0.8297871

The result is correct.

> sessionInfo()
R version 3.3.2 (2016-10-31)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 10586)

locale:
[1] LC_COLLATE=English_United States.1252
[2] LC_CTYPE=English_United States.1252
[3] LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C
[5] LC_TIME=English_United States.1252

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base

other attached packages:
[1] R.oo_1.21.0       R.methodsS3_1.7.1 magrittr_1.5      R.rsp_0.40.0

loaded via a namespace (and not attached):
[1] tools_3.3.2    digest_0.6.11  R.cache_0.12.0 R.utils_2.5.0
HenrikBengtsson commented 7 years ago

Thanks for this and sorry for the radio silence. I meant to reply to this but it kept slipping away.

Although it's a critical limitation, I don't have a quick fix for this, but please see my thoughts below.

The problem

I am aware of this problem and it's been a long-term goal to workaround it for quite a while. Basically, the main problem is that RSP uses tag %> that can also be the start of an R infix operator, e.g. %>% but also %>yada yada yada%. For example,

> `%>yada yada yada%` <- function(lhs, rhs) list(lhs = lhs, rhs = rhs)
> 123 %>yada yada yada% 456
$lhs
[1] 123

$rhs
[1] 456

Non-working workaround

The quick workaround for a user can often be (as you suggest) to "rename" the conflicting infix operator. However, this does not work with operators that use non-standard evaluation (NSE) such as magrittr::`%>%`.

Solutions (all require a modification of RSP)

In short, in order to solve this, the RSP parser has to resolve these conflicts / ambiguities. Here are some idea I have had for allowing %>% inside RSP constructs such as

Hello <% cat("world") %>!  Here are the data:
<% data %>% print %>

Idea 1: Don't allow % after an RSP closing tag %>.

One could restrict the RSP syntax such that % is not allowed immediately after an RSP construct. This would prevent RSP parse parse %>% as %> + "%", which it does now. Instead, this would always be parsed as the R infix operator %>%. The problem is, it might be that someone wants to do "Inflation was <%= 52 %>% last year". As workaround on top of this workaround, one could imagine "Inflation was <%= 52 %[]>% last year" where [] is an ending RSP option (currently not supported).

It feels like approach is rather ad hoc and will only target %>% crossing the fingers that the risk for other infix %> ... % operators to appear is small. More over, RSP was actually written to work in "any" language, not just R, meaning this fix would be a fix just for R.

Idea 2: Alternative RSP construct as a fallback

In addition to current <% ... %> syntax, one could support <%%% ... %%%> to mean the same thing. This would

Hello <% cat("world") %>!  Here are the data:
<%%% data %>% print %%%>

I think this would be non-ambigous because %%%>% is not valid syntax in R.

However, ... unfortunately, <%% ... %%> is already used to escape RSP constructs, which causes <%%% ... %%%> to be interpreted the same way;

> rcat("A random integer in [1,100]: <%%%=sample(1:100, size=1)%%%>\n")
A random integer in [1,100]: <%%=sample(1:100, size=1)%%>

This calls for an alternative "alternative" RSP construct. Maybe <%! ... !%>, e.g.

Hello <% cat("world") %>!  Here are the data:
<%! data %>% print !%>

Another rule could be that any symbol following <% can be used and if it that same symbol exists just before %> that defines the RSP construct. Not sure what complexity this would add to the RSP parser.

Idea 3: Move away from <% ... %> to a "safer" syntax

For a user using lots of magrittr pipes, their RSP code would contain lots of <%! ... !%> which becomes quite meaty. They original problem is the use of %. An alternative would be to use another symbol that % in <% ... %>. There are many options:

Yet further alternatives are:

However, there are plenty of "macro" languages out there that already uses that construct, so that would be confusing.

So, as you see, there are multiple paths here of which some a fairly "quick" and others requires bigger commitments. I simply have to think more about this, but the most likely "fix" is that I add support for something like <%! ... !%>.

Always happy for suggestions.

AndreMikulec commented 7 years ago

Thanks. Andre Mikulec

thomsonn commented 7 years ago

The GetoptLong package provides an argument code.pattern = qq.options("code.pattern") for its qq() function, which is set to "@\\{CODE\\)" by default. Perhaps a similar argument could be provided for RSP functions, such as pattern = GetOption("R.rsp.pattern") with default "<% ... %>". The <%! ... !%> syntax could be documented as a magrittr-friendly alternative.