Skip to content

anonymous functions

12 messages · Gregory R. Warnes, iuke-tier@ey m@iii@g oii uiow@@edu, Terry Therneau +5 more

#
?The shorthand form \(x) x + 1 is parsed as function(x) x + 1. It may be helpful in making 
code containing simple function expressions more readable.?

Color me unimpressed.
Over the decades I've seen several "who can write the shortest code" threads: in Fortran, 
in C, in Splus, ...   The same old idea that "short" is a synonym for either elegant, 
readable, or efficient is now being recylced in the tidyverse.   The truth is that "short" 
is actually an antonym for all of these things, at least for anyone else reading the code; 
or for the original coder 30-60 minutes after the "clever" lines were written.  Minimal 
use of the spacebar and/or the return key isn't usually held up as a goal, but creeps into 
many practiioner's code as well.

People are excited by replacing "function(" with "\("?  Really?   Are people typing code 
with their thumbs?
I am ambivalent about pipes: I think it is a great concept, but too many of my colleagues 
think that using pipes = no need for any comments.

As time goes on, I find my goal is to make my code less compact and more readable.  Every 
bug fix or new feature in the survival package now adds more lines of comments or other 
documentation than lines of code.  If I have to puzzle out what a line does, what about 
the poor sod who inherits the maintainance?
#
Thanks for expressing this eloquently. I heartily agree.

On Mon, Dec 7, 2020 at 12:04 PM Therneau, Terry M., Ph.D. via R-devel <
r-devel at r-project.org> 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.

Best,

luke
On Mon, 7 Dec 2020, Therneau, Terry M., Ph.D. via R-devel wrote:

            

  
    
#
It is easier to understand a function if you can see the entire
function body at once on a page or screen and excessive verbosity
interferes with that.

On Mon, Dec 7, 2020 at 12:04 PM Therneau, Terry M., Ph.D. via R-devel
<r-devel at r-project.org> wrote:

  
    
#
Luke,
 ? Mostly an aside.? I think that pipes are a good addition, and it is clear that you and 
other R-core thought through many of the details.?? Congratulations on what appears to be 
solid work. I've used Unix since '79, so it is almost guarranteed that I like the basic 
idiom, and I expect to make use of it.? Users who think that pipes -- or any other code -- 
is so clear that comments are superfluous is no reflection on R core, and also a bit of a 
hobby horse for me.

I am a bit bemused by the flood of change suggestions, before people have had a chance to 
fully exercise the new code. ? I'd suggest waiting several months, or a year, before major 
updates, straight up bugs excepted. ? The same advice holds when moving into a new house.
One? experience with the survival package has been that most new ideas have been 
implemented locally, and we run with them for half a year before submission to CRAN.? I've 
had a few "really great" modifications that, thankfully, were never inflicted on the rest 
of the R community.

Terry T.
On 12/7/20 11:26 AM, luke-tierney at uiowa.edu wrote:

  
  
#
One advantage of the new pipe operator over magrittr's is that the former
works with substitute().
paste(collapse=", ",x))
[1] "2^(1:4): 2, 4, 8, 16"
[1] ".: 2, 4, 8, 16"

This is because the new one is at the parser level, so f() sees an ordinary
function call.
f(2^(1:4))


On Mon, Dec 7, 2020 at 10:35 AM Therneau, Terry M., Ph.D. via R-devel <
r-devel at r-project.org> wrote:

            

  
  
#
I mostly agree with your comments on anonymous functions.

However, I think the main problem is cryptic-ness, rather than succinct-ness.
The backslash is a relatively universal symbol within programming
languages with C-like (ALGOL-like?) syntax.
Where it denotes escape sequences within strings.

Using the leading character for escape sequences, to define functions,
is like using integers to define floating point numbers:

    my.integer <- as.integer (2) * pi

Arguably, the motive is more to be ultra-succinct than cryptic.
But either way, we get syntax which is difficult to read, from a
mathematical and statistical perspective.


On Tue, Dec 8, 2020 at 6:04 AM Therneau, Terry M., Ph.D. via R-devel
<r-devel at r-project.org> wrote:
#
Sorry, I should replace "cryptic-ness" from my last post, with
"unnecessary cryptic-ness".
Sometimes short symbolic expressions are necessary.


P.S.
Often, I wish I could write: f (x) = x^2.
But that's replacement function syntax.
On Tue, Dec 8, 2020 at 11:56 AM Abby Spurdle <spurdle.a at gmail.com> wrote:
#
I will stick my oar in here as a user to say that I find the \(x) syntax a bit line-noise-ish. 

David
#
On 07/12/2020 12:26 p.m., luke-tierney at uiowa.edu wrote:
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
#
On 08/12/2020 6:21 a.m., Duncan Murdoch wrote:
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
#
On Mon, Dec 7, 2020 at 12:34 PM <luke-tierney at uiowa.edu> wrote:
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