From ||one| @end|ng |rom r@tud|o@com  Mon Oct  7 21:14:21 2019
From: ||one| @end|ng |rom r@tud|o@com (Lionel Henry)
Date: Mon, 7 Oct 2019 21:14:21 +0200
Subject: [Rd] [External] Re:  should base R have a piping operator ?
In-Reply-To: <alpine.DEB.2.21.1910071052330.14507@luke-Latitude-7480>
References: <CAEKh8uidcEWA4tzmkpQxpF=q7r93qjf-HtiWLfbT91TFGOSzFQ@mail.gmail.com>
 <CAGpovd2jxxWBUxPhMAR6ZPw1+UQzK7BzJVtps10cMBSp=EUdHQ@mail.gmail.com>
 <CALEXWq0ZvGeTbeq-AeYTSTcTwR-TR+gGczqQhWupzB2h0wa+zg@mail.gmail.com>
 <CAGpovd29V3rXSyB_SMBnbKfb3dzAFPF66ck9iU6XPB_+bS+8WQ@mail.gmail.com>
 <CAEKh8ugr0FNryRVmM64pBPxjP=4xLrC0T2OsUD27mSASAyHpVQ@mail.gmail.com>
 <CAD4oTHHgSUr5TfLaTHxAM94E-Sqw9bW6gON7KdW324VEr524Lw@mail.gmail.com>
 <95648642-FCC6-49BE-93D9-8872172946E6@rstudio.com>
 <alpine.DEB.2.21.1910071001350.14507@luke-Latitude-7480>
 <ABABA4EA-88E4-4E22-B256-214050E8720A@rstudio.com>
 <alpine.DEB.2.21.1910071052330.14507@luke-Latitude-7480>
Message-ID: <5B3D10F5-9E85-463E-933D-A125843E2B3F@rstudio.com>

On 7 Oct 2019, at 18:17, Tierney, Luke <luke-tierney at uiowa.edu> wrote:

> Here is a stylized example:

The previous value of the binding should only be restored if it
existed:

g <- function(x, y) {
  rlang::scoped_bindings(xx = x, .env = parent.frame())
  y
  get("xx") + 10
}

# Good
g(1, 2)
#> [1] 11

# Still good?
g(1, g(1, 2))
#> [1] 11


> If you play these games whether you get the result you want, or an
> obvious error, or just the wrong answer depends on argument evaluation
> order and the like.

I think the surprises are limited because the pattern has stack-like
semantics. We get in a new context where `.` gains a new meaning, and
when we exit the previous meaning is restored.

One example where this could lead to unexpected behaviour is trying to
capture the value of the placeholder in a closure:

f <- function(x) {
  x %>% {
    identity(function() .)
  }
}

# This makes sense:
f("A")()
#> Error: object '.' not found

# This doesn't:
"B" %>% { f("A")() }
#> [1] "B"


> Not to mention that you would be telling users they are not allowed
> to use '.' as a variable name for their own purposes or you would be
> polluting their environment with some other artificial symbol that
> they would see in debugging.

That's a good point. Debugging allows to move up the call stack before
the context is exited, so you'd see the last value of `.` in examples
of nested pipes like `foo %>% bar( f %>% g() )`. That could be confusing.


> Anything going in base needs to worry even about artificial cases.
> Yes, there are things in base that don't meet that standard. No, that
> is not a reason to add more.

Agreed. What I meant by artificial cases is functions making
questionable assumptions after peeking into foreign contexts etc.

I'm worried about what happens with important language constructs like
`<-` and `return()` when code is evaluated in a local context. That
said, I think binding pipe values to `.` is more important than these
particular semantics because the placeholder is an obvious binding to
inspect while debug-stepping through a pipeline. So evaluating in a
child is probably preferable to giving up the placeholder altogether.

Best,
Lionel



[Rd] [External] Re: should base R have a piping operator ?
Lionel Henry