Thanks Antoine for starting this discussion. It would indeed be great to see
an improved `ifelse()` in base R.
I also agree with Duncan's suggestion that the way to proceed would be to
create a package where the improved version could be drafted, discussed and
refined so that R Core would have a concrete proposal to consider in the end.
Some initial thoughts on what should be considered:
Performance has been mentioned a few times. While it would of course be nice
to see improvements there I think the main goal is in the API. The goal for
performance should rather be that it doesn't deteriorate unacceptably.
While data.table's and dplyr's ifelse variants may serve as a good
starting
point for identifiying the improvements needed, I don't think either is a
good
candidate for simply copying as the base R candidate. A function in base R
should adhere to the conventions in base R; neither of the packages does that.
They instead have their own stricter requirements. For example:
* Incompatible lengths: Base R recycles with a warning, both packages error out.
* Different classes: Base R coerces loosely, dplyr uses stricter coercion rules
based on vctrs, and data.table doesn't allow any coercion.
Another point to consider is the handling of attributes for the result.
data.table copies from the first non-NA input from left to right, while dplyr
delegates to vctrs again for merging the attributes gracefully. This matters
for example for factors, where data.table special-cases them to require the
same levels, wherease dplyr merges them. For a base R solution, it would make
sense to delegate the attribute handling to `c()` somehow, as that's
conceptually
what should be happening; we're combining values from the `yes` and `no`
objects.
I'm sure there are many other points to consider, but as I said this is what
comes to mind at first. Best of luck with the effort.
Kind regards,
Mikko
On Tuesday, 8 July 2025 at 21:41, avi.e.gross at gmail.com <avi.e.gross at
gmail.com> wrote:
> A package with only one function, what a concept!
>
> But then it becomes tempting to also create a function like if_else_else()
and if_else_default() and of course if_not_else() ....
>
> Joking aside, plenty of functionality in extendible languages like R were
written long enough ago that they might be done quite differently today. I
don't mean just different code, but different arguments it takes and
different defaults. Who really wanted you to type stringsAsFactors=TRUE every
time, for example.
>
> But it is late enough that making changes now can backfire. Look at the
announcement that updating ggplot2 to use S7 objects will break some packages
that depend on it including many in the Bioconductor world. I would imagine if R
magically had started with S7 and skipped over S3 and S4 and perhaps others that
have not been widely used, we might have had more consistency. But that is not
how it happened and we likely will be stuck for a long time with both R core and
all kinds of packages needing to be able to handle older kinds of objects. And,
not to compare, but a language like python made a very different approach to
objects long ago so that pretty much everything is an object and there generally
is no need to create a new form as you can use all kinds of existing ways to
tailor your objects to your needs.
>
> Given the budgets and other constraints we are dealing with, I suspect that
there is a long list of possible changes that are currently not being seriously
considered and since there are several work-arounds available in existing
packages, there is less urgency.
>
> And, there is a reality that although an ifelse() has a certain generality,
for specific purposes, it may be trivial enough to fashion your own variant
using anything from explicit to implicit loops. But, certainly, if some people
work on a variant and show it is compatible and benchmarks suggesting how much
faster, then a minimal package with no odd dependencies is a way to go, and
might eventually be taken into the core. I would be cautious about naming the
package/function as whatever is chosen, ...
>
> Avi (too)
>
> -----Original Message-----
> From: R-devel r-devel-bounces at r-project.org On Behalf Of Duncan Murdoch
>
> Sent: Tuesday, July 8, 2025 3:06 PM
> To: Josiah Parry josiah.parry at gmail.com; Avraham Adler avraham.adler at
gmail.com
>
> Cc: r-devel at r-project.org
> Subject: Re: [Rd] Time to revisit ifelse ?
>
> Since you and Antoine are volunteering to do the work, why not start in
> the way I suggested? Write up a comparison of the known ifelse
> implementations, and either pick the best one, or choose the best parts
> of each. Put the result in a package containing nothing else, and
> invite comment from the wider community.
>
> My only comment in advance is that the package should have no
> dependencies other than base packages, for two reasons:
>
> 1. The hope is to have it adopted in base R, and for that it can't have
> any other dependencies.
>
> 2. If it's never adopted by R Core, I might still want to use it, but I
> don't want to add extra dependencies for just one little function.
>
> Duncan Murdoch
>
> On 2025-07-08 12:46 p.m., Josiah Parry wrote:
>
> > Avi, appreciate the puns!
> >
> > I don't think anyone is suggesting R-core dedicate all of their
time to
> > this problem.
> > To me, the thread is about consensus making (as there is no formal way
to
> > do that).
> >
> > Quoting OP here:
> >
> > "It's not about asking others to do it really, that was a
harsh assumption.
> >
> > I'd be happy to propose a version if it helps, I'd be also
very happy if it
> >
> > were just a copy of if_else or fifelse (both MIT FWIW)."
> >
> > The initial email, IMO, was to show that there already are community
> > implementations of faster
> > and type-safer of ifelse (notably dplyr and data.table and I'd add
> > kit::iif, too) and perhaps now
> > is the time to add this enhancement to the language.
> >
> > It is tough to get a sense of total usage of each though but some code
> > searching on GitHub:
> >
> > - data.table::fifelse:
> >
https://github.com/search?q="fifelse("+language%3AR&type=code
> > - dplyr::if_else:
> >
https://github.com/search?q="if_else("+language%3AR&type=code
> > - kit::iif:
> >
https://github.com/search?q=%2F(%3F-i)iif\(%2F+language%3AR+&type=code
> >
> > On Tue, Jul 8, 2025 at 8:23?AM Avraham Adler avraham.adler at
gmail.com
> > wrote:
> >
> > > On Tue, Jul 8, 2025 at 10:55?AM Josiah Parry josiah.parry at
gmail.com
> > > wrote:
> > >
> > > > I think the point is not that there needs to be a smaller
package for yet
> > > > another if-else (https://xkcd.com/927/). It is that if the
R-language,
> > > > as a
> > > > whole, had a performant if-else in the base of the language
would benefit
> > > > everyone such that a data.table or dplyr or gtools etc.
alternative
> > > > would not be necessary.
> > >
> > > While that may be true, Josiah, R Core's time is very
limited.
> > > Following Duncan's idea, if a small, simple package were
created and
> > > was proven to dominate the performance of standard ifelse without
> > > causing any issues with the ten thousand plus packages in the R
> > > environment, that would make R Core's decision much simpler,
whether
> > > or not to use the existing, proved performant code. Asking R Core
to
> > > do the research and testing for something which currently works,
> > > albeit not in the most efficient way possible, is pretty much a
> > > non-starter. Do as much work as possible for R Core to have even
a
> > > possibility of consideration. For something similar, albeit much
less
> > > core (pun intended) to R's code, see this discussion [1] from
June
> > > 2012 on Kendall's tau, where the code already existed but was
deemed
> > > unimportant enough to add to base R.
> > >
> > > [1] https://stat.ethz.ch/pipermail/r-devel/2012-June/064351.html
> > >
> > > Thanks,
> > >
> > > Avi
> > >
> > > > On Tue, Jul 8, 2025 at 5:09?AM Ben Bolker bbolker at
gmail.com wrote:
> > > >
> > > > > I think Duncan's point is that R-core are
(reasonably) very, very,
> > > > > very conservative about adding things to base R. It
would be useful to
> > > > > the community, and would indeed further the discussion,
to make a tiny
> > > > > package containing just that function. (Even just
copying it from some
> > > > > other package might require some work to disentangle it
from
> > > > > dependencies: for example, a quick glance at
dplyr::if_else shows that
> > > > > it uses functions from rlang, vctrs, ...)
> > > > >
> > > > > I'd be happy to accept a pull request in `gtools`,
which is a
> > > > > zero-dependency (except base R) package for small
utility functions ...
> > > > >
> > > > > cheers
> > > > > Ben Bolker
> > > > >
> > > > > On 7/8/25 07:36, Antoine Fabri wrote:
> > > > >
> > > > > > It's not about asking others to do it really,
that was a harsh
> > > > > > assumption.
> > > > > > I'd be happy to propose a version if it helps,
I'd be also very
> > > > > > happy if
> > > > > > it
> > > > > > were just a copy of if_else or fifelse (both MIT
FWIW).
> > > > > > It's a low level building block and it's
broken, IMO it's way better
> > > > > > to
> > > > > > have it available and documented in base R and
incite everyone to
> > > > > > use it,
> > > > > > so not only we don't suffer from it in the
code we write, but also
> > > > > > in the
> > > > > > code we use or inherit from.
> > > > > >
> > > > > > Le mar. 8 juil. 2025 ? 13:25, Duncan Murdoch <
> > > > > > murdoch.duncan at gmail.com>
> > > > > > a
> > > > > > ?crit :
> > > > > >
> > > > > > > Rather than asking others to do this, why
don't you create a tiny
> > > > > > > package containing nothing other than an
ifelse() replacement? I
> > > > > > > wouldn't want to depend on dplyr or
data.table just to get their
> > > > > > > versions, but depending on your tiny package
wouldn't be an issue.
> > > > > > >
> > > > > > > Duncan Murdoch
> > > > > > >
> > > > > > > On 2025-07-08 6:12 a.m., Antoine Fabri wrote:
> > > > > > >
> > > > > > > > Dear r-devel,
> > > > > > > >
> > > > > > > > `ifelse()` has a lot of issues, and for
these reasons it has been
> > > > > > > > redone
> > > > > > > > in
> > > > > > > > `dplyr::if_else()` and
`data.table::fifelse()`, which are both
> > > > > > > > great.
> > > > > > > > Yet
> > > > > > > > it's an important base R function,
it's really hard to program in
> > > > > > > > base
> > > > > > > > R
> > > > > > > > without it and scores probably as high
as it gets in the most_used
> > > > > > > > *
> > > > > > > > most_problematic metric.
> > > > > > > >
> > > > > > > > Obviously we can't change it without
breaking a ton of code, but
> > > > > > > > with
> > > > > > > > all
> > > > > > > > the experience we now have with it and
the dplyr and data.table
> > > > > > > > alternative
> > > > > > > > maybe it might not be absurd to have a
good alternative, say
> > > > > > > > `if.else`
> > > > > > > > in
> > > > > > > > base R, that we can document on the same
page and recommend for
> > > > > > > > future
> > > > > > > > use.
> > > > > > > > It would require a common type in
yes/no, not return logical() for
> > > > > > > > all
> > > > > > > > zero
> > > > > > > > length input, work with dates, datetimes
and factors, handle a na
> > > > > > > > condition
> > > > > > > > etc. The test suites of dplyr and
data.table probably tell us
> > > > > > > > everything
> > > > > > > > about the edge cases we want to look at.
Maybe the old ifelse could
> > > > > > > > even
> > > > > > > > warn when called from the top level, to
incite us to work with the
> > > > > > > > new
> > > > > > > > one.
> > > > > > > >
> > > > > > > > It feels wrong to me to be stuck with
ifelse() forever just
> > > > > > > > because it
> > > > > > > > has
> > > > > > > > been like this for a long time. I'm
sure some of you learnt your
> > > > > > > > way
> > > > > > > > around
> > > > > > > > it but I work with R every day and after
10+ years of R it still
> > > > > > > > bites
> > > > > > > > me
> > > > > > > > all the time, I'm probably not
alone, at least chatGPT called it a
> > > > > > > > "footgun", and we don't
want that :).
> > > > > > > >
> > > > > > > > Thanks,
> > > > > > > >
> > > > > > > > Antoine
> > > > > > > >
> > > > > > > > [[alternative HTML version deleted]]
> > > > > > > >
> > > > > > > >
______________________________________________
> > > > > > > > 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
> > > > >
> > > > > --
> > > > > Dr. Benjamin Bolker
> > > > > Professor, Mathematics & Statistics and Biology,
McMaster University
> > > > > Director, School of Computational Science and
Engineering
> > > > > * E-mail is sent at my convenience; I don't expect
replies outside of
> > > > > working hours.
> > > > >
> > > > > ______________________________________________
> > > > > 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
> >
> > [[alternative HTML version deleted]]
> >
> > ______________________________________________
> > 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
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel