% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/robustDigest.R
\name{.robustDigest}
\alias{.robustDigest}
\alias{.robustDigest,ANY-method}
\alias{.robustDigest,function-method}
\alias{.robustDigest,expression-method}
\alias{.robustDigest,language-method}
\alias{.robustDigest,call-method}
\alias{.robustDigest,character-method}
\alias{.robustDigest,Path-method}
\alias{.robustDigest,environment-method}
\alias{.robustDigest,list-method}
\alias{.robustDigest,data.frame-method}
\alias{.robustDigest,numeric-method}
\alias{.robustDigest,matrix-method}
\alias{.robustDigest,integer-method}
\title{Create reproducible digests of objects in R}
\usage{
.robustDigest(
  object,
  .objects = NULL,
  length = getOption("reproducible.length", Inf),
  algo = "xxhash64",
  quick = getOption("reproducible.quick", FALSE),
  classOptions = list(),
  ...
)

\S4method{.robustDigest}{ANY}(object, .objects, length, algo, quick, classOptions)

\S4method{.robustDigest}{function}(object, .objects, length, algo, quick, classOptions)

\S4method{.robustDigest}{expression}(object, .objects, length, algo, quick, classOptions)

\S4method{.robustDigest}{language}(object, .objects, length, algo, quick, classOptions)

\S4method{.robustDigest}{call}(object, .objects, length, algo, quick, classOptions)

\S4method{.robustDigest}{character}(object, .objects, length, algo, quick, classOptions)

\S4method{.robustDigest}{Path}(object, .objects, length, algo, quick, classOptions)

\S4method{.robustDigest}{environment}(object, .objects, length, algo, quick, classOptions)

\S4method{.robustDigest}{list}(object, .objects, length, algo, quick, classOptions)

\S4method{.robustDigest}{data.frame}(object, .objects, length, algo, quick, classOptions)

\S4method{.robustDigest}{numeric}(object, .objects, length, algo, quick, classOptions)

\S4method{.robustDigest}{matrix}(object, .objects, length, algo, quick, classOptions)

\S4method{.robustDigest}{integer}(
  object,
  .objects,
  length,
  algo,
  quick,
  classOptions,
  cacheSaveFormat = getOption("reproducible.cacheSaveFormat")
)
}
\arguments{
\item{object}{an object to digest.}

\item{.objects}{Character vector of objects to be digested. This is only applicable
if there is a list, environment (or similar) with named objects
within it. Only this/these objects will be considered for caching,
i.e., only use a subset of
the list, environment or similar objects. In the case of nested list-type
objects, this will only be applied outermost first.}

\item{length}{Numeric. If the element passed to Cache is a \code{Path} class
object (from e.g., \code{asPath(filename)}) or it is a \code{Raster} with
file-backing, then this will be
passed to \code{digest::digest}, essentially limiting the number of bytes
to digest (for speed). This will only be used if \code{quick = FALSE}.
Default is \code{getOption("reproducible.length")}, which is set to \code{Inf}.}

\item{algo}{The digest algorithm to use. Default \code{xxhash64} (see \code{\link[digest:digest]{digest::digest()}} for others).}

\item{quick}{Logical or character. If \code{TRUE},
no disk-based information will be assessed, i.e., only
memory content. See Details section about \code{quick} in \code{\link[=Cache]{Cache()}}.}

\item{classOptions}{Optional list. This will pass into \code{.robustDigest} for
specific classes. Should be options that the \code{.robustDigest} knows what
to do with.}

\item{...}{Arguments passed to \code{FUN}, if \code{FUN} is not an expression.}

\item{cacheSaveFormat}{Character string: currently either \code{qs} or \code{rds}. Defaults to
\code{getOption("reproducible.cacheSaveFormat")}. \code{qs} may be faster but appears to have
narrower range of conditions that work; \code{rds} is safer, and may be slower.}

\item{objects}{Optional character vector indicating which objects are to
be considered while making digestible. This argument is not used
in the default cases; the only known method that uses this
in the default cases; the only known method that uses this
argument is the \code{simList} class from \code{SpaDES.core}.}
}
\value{
A hash i.e., digest of the object passed in.
}
\description{
Not all aspects of R objects are captured by current hashing tools in R
(e.g. \code{digest::digest}, \code{knitr} caching, \code{archivist::cache}).
This is mostly because many objects have "transient"
(e.g., functions have environments), or "disk-backed" features.
Since the goal of using reproducibility is to have tools that are not session specific,
this function attempts to strip all session specific information so that the digest
works between sessions and operating systems.
It is tested under many conditions and object types, there are bound to be others that don't
work correctly.
}
\section{Classes}{


\verb{Raster*} objects have the potential for disk-backed storage, thus, require more work.
Also, because \verb{Raster*} can have a built-in representation for having their data content
located on disk, this format will be maintained if the raster already is file-backed,
i.e., to create \code{.tif} or \code{.grd} backed rasters, use \code{writeRaster} first,
then \code{Cache}.
The \file{.tif} or \file{.grd} will be copied to the \file{raster/} subdirectory of the
\code{cachePath}.
Their RAM representation (as an R object) will still be in the usual  \file{cacheOutputs/}
(or formerly \file{gallery/}) directory.
For \code{inMemory} raster objects, they will remain as binary \code{.RData} files.

Functions (which are contained within environments) are
converted to a text representation via a call to \code{format(FUN)}.

Objects contained within a list or environment are recursively hashed
using \code{\link[digest:digest]{digest::digest()}}, while removing all references to
environments.

Character strings are first assessed with \code{dir.exists} and \code{file.exists}
to check for paths. If they are found to be paths, then the path is hashed with
only its filename via \code{basename(filename)}. If it is actually a path, we suggest
using \code{asPath(thePath)}
}

\examples{

a <- 2
tmpfile1 <- tempfile()
tmpfile2 <- tempfile()
tmpfile3 <- tempfile(fileext = ".grd")
tmpfile4 <- tempfile(fileext = ".grd")
save(a, file = tmpfile1)
save(a, file = tmpfile2)

# treats as character string, so 2 filenames are different
digest::digest(tmpfile1)
digest::digest(tmpfile2)

# tests to see whether character string is representing a file
.robustDigest(tmpfile1)
.robustDigest(tmpfile2) # same

# if you tell it that it is a path, then you can decide if you want it to be
#  treated as a character string or as a file path
.robustDigest(asPath(tmpfile1), quick = TRUE)
.robustDigest(asPath(tmpfile2), quick = TRUE) # different because using file info

.robustDigest(asPath(tmpfile1), quick = FALSE)
.robustDigest(asPath(tmpfile2), quick = FALSE) # same because using file content

# SpatRasters are have pointers
if (requireNamespace("terra", quietly = TRUE)) {
  r <- terra::rast(system.file("ex/elev.tif", package = "terra"))
  r3 <- terra::deepcopy(r)
  r1 <- terra::writeRaster(r, filename = tmpfile3)

  digest::digest(r)
  digest::digest(r3) # different but should be same
  .robustDigest(r1)
  .robustDigest(r3) # same... data & metadata are the same

  # note, this is not true for comparing memory and file-backed rasters
  .robustDigest(r)
  .robustDigest(r1) # different
}

}
\author{
Eliot McIntire
}
\keyword{internal}
