% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/slice.R
\name{vec_slice}
\alias{vec_slice}
\alias{vec_slice<-}
\alias{vec_assign}
\title{Get or set observations in a vector}
\usage{
vec_slice(x, i, ..., error_call = current_env())

vec_slice(x, i) <- value

vec_assign(x, i, value, ..., slice_value = FALSE, x_arg = "", value_arg = "")
}
\arguments{
\item{x}{A vector}

\item{i}{An integer, character or logical vector specifying the locations or
names of the observations to get/set. Specify \code{TRUE} to index all elements
(as in \code{x[]}), or \code{NULL}, \code{FALSE} or \code{integer()} to index none (as in
\code{x[NULL]}).}

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

\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.}

\item{value}{A vector of replacement values

\code{value} is cast to the type of \code{x}.

If \code{slice_value = FALSE}, \code{value} must be size 1 or the same size as \code{i}
after \code{i} has been converted to a positive integer location vector with
\code{\link[=vec_as_location]{vec_as_location()}} (which may not be the same size as \code{i} originally).

If \code{slice_value = TRUE}, \code{value} must be size 1 or the same size as \code{x}.}

\item{slice_value}{A boolean. If \code{TRUE}, the assignment proceeds as if you
had provided \code{vec_slice(x, i) <- vec_slice(value, i)}, but is optimized to
avoid materializing the slice of \code{value}.}

\item{x_arg, value_arg}{Argument names for \code{x} and \code{value}. These are used
in error messages to inform the user about the locations of
incompatible types and sizes (see \code{\link[=stop_incompatible_type]{stop_incompatible_type()}} and
\code{\link[=stop_incompatible_size]{stop_incompatible_size()}}).}
}
\value{
A vector of the same type as \code{x}.
}
\description{
This provides a common interface to extracting and modifying observations
for all vector types, regardless of dimensionality. They are analogs to \code{[}
and \verb{[<-} that match \code{\link[=vec_size]{vec_size()}} instead of \code{length()}.
}
\section{Genericity}{


Support for S3 objects depends on whether the object implements a
\code{\link[=vec_proxy]{vec_proxy()}} method.
\itemize{
\item When a \code{vec_proxy()} method exists, the proxy is sliced or assigned to and
\code{vec_restore()} is called on the result.
\item Otherwise, \code{vec_slice()} falls back to the base generic \code{[} and
\verb{vec_slice<-()} falls back to the base generic \verb{[<-}.
}

When \verb{vec_slice<-()} falls back to \verb{[<-}, it is expected that the subclass's
\verb{[<-} method can handle the following subset of cases that base R's \verb{[<-}
can also handle:
\itemize{
\item An \code{i} vector of positive integer positions (notably excluding \code{NA}).
\item A \code{value} vector of length 1 or length \code{length(i)}. If length 1, it
should be recycled by the \verb{[<-} method to the length of \code{i}.
}

If your \verb{[<-} method eventually calls base R's native \verb{[<-} code, then these
cases will be handled for you.

Note that S3 lists are treated as scalars by default, and will
cause an error if they don't implement a \code{\link[=vec_proxy]{vec_proxy()}} method.
}

\section{Differences with base R subsetting}{

\itemize{
\item \code{vec_slice()} only slices along one dimension. For
two-dimensional types, the first dimension is subsetted.
\item \code{vec_slice()} preserves attributes by default.
\item \verb{vec_slice<-()} is type-stable and always returns the same type
as the LHS.
}
}

\section{Dependencies}{

\subsection{vctrs dependencies}{
\itemize{
\item \code{\link[=vec_proxy]{vec_proxy()}}
\item \code{\link[=vec_restore]{vec_restore()}}
}
}

\subsection{base dependencies}{
\itemize{
\item \code{base::`[`}
\item \code{base::`[<-`}
}
}
}

\examples{
x <- sample(10)
x
vec_slice(x, 1:3)

# You can assign with the infix variant:
vec_slice(x, 2) <- 100
x

# Or with the regular variant that doesn't modify the original input:
y <- vec_assign(x, 3, 500)
y
x


# Slicing objects of higher dimension:
vec_slice(mtcars, 1:3)

# Type stability --------------------------------------------------

# The assign variant is type stable. It always returns the same
# type as the input.
x <- 1:5
vec_slice(x, 2) <- 20.0

# `x` is still an integer vector because the RHS was cast to the
# type of the LHS:
vec_ptype(x)

# Compare to `[<-`:
x[2] <- 20.0
vec_ptype(x)


# Note that the types must be coercible for the cast to happen.
# For instance, you can cast a double vector of whole numbers to an
# integer vector:
vec_cast(1, integer())

# But not fractional doubles:
try(vec_cast(1.5, integer()))

# For this reason you can't assign fractional values in an integer
# vector:
x <- 1:3
try(vec_slice(x, 2) <- 1.5)

# Slicing `value` -------------------------------------------------

# Sometimes both `x` and `value` start from objects that are the same length,
# and you need to slice `value` by `i` before assigning it to `x`. This comes
# up when thinking about how `base::ifelse()` and `dplyr::case_when()` work.
condition <- c(TRUE, FALSE, TRUE, FALSE)
yes <- 1:4
no <- 5:8

# Create an output container and fill it
out <- vec_init(integer(), 4)
out <- vec_assign(out, condition, vec_slice(yes, condition))
out <- vec_assign(out, !condition, vec_slice(no, !condition))
out

# This is wasteful because you have to materialize the slices of `yes` and
# `no` before they can be assigned, and you also have to validate `condition`
# multiple times. Using `slice_value` internally performs
# `vec_slice(yes, condition)` and `vec_slice(no, !condition)` for you,
# but does so in a way that avoids the materialization.
out <- vec_init(integer(), 4)
out <- vec_assign(out, condition, yes, slice_value = TRUE)
out <- vec_assign(out, !condition, no, slice_value = TRUE)
out
}
\keyword{internal}
