From toth@dene@ @end|ng |rom kogentum@hu  Mon Dec  7 23:52:36 2020
From: toth@dene@ @end|ng |rom kogentum@hu (=?UTF-8?B?RMOpbmVzIFTDs3Ro?=)
Date: Mon, 7 Dec 2020 23:52:36 +0100
Subject: [Rd] New pipe operator
In-Reply-To: <CAD4oTHE6oWztx7BB+jp_EFs28jDNpUoznOS9jehz_P7iuUexRA@mail.gmail.com>
References: <e55c2093-0bb5-5f9b-5521-0ca8bdf35953@gmail.com>
 <CAP01uRkkd3jOjvaS9JgKYCD1KA83HfzCd+MQSv_2aYJPgcOmSQ@mail.gmail.com>
 <CAP01uRkPcbCBRGwAzKM=W19Ohh-zDGwZH8gM7=A-sK2rRaQxaQ@mail.gmail.com>
 <CAD4oTHFBY4rBhiRsJUkA6jwD2YWaxPMz2OZDOqSvHfv6A7DZPg@mail.gmail.com>
 <CAP01uRmTYna1nM+ugELHrCqLjfWuWwHSfE4cvqoaq2537sHpAw@mail.gmail.com>
 <CAD4oTHHFWkiirncPRWngY+_k9HcB=8zo7VdXAONXQoXdNhKzDA@mail.gmail.com>
 <7e28d84a-f6d0-1e18-c131-163650e7cd75@gmail.com>
 <CAP01uRkCpLQ0uwJgFdTFTNG+80C+F1hn=TnQqRS2Z-nFuU5MmA@mail.gmail.com>
 <CADfFDC74ostfecs5mhOznSXEedGBA=_78SiNTfysz5B8JU=YUQ@mail.gmail.com>
 <F7AF463A-B9A1-4AEB-9EE3-1062B6AD3CFF@gmail.com>
 <7e1eb5e9-4ee7-4a80-ad7b-58ed67c830df@gmail.com>
 <91C38945-B1BA-4E7A-B2E0-79790A894240@gmail.com>
 <7f8cf17d-d5fa-0cd1-7760-7157ef1fe7bf@gmail.com>
 <CAP01uRkphV1txi+59LXi3uQO-4RCL+gAt9gbOpDCLXOV-484Yw@mail.gmail.com>
 <CAJXgQP1Jpo3BNVGvEf6ctKu9Bv3SV-QFJa5BRByOO-yjYE2XFA@mail.gmail.com>
 <CAD4oTHE6oWztx7BB+jp_EFs28jDNpUoznOS9jehz_P7iuUexRA@mail.gmail.com>
Message-ID: <8c468025-3d9f-1ace-6203-e58834f7dfdc@kogentum.hu>



On 12/7/20 11:09 PM, Gabriel Becker wrote:
> On Mon, Dec 7, 2020 at 11:05 AM Kevin Ushey <kevinushey at gmail.com> 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 agree. That said, one thing that maybe could be done, though I'm not
> super convinced its needed, is make a "curry-stuffed pipe", where something
> like
> 
> LHS |^pipearg^> RHS(arg1 = 5, arg3 = 7)
> 
> Would parse to
> 
> RHS(pipearg = LHS, arg1 = 5, arg3 = 7)
> 

This gave me the idea that naming the arguments can be used to skip the 
placeholder issue:

"funny" |> sub(pattern = "f", replacement = "b")

Of course this breaks if the maintainer changes the order of the 
function arguments (which is not a nice practice but happens).

An option could be to allow for missing argument in the first position, 
but this might add further undesired complexity, so probably not worth 
the effort:

"funny" |> sub(x =, "f", "b")

So basically the parsing rule would be:

LHS |> RHS(arg=, ...)     -> RHS(arg=LHS, ...)


> 
> (Assuming we could get the parser to handle |^bla^> correctly)
> 
> For argument position issues would be sufficient. For more complicated
> expressions, e.g., those that would use the placeholder multiple times or
> inside compound expressions, requiring anonymous functions seems quite
> reasonable to me. And honestly, while I kind of like it, I'm not sure if
> that "stuffed pipe" expression (assuming we could get the parser to capture
> it correctly) reads to me as nicer than the following, anyway.
> 
> LHS |> \(x) RHS(arg1 = 5, pipearg = x, arg3 = 7)
> 
> ~G
> 
>>
>> 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
>> <ggrothendieck at gmail.com> wrote:
>>>
>>> On Mon, Dec 7, 2020 at 12:54 PM Duncan Murdoch <murdoch.duncan at gmail.com>
>> 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 at r-project.org mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>
>> ______________________________________________
>> R-devel at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>
> 
> 	[[alternative HTML version deleted]]
> 
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>



[Rd] New pipe operator
=?UTF-8?B?RMOpbmVzIFTDs3Ro?=