diff --git a/.Rbuildignore b/.Rbuildignore index efb7e88..edfd5b9 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -1,3 +1,4 @@ +^.*\.Rcheck/$ ^.*\.Rproj$ ^\.Rproj\.user$ ^_pkgdown\.yml$ @@ -22,3 +23,4 @@ ^Makefile$ ^codecov\.yml$ ^pkgdown$ +^cran-comments\.md$ diff --git a/.gitignore b/.gitignore index 686258f..6382407 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ docs/ /doc/ /Meta/ ..Rcheck/ +*.Rcheck/ .claude .codex .agents diff --git a/DESCRIPTION b/DESCRIPTION index 465cb28..2e004e9 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: Immutables Type: Package Title: Fast and Functional Data Structures -URL: https://oneilsh.github.io/immutables, https://github.com/oneilsh/immutables +URL: https://oneilsh.github.io/immutables/, https://github.com/oneilsh/immutables BugReports: https://github.com/oneilsh/immutables/issues Version: 1.0.0 Authors@R: c( @@ -12,6 +12,8 @@ Description: Provides fast, side-effect free data structures, including sequences, and interval indices. License: MIT + file LICENSE Encoding: UTF-8 +Depends: + R (>= 4.1.0) Imports: coro, Rcpp, @@ -38,4 +40,4 @@ Suggests: Config/testthat/edition: 3 VignetteBuilder: knitr Roxygen: list(markdown = TRUE) -RoxygenNote: 7.3.2 +RoxygenNote: 7.3.3 diff --git a/NEWS.md b/NEWS.md index b0e5598..66296aa 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ -# immutables 1.0.0 +# Immutables 1.0.0 -* First release. +* First CRAN submission. +* `flexseq`s: list-like sequences with push/pop/peek from either end, indexed and named access, insertion, splitting, and concatenation. +* `priority_queue`s, `ordered_sequence`s, `interval_index`es: finger-tree-backed structures for min/max-by-priority, sorted-by-key, and interval-overlap queries. +* Developer API for building custom structures via monoid/measure combinations. +* Core operations implemented in C++ via Rcpp, with matching pure-R reference implementations using `lambda.r`. diff --git a/R/30-api-flexseq-core.R b/R/30-api-flexseq-core.R index 6f25952..207e73b 100644 --- a/R/30-api-flexseq-core.R +++ b/R/30-api-flexseq-core.R @@ -284,7 +284,8 @@ merge.flexseq <- function(x, y, ...) { #' x <- flexseq("a", "b", "c") #' if(requireNamespace("igraph", quietly = TRUE)) plot(x) #' -#' \dontrun{ +#' if (requireNamespace("igraph", quietly = TRUE)) { +#' \donttest{ #' # Label every node with its subtree size (leaves contribute 1). #' plot_structure(as_flexseq(1:10), node_label = function(node) { #' paste0(node$type, "\n.size=", node$measures$.size) @@ -296,8 +297,8 @@ merge.flexseq <- function(x, y, ...) { #' xs <- add_monoids(as_flexseq(c(3, 1, 4, 1, 5, 9, 2, 6)), #' list(sum = sum_monoid)) #' plot_structure(xs, node_label = function(node) { -#' if(node$type == "Element") sprintf("%g\nΣ=%g", node$element, node$measures$sum) -#' else sprintf("%s\nΣ=%g", node$type, node$measures$sum) +#' if(node$type == "Element") sprintf("%g\nsum=%g", node$element, node$measures$sum) +#' else sprintf("%s\nsum=%g", node$type, node$measures$sum) #' }) #' #' # List-valued built-in measure: priority_queue's .pq_min tracks the min @@ -315,6 +316,7 @@ merge.flexseq <- function(x, y, ...) { #' } #' }) #' } +#' } #' @export # Runtime: O(n) to build plot graph data. plot.flexseq <- function(x, ...) { diff --git a/R/70-plotting.R b/R/70-plotting.R index c4db4be..c8543f7 100644 --- a/R/70-plotting.R +++ b/R/70-plotting.R @@ -267,7 +267,8 @@ NULL #' @return Invoked for its side effect (draws to the active graphics #' device). Returns `NULL` invisibly. #' @examples -#' \dontrun{ +#' if (requireNamespace("igraph", quietly = TRUE)) { +#' \donttest{ #' t <- as_flexseq(letters[1:8]) #' plot_structure(t, title = "Finger tree") #' @@ -277,10 +278,11 @@ NULL #' xs <- add_monoids(as_flexseq(c(3, 1, 4, 1, 5, 9, 2, 6)), #' list(sum = sum_monoid)) #' plot_structure(xs, node_label = function(node) { -#' if(node$type == "Element") sprintf("%g\nΣ=%g", node$element, node$measures$sum) -#' else sprintf("%s\nΣ=%g", node$type, node$measures$sum) +#' if(node$type == "Element") sprintf("%g\nsum=%g", node$element, node$measures$sum) +#' else sprintf("%s\nsum=%g", node$type, node$measures$sum) #' }) #' } +#' } #' @seealso [plot.flexseq()], [measure_monoid()], [add_monoids()] #' @export # Runtime: O(n) to build graph structures prior to plotting. diff --git a/R/immutables-package.R b/R/immutables-package.R index c6ff451..1b0bddc 100644 --- a/R/immutables-package.R +++ b/R/immutables-package.R @@ -1,28 +1,28 @@ -#' immutables -#' -#' The `immutables` R package implements several immutable, or persistent, data +#' Immutables: Fast and Functional Data Structures +#' +#' The `Immutables` R package implements several immutable, or persistent, data #' structures: operations return modified copies while remaining fast and true #' to R's side-effect-free functional nature. #' -#' - `flexseq`s provide list-like operations including indexed and named element -#' access, push/pop/peek from either end for double-ended queue behavior, -#' insertion, splitting, and concatenation. -#' - `priority_queues` associate items with priority values and provide +#' - `flexseq`s provide list-like operations: indexed and named element access; +#' push/pop/peek from either end for double-ended queue behavior; insertion, +#' splitting, and concatenation. +#' - `priority_queue`s associate items with priority values and provide #' min and max peek/pop by priority and fast insertion. -#' - `ordered_sequences` associate items with key values and keep the elements in +#' - `ordered_sequence`s associate items with key values and keep the elements in #' sorted order by key. These may be similarly be inserted/popped/peeked by key #' value as well as position. Keys may be duplicated, with first-in-first-out order within key groups. -#' - `interval_indexes` store items associated with interval ranges, supporting +#' - `interval_index`es store items associated with interval ranges, supporting #' point as well as interval overlaps/contains/within queries. Items are kept #' in start-order enabling ordered sequence operations and sweep-line #' algorithms. #' #' Backed by monoid-annotated 2-3 fingertrees as described by -#' [Hinze and Paterson](https://doi.org/10.1017/S0956796805005769), most operations are constant time, amortized constant time, or $O(\\log(n))$ (indexing $k$ elements is $O(k \\log(n))$). Core functions are implemented in C++ (via Rcpp) for speed, with matching pure-R reference implementations using `lambda.r` syntax to match the paper. +#' Hinze and Paterson, most operations are constant time, amortized constant time, or $O(\\log(n))$. Core functions are implemented in C++ (via Rcpp) for speed, with matching pure-R reference implementations using `lambda.r` syntax to match the paper. #' -#' Finally, the developer API supports the addition of custom structures via combinations of monoids and measures; see vignettes for details. +#' Finally, the developer API supports the addition of custom structures via combinations of monoids and measures. #' -#' - Hinze, R. and Paterson, R. (2006), *Finger trees: a simple general-purpose data structure*. +#' - Hinze, R. and Paterson, R. (2006), *Finger trees: a simple general-purpose data structure*. \doi{10.1017/S0956796805005769} #' #' @keywords internal #' @import lambda.r diff --git a/cran-comments.md b/cran-comments.md new file mode 100644 index 0000000..62ad3e7 --- /dev/null +++ b/cran-comments.md @@ -0,0 +1,19 @@ +## R CMD check results + +0 errors | 0 warnings | 1 note + +The NOTE has two components: + +* "New submission" is expected +* "catenable" is flagged as a possibly misspelled word but is standard +terminology in functional data structures literature + +## Test environments + +- local macOS (aarch64), R 4.5.3 +- win-builder R-devel (R 4.6.0 RC, x86_64-w64-mingw32) +- GitHub Actions: ubuntu-latest, macos-latest, windows-latest + +## Notes + +This is a new submission. diff --git a/man/Immutables-package.Rd b/man/Immutables-package.Rd index 61c1161..7662eb2 100644 --- a/man/Immutables-package.Rd +++ b/man/Immutables-package.Rd @@ -4,40 +4,40 @@ \name{Immutables-package} \alias{Immutables} \alias{Immutables-package} -\title{immutables} +\title{Immutables: Fast and Functional Data Structures} \description{ -The \code{immutables} R package implements several immutable, or persistent, data +The \code{Immutables} R package implements several immutable, or persistent, data structures: operations return modified copies while remaining fast and true to R's side-effect-free functional nature. } \details{ \itemize{ -\item \code{flexseq}s provide list-like operations including indexed and named element -access, push/pop/peek from either end for double-ended queue behavior, -insertion, splitting, and concatenation. -\item \code{priority_queues} associate items with priority values and provide +\item \code{flexseq}s provide list-like operations: indexed and named element access; +push/pop/peek from either end for double-ended queue behavior; insertion, +splitting, and concatenation. +\item \code{priority_queue}s associate items with priority values and provide min and max peek/pop by priority and fast insertion. -\item \code{ordered_sequences} associate items with key values and keep the elements in +\item \code{ordered_sequence}s associate items with key values and keep the elements in sorted order by key. These may be similarly be inserted/popped/peeked by key value as well as position. Keys may be duplicated, with first-in-first-out order within key groups. -\item \code{interval_indexes} store items associated with interval ranges, supporting +\item \code{interval_index}es store items associated with interval ranges, supporting point as well as interval overlaps/contains/within queries. Items are kept in start-order enabling ordered sequence operations and sweep-line algorithms. } Backed by monoid-annotated 2-3 fingertrees as described by -\href{https://doi.org/10.1017/S0956796805005769}{Hinze and Paterson}, most operations are constant time, amortized constant time, or $O(\\log(n))$ (indexing $k$ elements is $O(k \\log(n))$). Core functions are implemented in C++ (via Rcpp) for speed, with matching pure-R reference implementations using \code{lambda.r} syntax to match the paper. +Hinze and Paterson, most operations are constant time, amortized constant time, or $O(\\log(n))$. Core functions are implemented in C++ (via Rcpp) for speed, with matching pure-R reference implementations using \code{lambda.r} syntax to match the paper. -Finally, the developer API supports the addition of custom structures via combinations of monoids and measures; see vignettes for details. +Finally, the developer API supports the addition of custom structures via combinations of monoids and measures. \itemize{ -\item Hinze, R. and Paterson, R. (2006), \emph{Finger trees: a simple general-purpose data structure}. +\item Hinze, R. and Paterson, R. (2006), \emph{Finger trees: a simple general-purpose data structure}. \doi{10.1017/S0956796805005769} } } \seealso{ Useful links: \itemize{ - \item \url{https://oneilsh.github.io/immutables} + \item \url{https://oneilsh.github.io/immutables/} \item \url{https://github.com/oneilsh/immutables} \item Report bugs at \url{https://github.com/oneilsh/immutables/issues} } diff --git a/man/plot.flexseq.Rd b/man/plot.flexseq.Rd index 435b85c..e61cc49 100644 --- a/man/plot.flexseq.Rd +++ b/man/plot.flexseq.Rd @@ -54,7 +54,8 @@ built-in \code{.pq_min} on \code{priority_queue} is \code{list(has, priority)}). x <- flexseq("a", "b", "c") if(requireNamespace("igraph", quietly = TRUE)) plot(x) -\dontrun{ +if (requireNamespace("igraph", quietly = TRUE)) { +\donttest{ # Label every node with its subtree size (leaves contribute 1). plot_structure(as_flexseq(1:10), node_label = function(node) { paste0(node$type, "\n.size=", node$measures$.size) @@ -66,8 +67,8 @@ sum_monoid <- measure_monoid(`+`, 0, function(el) el) xs <- add_monoids(as_flexseq(c(3, 1, 4, 1, 5, 9, 2, 6)), list(sum = sum_monoid)) plot_structure(xs, node_label = function(node) { - if(node$type == "Element") sprintf("\%g\nΣ=\%g", node$element, node$measures$sum) - else sprintf("\%s\nΣ=\%g", node$type, node$measures$sum) + if(node$type == "Element") sprintf("\%g\nsum=\%g", node$element, node$measures$sum) + else sprintf("\%s\nsum=\%g", node$type, node$measures$sum) }) # List-valued built-in measure: priority_queue's .pq_min tracks the min @@ -86,3 +87,4 @@ plot_structure(pq, node_label = function(node) { }) } } +} diff --git a/man/plot_structure.Rd b/man/plot_structure.Rd index 3124fec..3b2e0fa 100644 --- a/man/plot_structure.Rd +++ b/man/plot_structure.Rd @@ -92,7 +92,8 @@ access to the full \code{node_label} API for custom label formatting. Requires the \code{igraph} package (listed in \code{Suggests}). } \examples{ -\dontrun{ +if (requireNamespace("igraph", quietly = TRUE)) { +\donttest{ t <- as_flexseq(letters[1:8]) plot_structure(t, title = "Finger tree") @@ -102,11 +103,12 @@ sum_monoid <- measure_monoid(`+`, 0, function(el) el) xs <- add_monoids(as_flexseq(c(3, 1, 4, 1, 5, 9, 2, 6)), list(sum = sum_monoid)) plot_structure(xs, node_label = function(node) { - if(node$type == "Element") sprintf("\%g\nΣ=\%g", node$element, node$measures$sum) - else sprintf("\%s\nΣ=\%g", node$type, node$measures$sum) + if(node$type == "Element") sprintf("\%g\nsum=\%g", node$element, node$measures$sum) + else sprintf("\%s\nsum=\%g", node$type, node$measures$sum) }) } } +} \seealso{ \code{\link[=plot.flexseq]{plot.flexseq()}}, \code{\link[=measure_monoid]{measure_monoid()}}, \code{\link[=add_monoids]{add_monoids()}} }