This version handles the changes in dependencies that broke the previous version, supports idiomatic construction for many new classes and integrates a couple of new features.
New features:
construct_serialize() shows how to rebuild an object from its serialized
form, which is useful for objects that have no idiomatic constructor.opts_character(multiline = TRUE) prints strings containing new lines on
several lines rather than escaping them.opts_matrix(byrow = TRUE) lays matrices out by row, in the spirit of
tibble::tribble().opts_environment(context =) controls which aspects of an environment we
describe: parents, attributes, locks, names, objects.opts_environment("unserialize") reconstructs an environment from its
serialized form, preserving active bindings, locks and self references."default" constructor for ggplot2 themes guesses the theme_*()
function an object comes from, and falls back on a plain theme() call.New supported classes:
"table", "ftable", "dist", "ecdf",
"stepfun", "roman" and "raster"clock: the 6 calendars, "clock_naive_time", "clock_sys_time",
"clock_zoned_time", "clock_duration" and "clock_weekday"data.table: "IDate" and "ITime"fs: "fs_path", "fs_bytes" and "fs_perms"glue: "glue"haven: "haven_labelled" and "haven_labelled_spss"hms: "hms"htmltools: "shiny.tag", "shiny.tag.list", "shiny.tag.function",
"html" and "html_dependency"lubridate: "Period", "Duration" and "Interval"Matrix: "sparseMatrix", "denseMatrix", "diagonalMatrix",
"indMatrix" and "sparseVector"readr: "col_spec", "collector", "locale" and "date_names"sf: "sf", "sfc", "sfg", "crs" and "bbox"survival: "Surv"tsibble: "tbl_ts", "grouped_ts", "yearmonth", "yearquarter" and
"yearweek"units: "units" and "mixed_units"vctrs: "vctrs_vctr", "vctrs_rcrd" and "vctrs_unspecified"Fixes and improvements:
.additional_properties argument of
ellmer::type_object() anymore. ellmer 0.5.0 made it deprecated().NA predicates (as.character(), is.na(), [[ and
friends) are shimmed internally so a class with its own methods cannot alter
the code we generate.xts objects are constructed exactly, with xts::xts() rather than
as.xts() on a matrix, which used to lose the index class and time zone.integer64 values are constructed with NA rather than the string
"NA", which newer bit64 warns about.lengths() is shimmed to honour use.names = FALSE and to return
integer(0) on empty input.name attribute of R6 generators is not repaired anymore.array() gets its dimnames argument right..cstr_construct.CoordCartesian.default() is registered, it was missing due
to a wrong roxygen tag.Other:
constructive now declares a dependency on R >= 4.0.0.1.2.0 couldn't be installed on some OS, R versions, or combinations of the latter, this is addressed in 1.3.0 along with a few additional fixes and features so it ends up being a new minor version.
matrix() and array() are not used anymore when calling construct_dput(), this is consistent with dput().initialize() methodxml2::read_html() or xml2::read_xml().cstr_new_class() and .cstr_new_constructor() work with VSCode and VSCode based editors.cynkra (https://cynkra.com) is officially a funder, already was from the start in practice, thanks cynkra!
Features and improvements:
getClass("S4")@prototype |> asS3(complete = FALSE)
or S7::S7_object() |> structure(class = NULL)ggplot2::geom_point
and geom_point to be equivalent in stored calls. It's not fully satisfying because an aim
of constructive is to spot such small details, but we also want to be practical
and assessing the practical equivalence of the generated code seems more valuable
than perfect accuracy there. Please open a ticket if this upsets you and we'll work something out.cli::code_highlight() is now used, removing the dependency on {prettycode}. Turn it off with options(constructive_pretty = FALSE).
The style argument of print.constructive_code() is deprecated in favour of the new argument code_theme. Thanks @wurli!Bug fixes:
deparse_call() supports more corner cases (mostly for artificial cases you probably won't encounter)function function (of type "language") are correctly constructeddata.frame() when a column has attributes that don't support itFeatures:
"cbind" and "rbind" constructors for matricesopts_*() functions if the package is not
attached, this mean we can call for instance constructive::construct(x, opts_tbl_df("tribble"))
rather than constructive::construct(x, constructive::opts_tbl_df("tribble"))Fixes and improvements:
construct_diff()construct_clip() now shows a console message in addition to writing to the
clipboardNA or duplicate namestribble() calls when calling construct(x, opts_tbl_df("tribble"))"POSIXlt" classnumeric_version(), package_version(),
and R_system_version()(`fun<-`)() or (`a b`)()NULL parents.cstr_new_class(, commented = TRUE)deparse_call()construct_dput() and construct_base() allow to construct
objects respectively without using high level constructors at all, or using
only those included in base packages (such as data.frame() etc).construct_clip() is just like construct() but
copies code directly to the clipboard (Thanks Josiah Parry @JosiahParry for the suggestion).opts_logical(), opts_integer(), opts_double(), opts_complex(),
opts_character() and opts_raw() so options can be set independently.
opts_atomic() still works to set a. behavior for all atomics but the new functions have precedence.
The "raw" type is supported better can be constructed from integers in
decimal or hexadecimal notation with the "as.raw" constructor, or from
character using the "charToRaw" constructor..cstr_new_class() and .cstr_new_template()
facilitate the process of working with the new extension system.NA or negative integer64 objects using base R only.classes argument that generalize
construct_dput() and construct_base(), so users can enable or disable the idiomatic construction of some
classes.construct_reprex() and construct_multi() gain the include_dotted = TRUE
argument so we can optionally disable the construction of objects such as
.Random.seed int he global environment or .Class in the execution environment
of S3 methods.sconstruct() and construct_multi() gain the arguments unicode_representation
and escape previously used by opts_atomic() and these are now not only
applied on strings but also on element names and variable names.opts_tbl_df() gains a justify argument to control the justification of
columns with constructor = "tribble"` (Thanks Jacob Scott @wurli for the implementation).parent.env(asNamespace("pkg")) and getNamespaceInfo("pkg", "lazydata").
Before that they were constructed as regular environments.-0. identical(0, -0)) is TRUE but
1/-0 is -Inf so it made sense to support them.opts_environment() gains a "predefine" constructor and
opts_environment(predefine = TRUE) is deprecated. The old way still works
but warns and is not documented anymore.opts_atomic() the arguments unicode_representation and escape are
deprecated, use the new opts_character() function or set them in the
main function directly instead so they also affect symbols and argument names.
The old way still works but warns and is not documented anymore.deparse_call()NAs,
or are named like c()'s arguments recursive and use.namesNAs and NaNs are not conflated anymore when compressing double vectorsNA values in their real and imaginary parts.isS4() and use asS4() when necessaryopts_numeric_version(), opts_package_version() and opts_R_system_version()
the incorrectly named "atomic" constructor is replaced by a "list" constructorstructure() has a .Data argument.c(NA, -<nrow>) form,
as in dput(), this solves some rare corner cases.NA, NaN, Inf dates and NULL timezonesconstruct_reprex() function, is introduced.
It can be called in any function and will construct all variables and arguments
where it's called.construct_multi() now constructs promises, in practice this is useful so
we can construct the evaluation environment of a function, including the uneavaluated
and potentially NSE args of a functionoptions(constructive_print_mode = <character>) where <character> is a vector
of strings among "console", script, "clipboard" and "reprex". The default
behavior is "console". See `` ?constructive-global_optionsopts_atomic(escape = FALSE) (the default) now correctly uses surrounding single quotes
for strings that contain double quotes and no single quotes.deparse_call() is more robust and gains the arguments escape and unicode_representation
that were already present in opts_atomic()data.frame()
methodone_liner argumentlength, [, [[ etc are handled better.env() doesn't crash anymore when provided a wrong or obsolete memory address.Machine$integer.maxslot argument rather than the representation arg%>% for R versions that don't support |>NA levels are supported for the classes "factor" and "ordered"constructive:: in the
... before opts_* functions, for instance we can call constructive::construct(cars, opts_data.frame("read.table")).quote({}) is now constructed as "{ }" rather than "`{`()"construct() generates the code to build an object using idiomatic code, it
wraps the lower level .cstr_construct() S3 generic.opts_ can be used to choose various constructors
and apply parameters to tweak the output..cstr_construct() method. This is useful to explore objects at a level one
step lower than the idiomatic constructor..cstr_,
a vignette describes how to proceed.construct_issues() is used without arguments to check what were the issues encountered
with the last reconstructed object, it can also be provided a specific constructive object.construct_diff() highlights the differences in the code used to produce 2 objects.construct_multi() constructs several objects from a named list,construct_dump() is similar to base::dump(), it's a wrapper around construct_multi()
that writes to a file.construct_signature() constructs a function signature such as the one we see in the
"usage" section of a function's help file.
outputs the code produceddeparse_call() is an alternative to base::deparse() and rlang::expr_deparse() that
handles additional corner cases and fails when encountering tokens other than symbols
and syntactic literals .base::dput() or base::deparse() but {constructive} strives to use "natural" constructors
(factor for factors, as.Date() for dates, data.frame() for data frames etc),
in order to get output readable by humans.