Hi Gabriel,

Thanks for the comments. See inline.

On 12/6/20 8:16 PM, Gabriel Becker wrote:
Hi Denes,

On Sun, Dec 6, 2020 at 6:43 AM Dénes Tóth <toth.de...@kogentum.hu <mailto:toth.de...@kogentum.hu>> wrote:

    Dear Luke,

    In the meantime I checked the R-syntax branch and the docs; they are
    very helpful. I would also like to thank you for putting effort into
    this feature. Keeping it at the syntax level is also a very smart
    decision. However, the current API might not exploit the full power of
    the basic idea.

    1) Requiring either an anonymous function or a function call, but not
    allowing for symbols which point to functions is inconsistent and will
    be misleading for non-experts.

    foo <- function(x) x
    identical(foo, function(x) x)

    mtcars |> foo               #bang!
    mtcars |> function(x) x     #fine?

    You stated in :
    "
    Another variation supported by the implementation is that a symbol on
    the RHS is interpreted as the name of a function to call with the LHS
    as argument:

    ```r
      > quote(x |> f)
    f(x)
    ```
    "

    So clearly this is not an implementation issue but a design decision.

    As a remedy, two different pipe operators could be introduced:

    LHS |> RHS    -> RHS is treated as a function call
    LHS |>> RHS   -> RHS is treated as a function

    If |>> is used, it would not matter which notation is used for the RHS
    expression; the parser would assume it evaluates to a function.


I think multiplying the operators would not be a net positive. You'd then have to remember and mix them when you mix anonymous functions and non-anonymous functions.  It would result in

LHS |> RHS1() |>> \(x,y) blablabla |> RHS3()

I think thats too much intricacy. Better to be a little more restrictive  in way that (honestly doesnt' really hurt anything afaics, and) guarantees consistency.


That was just a secondary option for the case if pure symbols are disallowed on the RHS. The point is that one can not avoid inconsistency here because of practical considerations; let us admit, R has tons of inconsistencies which are usually motivated by making interactive data analysis more convenient. To me it seems more inconsistent to allow for function calls and functions but not symbols - either allow all of them or be strict and enforce function calls.


    2) Simplified lambda expression:
    IMHO in the vast majority of use cases, this is used for
    single-argument
    functions, so parenthesis would not be required. Hence, both forms
    would
    be valid and equivalent:

    \x x + 1
    \(x) x + 1


Why special case something here when soemtimes you'll want more than one argument. The parentheses seem really not a big deal. So I don't understand the motivation here, if I'm being honest.

Just as I told before: because of practical considerations. In a Hungarian keyboard layout, this is how one types the backslash character: RightAlt+Q. Parenthesis: Shift+8 (left), Shift+9 (Right). This is how you type 'function' in the R terminal: fu+TAB. I do not really see the point of the new notation as it is now.



    3) Function composition:
    Allowing for concise composition of functions would be a great feature.
    E.g., instead of

    foo <- function(x) print(mean(sqrt(x), na.rm = TRUE), digits = 2)

    or

    foo <- \x {x |> sqrt() |> mean(na.rm = TRUE) |> print(digits = 2)}

    one could write

    foo <- \x |> sqrt() |> mean(na.rm = TRUE) |> print(digits = 2)

    So basically if the lambda argument is followed by a pipe operator, the
    pipe chain is transformed to a function body where the first lambda
    argument is inserted into the first position of the pipeline.


This one I disagree with very strongly. Reading pipelines would suddenly require a /much/ higher cognitive load than before because you have to model that complexity just to read it and know what it says. The brackets there seem like an extremely low price to pay to avoid that. Operator precedence should be extremely and easily predictable.


Unfortunately I could not come up with a better solution to approximate a function composition operator (supporting tacit/pointfree-style programming) which avoids the introduction of a separate function (like e.g. purrr::compose).

In Haskell:
floor . sqrt

In Julia (looks nice but requires \circTAB or custom keybinding):
floor ∘ sqrt

In R: ?


