Re: [Rd] New pipe operator

2020-12-08 Thread Bravington, Mark (Data61, Hobart)
> [Duncan Murdoch responding to...]
> [... Mark Bravington's proposals for placeholders and anonymous functions]
> > x |> foo( _PIPE_)  # placeholder
> > x |> bah( otherarg, _PIPE_)# placeholder
> > x |> { y <- _PIPE_+1; _PIPE_ / y } # anonymous function

> [DM] About your proposal [specifically, the anonymous function bit]:

> I don't find it attractive, but I can see that some people would.  But I
> don't think it's necessary to put it into the base parser.  Other than
> using an illegal name, there doesn't seem to be a reason you couldn't
> write a small function to convert your placeholder proposal to a call to
> a function.  So instead of typing

>   x |> { y <- _PIPE_+1; _PIPE_ / y }

> you would type

>   x |> forpipe({ y <- PIPE_+1; PIPE_ / y })

> I don't think "forpipe" is the right name here.  I proposed a generic
> "as.call" before, but I don't like that one either.  I'm still trying to
> think of a good name, and whether or not it makes sense for it to be
> generic.

Right, yes. Actually that was part of my first email: I had

x |> _ANON_({ y <- _PIPE_+1; _PIPE_ / y })

I deliberately picked otherwise-illegal names, to prevent extrapipular abuse, 
but that's not a big deal. Second email gives that option as well as 
curly-brace version.

It's true that there's no *need* to change the base parser in order to get the 
functionality of your 'forpipe' / my '_ANON_'--- but pipes are really about 
convenience, so "need" becomes quite subjective; perhaps the curly-brace 
version, or something else, is attractive enough to warrant it (I don't know). 
And it seems like the new pipe-aware parser is already having to deal 
differently with expressions inside a pipe vs outside.

However, I was also discussing non-anonymous function calls in pipes, and 
arguing that they should require (or at least be able to use) a reserved-word 
placeholder (PIPE_ or whatever)--- EG

x |> match( LETTERS, _PIPE_) # non-first arg

So that's a separate part of my proposal.

If I was king I actually wouldn't let people do

x |> head

and would force them instead to do 

x |> head( _PIPE_)

but, clearly, I am not.

> But the point is that we don't need to choose just one from all the
> proposed replacements for anonymous function syntax, we can try them out
> and see which ones we like.  We might end up with more than one (like we
> have at least 4 different high level graphics paradigms!), and that's
> not the end of the world.

Good point. Multiple options is no disaster, and experiments are excellent--- 
though once things get embedded in R, it's hard to pull them out... 

However, aren't we limited to experimenting within the confines of the current 
pipe-aware parser? Many of the suggestions on this topic seem to go beyond that 
(including mine). EG I *think*, subject to correction, that

 - you're right that 'forpipe'/'_ANON_' can be implemented to work with the 
current pipe-aware parser
 
 - But, the curly-brace version would require a parser change
 
 - and the use of a reserved-word placeholder also isn't possible as-is
 
If there's some way to try those things out, it would be great.

cheers
Mark


Mark Bravington
CSIRO Marine Lab
Hobart
Australia



From: Duncan Murdoch 
Sent: Wednesday, 9 December 2020 09:28
To: Bravington, Mark (Data61, Hobart); Gabor Grothendieck; Gabriel Becker
Cc: r-devel@r-project.org
Subject: Re: [Rd] New pipe operator

First, one comment:

You're right about the illegality of _PIPE_ as a name, I had
misremembered the rule.

About your proposal:

I don't find it attractive, but I can see that some people would.  But I
don't think it's necessary to put it into the base parser.  Other than
using an illegal name, there doesn't seem to be a reason you couldn't
write a small function to convert your placeholder proposal to a call to
a function.  So instead of typing

  x |> { y <- _PIPE_+1; _PIPE_ / y }

you would type

  x |> forpipe({ y <- PIPE_+1; PIPE_ / y })

I don't think "forpipe" is the right name here.  I proposed a generic
"as.call" before, but I don't like that one either.  I'm still trying to
think of a good name, and whether or not it makes sense for it to be
generic.

But the point is that we don't need to choose just one from all the
proposed replacements for anonymous function syntax, we can try them out
and see which ones we like.  We might end up with more than one (like we
have at least 4 different high level graphics paradigms!), and that's
not the end of the world.

Duncan Murdoch

On 08/12/2020 4:26 p.m., Bravington, Mark (Data61, Hobart) wrote:
>>> On 06/12/2020 8:22 p.m., Bravington, Mark (Data61, Hobart) wrote:
>> (and Duncan Murdoch responded, as below)
>
> It still seems to me that placeholders are viable and unambiguous (only as 
> things in RHS of pipes), and that something like
>
> x |> foo( _PIPE_)
> x |> bah( otherarg, _PIPE_)
> x |> { y <- _PIPE_+1; _PIPE_ / y } # anonymous function
>
> would be a vi

Re: [Rd] Ignore Sites Option For libPaths

2020-12-08 Thread Dirk Eddelbuettel


On 9 December 2020 at 02:00, Dario Strbenac wrote:
| That seems like a straightforward and reasonable thing to do, but:
| 
| ~$ R_LIBS="/tmp" R_LIBS_SITE="/var" Rscript -e 'print(.libPaths())'
| [1] "/dora/nobackup/biostat/Rpackages/v4" 
"/dora/users/course/splus/library/R" 
| [3] "/usr/lib/R/site-library" "/usr/lib/R/library"

Hm. Maybe you have code in RHOME/etc/* or in HOME to set some of these?

The (very detailed) description of what happens when is in help(Startup)
which is a great resource but as dense as they get. My example came from my
Ubuntu 20.04 box where I set nothing apart from not using a ~/R/ path.

Also try "R -q -e 'print(.libPaths())'" with these switches to narrow it down:

  --no-environ  Don't read the site and user environment files
  --no-site-fileDon't read the site-wide Rprofile 
  --no-init-fileDon't read the user R profile

| /tmp and /var exist of course.

Right, I didn't stress that but the choice made it clear.  I still think you
should be able to tune this with just base R.

Cheers, Dirk

-- 
https://dirk.eddelbuettel.com | @eddelbuettel | e...@debian.org

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] Ignore Sites Option For libPaths

2020-12-08 Thread Dario Strbenac
Good day,

That seems like a straightforward and reasonable thing to do, but:

~$ R_LIBS="/tmp" R_LIBS_SITE="/var" Rscript -e 'print(.libPaths())'
[1] "/dora/nobackup/biostat/Rpackages/v4" "/dora/users/course/splus/library/R" 
[3] "/usr/lib/R/site-library" "/usr/lib/R/library"

/tmp and /var exist of course.

--
Dario Strbenac
University of Sydney
Camperdown NSW 2050
Australia
__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] Ignore Sites Option For libPaths

2020-12-08 Thread Gabriel Becker
Of course you can, but the ability to do something via R code and the
ability to do them by wrapping the invocation of R are not similar terms of
convenience, IMO.

I say that as someone who routinely does both type of thing.

~G

On Tue, Dec 8, 2020 at 4:07 PM Dirk Eddelbuettel  wrote:

>
> On 8 December 2020 at 23:00, Dario Strbenac wrote:
> | Could .libPaths gain an option to ignore all values other than the
> user-specified new parameter? Currently, it takes the union of new and
> .Library and .Library.site and there is no way to turn it off.
>
> Are you use? It is constructed from looking at environment variables you
> could set.
>
>   edd@rob:~$ R_LIBS="/tmp" R_LIBS_SITE="/var" Rscript -e
> 'print(.libPaths())'
>   [1] "/tmp"   "/var"   "/usr/lib/R/library"
>   edd@rob:~$
>
> Dirk
>
> --
> https://dirk.eddelbuettel.com | @eddelbuettel | e...@debian.org
>
> __
> R-devel@r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>

[[alternative HTML version deleted]]

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] Ignore Sites Option For libPaths

2020-12-08 Thread Dirk Eddelbuettel


On 8 December 2020 at 23:00, Dario Strbenac wrote:
| Could .libPaths gain an option to ignore all values other than the 
user-specified new parameter? Currently, it takes the union of new and .Library 
and .Library.site and there is no way to turn it off. 

Are you use? It is constructed from looking at environment variables you could 
set.

  edd@rob:~$ R_LIBS="/tmp" R_LIBS_SITE="/var" Rscript -e 'print(.libPaths())'
  [1] "/tmp"   "/var"   "/usr/lib/R/library"
  edd@rob:~$ 

Dirk

-- 
https://dirk.eddelbuettel.com | @eddelbuettel | e...@debian.org

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] Ignore Sites Option For libPaths

2020-12-08 Thread Gabriel Becker
Hi Dario,

My switchr package is designed specifically to do what you're describing,
and does support excluding site libraries. So clearly I agree it would be
useful, but also, it does go against the "concept" of site libraries
somewhat.

I agree it would be a useful addition with the default to including them,
personally. And the patch would be pretty easy to put together. I can put
together a patch and add it to bugzilla as a wishlist item and we'll see
what thoughts are (unless I hear an emphatic no here, in which case I won't
bother, or unless you'd like to take a crack at it yourself).

~G

On Tue, Dec 8, 2020 at 3:00 PM Dario Strbenac 
wrote:

> Good day,
>
> Could .libPaths gain an option to ignore all values other than the
> user-specified new parameter? Currently, it takes the union of new and
> .Library and .Library.site and there is no way to turn it off. For quick
> and convenient troubleshooting that doesn't involve requiring the editing
> of configuration files, it would be nice to be able to run
> .libPaths(.libPaths()[1], ignoreSiteFiles = TRUE) to limit to only one
> folder of R packages.
>
> > .libPaths()
> [1] "/dskh/nobackup/biostat/Rpackages/v4"
> "/usr/users/course/splus/library/R"
> [3] "/usr/lib/R/site-library" "/usr/lib/R/library"
> > .libPaths(.libPaths()[1]) # No option to ignore system-wide folders.
> > .libPaths() # Paths are same as before.
> [1] "/dskh/nobackup/biostat/Rpackages/v4"
> "/usr/users/course/splus/library/R"
> [3] "/usr/lib/R/site-library" "/usr/lib/R/library"
>
> --
> Dario Strbenac
> University of Sydney
> Camperdown NSW 2050
> Australia
> __
> R-devel@r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>

[[alternative HTML version deleted]]

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


[Rd] Ignore Sites Option For libPaths

2020-12-08 Thread Dario Strbenac
Good day,

Could .libPaths gain an option to ignore all values other than the 
user-specified new parameter? Currently, it takes the union of new and .Library 
and .Library.site and there is no way to turn it off. For quick and convenient 
troubleshooting that doesn't involve requiring the editing of configuration 
files, it would be nice to be able to run .libPaths(.libPaths()[1], 
ignoreSiteFiles = TRUE) to limit to only one folder of R packages.

> .libPaths()
[1] "/dskh/nobackup/biostat/Rpackages/v4" "/usr/users/course/splus/library/R"
[3] "/usr/lib/R/site-library" "/usr/lib/R/library"
> .libPaths(.libPaths()[1]) # No option to ignore system-wide folders.
> .libPaths() # Paths are same as before.
[1] "/dskh/nobackup/biostat/Rpackages/v4" "/usr/users/course/splus/library/R"
[3] "/usr/lib/R/site-library" "/usr/lib/R/library"

--
Dario Strbenac
University of Sydney
Camperdown NSW 2050
Australia
__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] New pipe operator

2020-12-08 Thread Duncan Murdoch

First, one comment:

You're right about the illegality of _PIPE_ as a name, I had  
misremembered the rule.


About your proposal:

I don't find it attractive, but I can see that some people would.  But I  
don't think it's necessary to put it into the base parser.  Other than  
using an illegal name, there doesn't seem to be a reason you couldn't  
write a small function to convert your placeholder proposal to a call to  
a function.  So instead of typing


 x |> { y <- _PIPE_+1; _PIPE_ / y }

you would type

 x |> forpipe({ y <- PIPE_+1; PIPE_ / y })

I don't think "forpipe" is the right name here.  I proposed a generic  
"as.call" before, but I don't like that one either.  I'm still trying to  
think of a good name, and whether or not it makes sense for it to be  
generic.


But the point is that we don't need to choose just one from all the  
proposed replacements for anonymous function syntax, we can try them out  
and see which ones we like.  We might end up with more than one (like we  
have at least 4 different high level graphics paradigms!), and that's  
not the end of the world.


Duncan Murdoch

On 08/12/2020 4:26 p.m., Bravington, Mark (Data61, Hobart) wrote:

On 06/12/2020 8:22 p.m., Bravington, Mark (Data61, Hobart) wrote:

(and Duncan Murdoch responded, as below)


It still seems to me that placeholders are viable and unambiguous (only as 
things in RHS of pipes), and that something like

x |> foo( _PIPE_)
x |> bah( otherarg, _PIPE_)
x |> { y <- _PIPE_+1; _PIPE_ / y } # anonymous function

would be a viable solution that doesn't break syntax. This suggestion expands 
slightly on my previous post, to deal with anonymous functions without either 
ugly or cumbersome syntax. Specifically, the parser could expand curly-braces 
in a pipe RHS like this:

x |> {expr}

into

_ANON_( _PIPE_, {expr})( x)

where '_ANON_' itself  constructs-and-calls a function with one argument called 
'_PIPE_' whose body consists of 'expr' (which presumably refers to '_PIPE_')

No new weird operators like \(, and the only break with normal syntax is the 
expansion of curly-braces--- plus treating one symbol, _PIPE_ or any other 
pre-agreed one perhaps even just _, as a legal name inside a pipe.

Now back to my previous post and responding to Duncan's comments:


   - I don't see the problem with a placeholder--- doesn't it remove all 
ambiguity? Sure there needs to be a standard unclashable name and people can 
argue about what that should be, but the following seems clear and flexible... 
to me, anyway:
   
   thing |>

 foo( _PIPE_) |>   # standard
 bah( arg1, _PIPE_) |>   # multi-arg function
 _ANON_({ x <- sum( _PIPE_); _PIPE_/x + x/_PIPE_ })   # anon function

where '_PIPE_' is the ordained name of the placeholder, and '_ANON_' constructs-and-calls a function with single argument '_PIPE_'. There is just one rule (I think...): each pipe-stage must be a *call* involving the argument '_PIPE_'.


and (see end) I think the line with _ANON_ above could in fact just be

   ... |> { x <- sum( _PIPE_); _PIPE_/x + x/_PIPE_ }
   

I believe there's no ambiguity if the placeholder is *only* allowed in the RHS 
of a pipe expression.


Yes--- that's my suggestion: there and only there. Hence an otherwise-illegal 
name like _PIPE_.


I think the ambiguity arises if you allow
the same syntax to be used to generate anonymous functions.


Agreed; don't allow that outside of pipes.


We can't use _PIPE_ as the placeholder, because it's a legal name.


Surely _PIPE_ is not a legal R name though? Not in my R4.1.0dev, anyway. Of 
course, the parser can _make_ it legal *only* in the context of RHS of pipe. 
Anyway, I'm not suggesting the names must be _PIPE_ and _ANON_--- the name is 
secondary to the concept.


But we could use _.


Yes, any unclashable name would do--- though "_" is hard to read (as per complaints about "." as 
placeholder, which I use in my own code). And I remember back when R decided to disallow "_" as an assignment 
operator. Which forced me to change about 5 lines of code that wasn't stored in text files, so I wasn't happy--- 
and the only reason that was ever given to me, was "it's ugly" ! Which is kinda true.


However, implementing this makes the parser pretty ugly: its handling of _ 
depends on the outer context.


That context issue is already the case under the current proposal though; eg 
'head(10)' in

x |> head(10) # really head( , 10)

or indeed 'head' in

x |> head # actually a call to head(), not a symbol



I now agree that leaving out placeholder syntax was the right decision.


Others are not so sure!

Re operator precedence: thanks for pointing that out, I accept that R's current 
operator-precedence rules make it impossible for people to cleanly implement 
their own preferred homemade %my_pipe_op%.

All the more reason to be careful with the pipe syntax choice for base-R, of 
course...



Then



x |> (_ + 1) + mean(_)



could expand unambiguously to



(fun

Re: [Rd] New pipe operator

2020-12-08 Thread Bravington, Mark (Data61, Hobart)
> > On 06/12/2020 8:22 p.m., Bravington, Mark (Data61, Hobart) wrote:
> (and Duncan Murdoch responded, as below)

It still seems to me that placeholders are viable and unambiguous (only as 
things in RHS of pipes), and that something like  

x |> foo( _PIPE_) 
x |> bah( otherarg, _PIPE_)
x |> { y <- _PIPE_+1; _PIPE_ / y } # anonymous function

would be a viable solution that doesn't break syntax. This suggestion expands 
slightly on my previous post, to deal with anonymous functions without either 
ugly or cumbersome syntax. Specifically, the parser could expand curly-braces 
in a pipe RHS like this:

x |> {expr} 

into

_ANON_( _PIPE_, {expr})( x)

where '_ANON_' itself  constructs-and-calls a function with one argument called 
'_PIPE_' whose body consists of 'expr' (which presumably refers to '_PIPE_')

No new weird operators like \(, and the only break with normal syntax is the 
expansion of curly-braces--- plus treating one symbol, _PIPE_ or any other 
pre-agreed one perhaps even just _, as a legal name inside a pipe.

Now back to my previous post and responding to Duncan's comments:

> >   - I don't see the problem with a placeholder--- doesn't it remove all 
> > ambiguity? Sure there needs to be a standard unclashable name and people 
> > can argue about what that should be, but the following seems clear and 
> > flexible... to me, anyway:
> >   
> >   thing |>
> > foo( _PIPE_) |>   # standard
> > bah( arg1, _PIPE_) |>   # multi-arg function
> > _ANON_({ x <- sum( _PIPE_); _PIPE_/x + x/_PIPE_ })   # anon function
> >
> > where '_PIPE_' is the ordained name of the placeholder, and '_ANON_' 
> > constructs-and-calls a function with single argument '_PIPE_'. There is 
> > just one rule (I think...): each pipe-stage must be a *call* involving the 
> > argument '_PIPE_'.

and (see end) I think the line with _ANON_ above could in fact just be

  ... |> { x <- sum( _PIPE_); _PIPE_/x + x/_PIPE_ }
  
> I believe there's no ambiguity if the placeholder is *only* allowed in the 
> RHS of a pipe expression.

Yes--- that's my suggestion: there and only there. Hence an otherwise-illegal 
name like _PIPE_.

> I think the ambiguity arises if you allow 
> the same syntax to be used to generate anonymous functions.

Agreed; don't allow that outside of pipes.

> We can't use _PIPE_ as the placeholder, because it's a legal name.

Surely _PIPE_ is not a legal R name though? Not in my R4.1.0dev, anyway. Of 
course, the parser can _make_ it legal *only* in the context of RHS of pipe. 
Anyway, I'm not suggesting the names must be _PIPE_ and _ANON_--- the name is 
secondary to the concept.

> But we could use _.  

Yes, any unclashable name would do--- though "_" is hard to read (as per 
complaints about "." as placeholder, which I use in my own code). And I 
remember back when R decided to disallow "_" as an assignment operator. Which 
forced me to change about 5 lines of code that wasn't stored in text files, 
so I wasn't happy--- and the only reason that was ever given to me, was "it's 
ugly" ! Which is kinda true.

> However, implementing this makes the parser pretty ugly: its handling of _ 
> depends on the outer context.  

That context issue is already the case under the current proposal though; eg 
'head(10)' in 

x |> head(10) # really head( , 10)

or indeed 'head' in 

x |> head # actually a call to head(), not a symbol


> I now agree that leaving out placeholder syntax was the right decision.

Others are not so sure!

Re operator precedence: thanks for pointing that out, I accept that R's current 
operator-precedence rules make it impossible for people to cleanly implement 
their own preferred homemade %my_pipe_op%.

All the more reason to be careful with the pipe syntax choice for base-R, of 
course...


> Then

>x |> (_ + 1) + mean(_)

> could expand unambiguously to

>(function(_) (_  + 1) + mean(_))(x)

> but

>(_ + 1) + mean(_)

> shouldn't be taken to be an anonymous function declaration, otherwise 
> things like

>mean(_ |> _)

> do become ambiguous:  is the second placeholder the argument to the anon 
> function, or is it the placeholder for the embedded pipe?

That wouldn't be allowed in my proposal; the "_ |> _" is illegal because the 
RHS is not a call. For the whole thing, I'd require

x |> _ANON_((_PIPE_ + 1) + mean( _PIPE_))

or the just-curly version

x |> { (_PIPE_ + 1) + mean( _PIPE_)} 

but with the implication that this would parse out to 

(`_ANON_`( { (_PIPE_ + 1) + mean( _PIPE_)}))( x)

> > [*] Definition of _ANON_ could be something like this--- almost certainly 
> > won't work as-is, this is just to point out that it could be done in 
> > standard R.

> > `_ANON_` <- function( expr) { 
> >   #1. Construct a function with arg '_PIPE_' and body 'expr'
> >   #2. Construct a call() to that function
> >   #3. Do the call

> >   f <- function( `_PIPE_`) NULL
> >   body( f) <- expr
> >   environment( f) <- parent.frame() # or something... yes these deta

Re: [Rd] [External] Re: New pipe operator

2020-12-08 Thread Gabor Grothendieck
On Mon, Dec 7, 2020 at 9:09 AM Gabor Grothendieck
 wrote:
>
> On Sat, Dec 5, 2020 at 1:19 PM  wrote:
> > Let's get some experience
>
> Here is my last SO post using dplyr rewritten to use R 4.1 devel.  Seems

It occurred to me it would also be interesting to show this example
rewritten using John Mount's bizarro pipe
(which is clever use of syntax to get the effect of a pipe) with the
new \(x) ...
This can be done entirely in base R 4.1.  It does not use \>, just \(x)...

  "myfile.csv" ->.;
readLines(.) ->.;
gsub(r'{(c\(.*?\)|integer\(0\))}', r'{"\1"}', .) ->.;
read.csv(text = .) ->.;
replace(., 2:3, lapply(.[2:3], \(col) lapply(col, \(x)
eval(parse(text = x) ->.;
. -> DF

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] [External] anonymous functions

2020-12-08 Thread Gabor Grothendieck
On Mon, Dec 7, 2020 at 12:34 PM  wrote:
> I don't disagree in principle, but the reality is users want shortcuts
> and as a result various packages, in particular tidyverse, have been
> providing them. Mostly based on formulas, mostly with significant
> issues since formulas weren't designed for this, and mostly
> incompatible (tidyverse ones are compatible within tidyverse but not
> with others). And of course none work in sapply or lapply.

The formulas as functions in the gsubfn package work with nearly any function
including sapply and lapply.

  library(gsubfn)
  fn$lapply(1:3, ~ x + 1)
  ## [1] 2 3 4

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] [External] anonymous functions

2020-12-08 Thread Duncan Murdoch

On 08/12/2020 6:21 a.m., Duncan Murdoch wrote:

On 07/12/2020 12:26 p.m., luke-tier...@uiowa.edu wrote:

I don't disagree in principle, but the reality is users want shortcuts
and as a result various packages, in particular tidyverse, have been
providing them. Mostly based on formulas, mostly with significant
issues since formulas weren't designed for this, and mostly
incompatible (tidyverse ones are compatible within tidyverse but not
with others). And of course none work in sapply or lapply. Providing a
shorthand in base may help to improve this. You don't have to use it
if you don't want to, and you can establish coding standards that
disallow it if you like.

Here's a suggestion to let people define their own shorthands and work
with the current |> definition.

Define "as.call" as an S3 generic, with a default definition something like >
as.call.default <- function(x, f, ...) f(x, ...)


That's probably a bad choice of name for the generic in that it doesn't 
convert x to a call and it's only useful in a pipe, but I do think the 
idea of some generic function would be useful.


Duncan Murdoch



so one could use

   x |> as.call(mean)

to get the same result as

   x |> mean()

or (if working in the tidyverse)

   x |> as.call(~ .x + 1)

to use a method to be provided by rlang or purrr to convert their
shorthand into a call that the pipe can work with.

We already have the generic as.function, which could be used internally
by lapply and sapply for the same sort of purpose.  tidyverse has
rlang::as_function, so they could pretty easily add methods for
as.function if they wanted to allow people to use their shorthand in
*apply functions.

Duncan Murdoch



__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] New pipe operator

2020-12-08 Thread Hadley Wickham
I just wanted to pipe in here (HA HA) to say that I agree with Kevin.
I've never loved the complicated magrittr rule (which has personally
tripped me up a couple of times) and I think the compact inline
function syntax provides a more general solution. It is a bit more
typing, and it will require a little time for your eyes to get used to
the new syntax, but overall I think it's a better solution.

In general, I think the base pipe does an excellent job of taking what
we've learned from 6 years of magrittr, keeping what has been most
successful while discarding complications around the edges.

Hadley

On Mon, Dec 7, 2020 at 1:05 PM Kevin Ushey  wrote:
>
> IMHO the use of anonymous functions is a very clean solution to the
> placeholder problem, and the shorthand lambda syntax makes it much
> more ergonomic to use. Pipe implementations that crawl the RHS for
> usages of `.` are going to be more expensive than the alternatives. It
> is nice that the `|>` operator is effectively the same as a regular R
> function call, and given the identical semantics could then also be
> reasoned about the same way regular R function calls are.
>
> I also agree usages of the `.` placeholder can make the code more
> challenging to read, since understanding the behavior of a piped
> expression then requires scouring the RHS for usages of `.`, which can
> be challenging in dense code. Piping to an anonymous function makes
> the intent clear to the reader: the programmer is likely piping to an
> anonymous function because they care where the argument is used in the
> call, and so the reader of code should be aware of that.
>
> Best,
> Kevin
>
>
>
> On Mon, Dec 7, 2020 at 10:35 AM Gabor Grothendieck
>  wrote:
> >
> > On Mon, Dec 7, 2020 at 12:54 PM Duncan Murdoch  
> > wrote:
> > > An advantage of the current implementation is that it's simple and easy
> > > to understand.  Once you make it a user-modifiable binary operator,
> > > things will go kind of nuts.
> > >
> > > For example, I doubt if there are many users of magrittr's pipe who
> > > really understand its subtleties, e.g. the example in Luke's paper where
> > > 1 %>% c(., 2) gives c(1,2), but 1 %>% c(c(.), 2) gives c(1, 1, 2). (And
> > > I could add 1 %>% c(c(.), 2, .) and  1 %>% c(c(.), 2, . + 2)  to
> > > continue the fun.)
> >
> > The rule is not so complicated.  Automatic insertion is done unless
> > you use dot in the top level function or if you surround it with
> > {...}.  It really makes sense since if you use gsub(pattern,
> > replacement, .) then surely you don't want automatic insertion and if
> > you surround it with { ... } then you are explicitly telling it not
> > to.
> >
> > Assuming the existence of placeholders a possible simplification would
> > be to NOT do automatic insertion if { ... } is used and to use it
> > otherwise although personally having used it for some time I find the
> > existing rule in magrittr generally does what you want.
> >
> > __
> > R-devel@r-project.org mailing list
> > https://stat.ethz.ch/mailman/listinfo/r-devel
>
> __
> R-devel@r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel



-- 
http://hadley.nz

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] New pipe operator

2020-12-08 Thread Gabor Grothendieck
Duncan Murdoch:
> I agree it's all about call expressions, but they aren't all being
> treated equally:
>
> x |> f(...)
>
> expands to f(x, ...), while
>
> x |> `function`(...)
>
> expands to `function`(...)(x).  This is an exception to the rule for

Yes, this is the problem.  It is trying to handle two different sorts of right
hand sides, calls and functions, using only syntax level operations and
it really needs to either make use of deeper information or have some
method that is available at the syntax level for identifying whether the
right hand side is a call or function.  In the latter case having two
operators would be one way to do it.

  f <- \(x) x + 1
  x |> f()  # call
  x |:> f  # function
  x |:> \(x) x + 1  # function

In the other case where deeper information is used there would only be one
operator and it would handle all cases but would use more than just syntax
level knowledge.

R solved these sorts of problems long ago using S3 and other object oriented
systems which dispatch different methods based on what the right hand side is.
The attempt to avoid using the existing or equivalent mechanisms seems to have
led to this problem.

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] [External] anonymous functions

2020-12-08 Thread Duncan Murdoch

On 07/12/2020 12:26 p.m., luke-tier...@uiowa.edu wrote:

I don't disagree in principle, but the reality is users want shortcuts
and as a result various packages, in particular tidyverse, have been
providing them. Mostly based on formulas, mostly with significant
issues since formulas weren't designed for this, and mostly
incompatible (tidyverse ones are compatible within tidyverse but not
with others). And of course none work in sapply or lapply. Providing a
shorthand in base may help to improve this. You don't have to use it
if you don't want to, and you can establish coding standards that
disallow it if you like.
Here's a suggestion to let people define their own shorthands and work 
with the current |> definition.


Define "as.call" as an S3 generic, with a default definition something like

as.call.default <- function(x, f, ...) f(x, ...)

so one could use

 x |> as.call(mean)

to get the same result as

 x |> mean()

or (if working in the tidyverse)

 x |> as.call(~ .x + 1)

to use a method to be provided by rlang or purrr to convert their 
shorthand into a call that the pipe can work with.


We already have the generic as.function, which could be used internally 
by lapply and sapply for the same sort of purpose.  tidyverse has 
rlang::as_function, so they could pretty easily add methods for 
as.function if they wanted to allow people to use their shorthand in 
*apply functions.


Duncan Murdoch

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel