% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/eval-relocate.R
\name{eval_relocate}
\alias{eval_relocate}
\title{Evaluate an expression to relocate variables}
\usage{
eval_relocate(
  expr,
  data,
  ...,
  before = NULL,
  after = NULL,
  strict = TRUE,
  name_spec = NULL,
  allow_rename = TRUE,
  allow_empty = TRUE,
  allow_predicates = TRUE,
  before_arg = "before",
  after_arg = "after",
  env = caller_env(),
  error_call = caller_env()
)
}
\arguments{
\item{expr}{Defused R code describing a selection according to the
tidyselect syntax.}

\item{data}{A named list, data frame, or atomic vector.
Technically, \code{data} can be any vector with \code{names()} and \code{"[["}
implementations.}

\item{...}{These dots are for future extensions and must be empty.}

\item{before, after}{Defused R code describing a selection according to the
tidyselect syntax. The selection represents the destination of the
selection provided through \code{expr}. Supplying neither of these will move the
selection to the left-hand side. Supplying both of these is an error.}

\item{strict}{If \code{TRUE}, out-of-bounds errors are thrown if \code{expr}
attempts to select or rename a variable that doesn't exist. If
\code{FALSE}, failed selections or renamings are ignored.}

\item{name_spec}{A name specification describing how to combine or
propagate names. This is used only in case nested \code{c()}
expressions like \code{c(foo = c(bar = starts_with("foo")))}. See the
\code{name_spec} argument of \code{\link[vctrs:vec_c]{vctrs::vec_c()}} for a description of
valid name specs.}

\item{allow_rename}{If \code{TRUE} (the default), the renaming syntax
\code{c(foo = bar)} is allowed. If \code{FALSE}, it causes an error. This
is useful to implement purely selective behaviour.}

\item{allow_empty}{If \code{TRUE} (the default), it is ok for \code{expr} to result
in an empty selection. If \code{FALSE}, will error if \code{expr} yields an empty
selection.}

\item{allow_predicates}{If \code{TRUE} (the default), it is ok for \code{expr} to
use predicates (i.e. in \code{where()}). If \code{FALSE}, will error if \code{expr} uses a
predicate. Will automatically be set to \code{FALSE} if \code{data} does not
support predicates (as determined by \code{\link[=tidyselect_data_has_predicates]{tidyselect_data_has_predicates()}}).}

\item{before_arg, after_arg}{Argument names for \code{before} and \code{after}. These
are used in error messages.}

\item{env}{The environment in which to evaluate \code{expr}. Discarded
if \code{expr} is a \link[rlang:enquo]{quosure}.}

\item{error_call}{The execution environment of a currently
running function, e.g. \code{caller_env()}. The function will be
mentioned in error messages as the source of the error. See the
\code{call} argument of \code{\link[rlang:abort]{abort()}} for more information.}
}
\value{
A named vector of numeric locations with length equal to \code{length(data)}.
Each position in \code{data} will be represented exactly once.

The names are normally the same as in the input data, except when the user
supplied named selections with \code{c()}. In the latter case, the names reflect
the new names chosen by the user.
}
\description{
\code{eval_relocate()} is a variant of \code{\link[=eval_select]{eval_select()}} that moves a selection to
a new location. Either \code{before} or \code{after} can be provided to specify where
to move the selection to. This powers \code{dplyr::relocate()}.
}
\examples{
library(rlang)

# Interpret defused code as a request to relocate
x <- expr(c(mpg, disp))
after <- expr(wt)
eval_relocate(x, mtcars, after = after)

# Supplying neither `before` nor `after` will move the selection to the
# left-hand side
eval_relocate(x, mtcars)

# Within a function, use `enquo()` to defuse a single argument.
# Note that `before` and `after` must also be defused with `enquo()`.
my_relocator <- function(x, expr, before = NULL, after = NULL) {
  eval_relocate(enquo(expr), x, before = enquo(before), after = enquo(after))
}

my_relocator(mtcars, vs, before = hp)

# Here is an example of using `eval_relocate()` to implement `relocate()`.
# Note that the dots are passed on as a defused call to `c(...)`.
relocate <- function(.x, ..., .before = NULL, .after = NULL) {
  pos <- eval_relocate(
    expr(c(...)),
    .x,
    before = enquo(.before),
    after = enquo(.after)
  )
  set_names(.x[pos], names(pos))
}

relocate(mtcars, vs, .before = hp)
relocate(mtcars, starts_with("d"), .after = last_col())
}