Best,
Denes





    Best,
    Denes


    On 12/5/20 7:10 PM, luke-tier...@uiowa.edu
    <mailto:luke-tier...@uiowa.edu> wrote:
     > We went back and forth on this several times. The key advantage of
     > requiring parentheses is to keep things simple and consistent.  Let's
     > get some experience with that. If experience shows requiring
     > parentheses creates too many issues then we can add the option of
     > dropping them later (with special handling of :: and :::). It's
    easier
     > to add flexibility and complexity than to restrict it after the fact.
     >
     > Best,
     >
     > luke
     >
     > On Sat, 5 Dec 2020, Hugh Parsonage wrote:
     >
     >> I'm surprised by the aversion to
     >>
     >> mtcars |> nrow
     >>
     >> over
     >>
     >> mtcars |> nrow()
     >>
     >> and I think the decision to disallow the former should be
     >> reconsidered.  The pipe operator is only going to be used when
    the rhs
     >> is a function, so there is no ambiguity with omitting the
    parentheses.
     >> If it's disallowed, it becomes inconsistent with other
    treatments like
     >> sapply(mtcars, typeof) where sapply(mtcars, typeof()) would just be
     >> noise.  I'm not sure why this decision was taken
     >>
     >> If the only issue is with the double (and triple) colon
    operator, then
     >> ideally `mtcars |> base::head` should resolve to
    `base::head(mtcars)`
     >> -- in other words, demote the precedence of |>
     >>
     >> Obviously (looking at the R-Syntax branch) this decision was
     >> considered, put into place, then dropped, but I can't see why
     >> precisely.
     >>
     >> Best,
     >>
     >>
     >> Hugh.
     >>
     >>
     >>
     >>
     >>
     >>
     >>
     >> On Sat, 5 Dec 2020 at 04:07, Deepayan Sarkar
     >> <deepayan.sar...@gmail.com <mailto:deepayan.sar...@gmail.com>>
    wrote:
     >>>
     >>> On Fri, Dec 4, 2020 at 7:35 PM Duncan Murdoch
     >>> <murdoch.dun...@gmail.com <mailto:murdoch.dun...@gmail.com>> wrote:
     >>>>
     >>>> On 04/12/2020 8:13 a.m., Hiroaki Yutani wrote:
     >>>>>>   Error: function '::' not supported in RHS call of a pipe
     >>>>>
     >>>>> To me, this error looks much more friendly than magrittr's error.
     >>>>> Some of them got too used to specify functions without (). This
     >>>>> is OK until they use `::`, but when they need to use it, it takes
     >>>>> hours to figure out why
     >>>>>
     >>>>> mtcars %>% base::head
     >>>>> #> Error in .::base : unused argument (head)
     >>>>>
     >>>>> won't work but
     >>>>>
     >>>>> mtcars %>% head
     >>>>>
     >>>>> works. I think this is a too harsh lesson for ordinary R users to
     >>>>> learn `::` is a function. I've been wanting for magrittr to
    drop the
     >>>>> support for a function name without () to avoid this confusion,
     >>>>> so I would very much welcome the new pipe operator's behavior.
     >>>>> Thank you all the developers who implemented this!
     >>>>
     >>>> I agree, it's an improvement on the corresponding magrittr error.
     >>>>
     >>>> I think the semantics of not evaluating the RHS, but treating
    the pipe
     >>>> as purely syntactical is a good decision.
     >>>>
     >>>> I'm not sure I like the recommended way to pipe into a particular
     >>>> argument:
     >>>>
     >>>>    mtcars |> subset(cyl == 4) |> \(d) lm(mpg ~ disp, data = d)
     >>>>
     >>>> or
     >>>>
     >>>>    mtcars |> subset(cyl == 4) |> function(d) lm(mpg ~ disp,
    data = d)
     >>>>
     >>>> both of which are equivalent to
     >>>>
     >>>>    mtcars |> subset(cyl == 4) |> (function(d) lm(mpg ~ disp,
    data =
     >>>> d))()
     >>>>
     >>>> It's tempting to suggest it should allow something like
     >>>>
     >>>>    mtcars |> subset(cyl == 4) |> lm(mpg ~ disp, data = .)
     >>>
     >>> Which is really not that far off from
     >>>
     >>> mtcars |> subset(cyl == 4) |> \(.) lm(mpg ~ disp, data = .)
     >>>
     >>> once you get used to it.
     >>>
     >>> One consequence of the implementation is that it's not clear how
     >>> multiple occurrences of the placeholder would be interpreted. With
     >>> magrittr,
     >>>
     >>> sort(runif(10)) %>% ecdf(.)(.)
     >>> ## [1] 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
     >>>
     >>> This is probably what you would expect, if you expect it to
    work at
     >>> all, and not
     >>>
     >>> ecdf(sort(runif(10)))(sort(runif(10)))
     >>>
     >>> There would be no such ambiguity with anonymous functions
     >>>
     >>> sort(runif(10)) |> \(.) ecdf(.)(.)
     >>>
     >>> -Deepayan
     >>>
     >>>> which would be expanded to something equivalent to the other
    versions:
     >>>> but that makes it quite a bit more complicated.  (Maybe _ or
    \. should
     >>>> be used instead of ., since those are not legal variable names.)
     >>>>
     >>>> I don't think there should be an attempt to copy magrittr's
    special
     >>>> casing of how . is used in determining whether to also include the
     >>>> previous value as first argument.
     >>>>
     >>>> Duncan Murdoch
     >>>>
     >>>>
     >>>>>
     >>>>> Best,
     >>>>> Hiroaki Yutani
     >>>>>
     >>>>> 2020年12月4日(金) 20:51 Duncan Murdoch
    <murdoch.dun...@gmail.com <mailto:murdoch.dun...@gmail.com>>:
     >>>>>>
     >>>>>> Just saw this on the R-devel news:
     >>>>>>
     >>>>>>
     >>>>>> R now provides a simple native pipe syntax ‘|>’ as well as a
     >>>>>> shorthand
     >>>>>> notation for creating functions, e.g. ‘\(x) x + 1’ is parsed as
     >>>>>> ‘function(x) x + 1’. The pipe implementation as a syntax
     >>>>>> transformation
     >>>>>> was motivated by suggestions from Jim Hester and Lionel
    Henry. These
     >>>>>> features are experimental and may change prior to release.
     >>>>>>
     >>>>>>
     >>>>>> This is a good addition; by using "|>" instead of "%>%" there
     >>>>>> should be
     >>>>>> a chance to get operator precedence right.  That said, the
    ?Syntax
     >>>>>> help
     >>>>>> topic hasn't been updated, so I'm not sure where it fits in.
     >>>>>>
     >>>>>> There are some choices that take a little getting used to:
     >>>>>>
     >>>>>>  > mtcars |> head
     >>>>>> Error: The pipe operator requires a function call or an
    anonymous
     >>>>>> function expression as RHS
     >>>>>>
     >>>>>> (I need to say mtcars |> head() instead.)  This sometimes
    leads to
     >>>>>> error
     >>>>>> messages that are somewhat confusing:
     >>>>>>
     >>>>>>  > mtcars |> magrittr::debug_pipe |> head
     >>>>>> Error: function '::' not supported in RHS call of a pipe
     >>>>>>
     >>>>>> but
     >>>>>>
     >>>>>> mtcars |> magrittr::debug_pipe() |> head()
     >>>>>>
     >>>>>> works.
     >>>>>>
     >>>>>> Overall, I think this is a great addition, though it's going
    to be
     >>>>>> disruptive for a while.
     >>>>>>
     >>>>>> Duncan Murdoch
     >>>>>>
     >>>>>> ______________________________________________
     >>>>>> R-devel@r-project.org <mailto:R-devel@r-project.org> mailing
    list
     >>>>>> https://stat.ethz.ch/mailman/listinfo/r-devel
     >>>>>
     >>>>> ______________________________________________
     >>>>> R-devel@r-project.org <mailto:R-devel@r-project.org> mailing list
     >>>>> https://stat.ethz.ch/mailman/listinfo/r-devel
     >>>>>
     >>>>
     >>>> ______________________________________________
     >>>> R-devel@r-project.org <mailto:R-devel@r-project.org> mailing list
     >>>> https://stat.ethz.ch/mailman/listinfo/r-devel
     >>>
     >>> ______________________________________________
     >>> R-devel@r-project.org <mailto:R-devel@r-project.org> mailing list
     >>> https://stat.ethz.ch/mailman/listinfo/r-devel
     >>
     >> ______________________________________________
     >> R-devel@r-project.org <mailto:R-devel@r-project.org> mailing list
     >> https://stat.ethz.ch/mailman/listinfo/r-devel
     >>
     >

    ______________________________________________
    R-devel@r-project.org <mailto: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

Reply via email to