The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.
The marker /// @export makes a public Zig function an R
function. Options of the marker and the documentation lines decide the
name, the defaults and the visibility of the R function;
/// @class makes a struct an R class. This vignette shows
each form in one package. The scan and the generated files are plain R;
the build and the calls run when a supported Zig compiler is found (this
copy ran them).
path <- file.path(tempdir(), "exportspkg")
create_rzig_package(path, tests = FALSE)
#> Created package exportspkg at /private/var/folders/vh/njwnyy0141n0zbrgjw2vbz800000gn/T/RtmppmxRLi/exportspkg
#> Write Zig functions in src/rzig/src/main.zig, then run rzig::document(path) and rzig::build_zig(path)
main_zig <- file.path(path, "src", "rzig", "src", "main.zig")name= gives the R function another name than the Zig
function, @default gives an argument a default value
written in R, and invisible returns the result
invisibly:
cat(
"",
"/// Shrink values towards zero.",
"/// @param x A numeric vector.",
"/// @param amount The amount to subtract from each absolute value.",
"/// @default amount 0.5",
"/// @return The shrunk values, invisibly.",
"/// @export name=shrink invisible",
"pub fn shrink_zig(ctx: *rzig.Ctx, x: []const f64, amount: f64) rzig.Error![]f64 {",
" const out = try ctx.alloc(f64, x.len);",
" for (x, out) |value, *slot| {",
" const size = @max(@abs(value) - amount, 0);",
" slot.* = if (value < 0) -size else size;",
" }",
" return out;",
"}",
sep = "\n", file = main_zig, append = TRUE
)A routine that only the package’s own R code calls is marked
/// @export internal: it gets an R wrapper, which the
package does not export and which gets no help page. The exported R
function checks its arguments in R and calls it:
cat(
"",
"/// The weighted mean, for weighted_mean().",
"/// @export internal",
"pub fn weighted_mean_zig(x: []const f64, w: []const f64) rzig.Error!f64 {",
" if (x.len != w.len) return rzig.raise(\"x and w differ in length\", .{});",
" var total: f64 = 0;",
" var weights: f64 = 0;",
" for (x, w) |value, weight| {",
" total += value * weight;",
" weights += weight;",
" }",
" return total / weights;",
"}",
sep = "\n", file = main_zig, append = TRUE
)
writeLines(c(
"#' The weighted mean",
"#'",
"#' @param x A numeric vector.",
"#' @param w Non-negative weights of the same length.",
"#' @return A number.",
"#' @export",
"weighted_mean <- function(x, w = rep(1, length(x))) {",
" stopifnot(is.numeric(x), is.numeric(w), all(w >= 0))",
" weighted_mean_zig(as.double(x), as.double(w))",
"}"
), file.path(path, "R", "weighted.R"))A struct marked /// @class becomes an R class. Its
init function is the constructor, exported under the
struct’s name, and each public function that takes the struct as its
first parameter is a method, called with $. The object owns
the Zig value, which R’s garbage collector releases:
cat(
"",
"/// A running mean.",
"/// @class",
"pub const RunningMean = struct {",
" total: f64 = 0,",
" count: usize = 0,",
"",
" /// Create an empty running mean.",
" pub fn init() RunningMean {",
" return .{};",
" }",
"",
" /// Add values.",
" pub fn add(self: *RunningMean, values: []const f64) void {",
" for (values) |value| self.total += value;",
" self.count += values.len;",
" }",
"",
" /// The mean of the values added so far.",
" pub fn mean(self: *const RunningMean) f64 {",
" return self.total / @as(f64, @floatFromInt(self.count));",
" }",
"};",
sep = "\n", file = main_zig, append = TRUE
)The scan lists every export with its R arguments, the internal routine marked as such, and the constructor and methods of the class:
scan_exports(path)
#> Zig exports of package exportspkg (src/rzig/src/main.zig): 6 functions
#>
#> hello_zig(name)
#> name []const u8 character, length 1, copied
#> returns rzig.Error![]const u8 character, length 1
#>
#> shrink(x, amount)
#> x []const f64 double vector, borrowed
#> amount f64 double, length 1
#> returns rzig.Error![]f64 double vector
#>
#> weighted_mean_zig(x, w) [internal: not exported from the package]
#> x []const f64 double vector, borrowed
#> w []const f64 double vector, borrowed
#> returns rzig.Error!f64 double, length 1
#>
#> RunningMean()
#> returns rzig.Error!rzig.External(RunningMean) external pointer that owns a Zig value
#>
#> RunningMean_add(self, values) [internal: not exported from the package]
#> self rzig.External(RunningMean) external pointer to a Zig value of this package
#> values []const f64 double vector, borrowed
#> returns void NULL
#>
#> RunningMean_mean(self) [internal: not exported from the package]
#> self rzig.External(RunningMean) external pointer to a Zig value of this package
#> returns f64 double, length 1document() writes the wrappers; the generated R code
shows the default, the invisible result and the internal routine:
bindings <- document(path)
#> Generated RZig bindings for exportspkg: 6 exported functions
cat(bindings$wrappers)
#> # Generated by rzig::document(). Do not edit.
#>
#> #' Return a friendly greeting.
#> #' @param name A name to greet.
#> #' @return A character string.
#> #' @examples
#> #' hello_zig("R")
#> #'
#> #' @export
#> hello_zig <- function(name) {
#> .Call(hello_zig_, name)
#> }
#>
#> #' Shrink values towards zero.
#> #' @param x A numeric vector.
#> #' @param amount The amount to subtract from each absolute value.
#> #' @return The shrunk values, invisibly.
#> #'
#> #' @export
#> shrink <- function(x, amount = 0.5) {
#> invisible(.Call(shrink_, x, amount))
#> }
#>
#> #' The weighted mean, for weighted_mean().
#> #'
#> #' @keywords internal
#> #' @noRd
#> weighted_mean_zig <- function(x, w) {
#> .Call(weighted_mean_zig_, x, w)
#> }
#>
#> #' A running mean.
#> #'
#> #' Create an empty running mean.
#> #'
#> #' @return An object of class `RunningMean`: an external pointer to a Zig value.
#> #' @section Methods:
#> #' For an object `x` made by `RunningMean()`:
#> #' * `x$add(values)`: Add values.
#> #' * `x$mean()`: The mean of the values added so far.
#> #' @export
#> RunningMean <- function() {
#> .Call(RunningMean_)
#> }
#>
#> #' Add values.
#> #'
#> #' @keywords internal
#> #' @noRd
#> RunningMean_add <- function(self, values) {
#> invisible(.Call(RunningMean_add_, self, values))
#> }
#>
#> #' The mean of the values added so far.
#> #'
#> #' @keywords internal
#> #' @noRd
#> RunningMean_mean <- function(self) {
#> .Call(RunningMean_mean_, self)
#> }
#>
#> #' @noRd
#> `$.RunningMean` <- function(x, name) {
#> methods <- list("add" = RunningMean_add, "mean" = RunningMean_mean)
#> method <- methods[[name]]
#> if (is.null(method)) {
#> stop(sprintf("a RunningMean has no method `%s`; its methods are: %s", name,
#> paste(names(methods), collapse = ", ")), call. = FALSE)
#> }
#> function(...) method(x, ...)
#> }
#>
#> #' @noRd
#> print.RunningMean <- function(x, ...) {
#> cat("<RunningMean> with the methods:\n $add(values)\n $mean()\n")
#> invisible(x)
#> }
#>
#> #' @noRd
#> .DollarNames.RunningMean <- function(x, pattern = "") {
#> grep(pattern, c("add", "mean"), value = TRUE)
#> }The NAMESPACE of the package has a block that
document() manages; the lines outside it belong to the
package author, here the export of the R function
weighted_mean():
cat("export(weighted_mean)\n", file = file.path(path, "NAMESPACE"), append = TRUE)
cat(readLines(file.path(path, "NAMESPACE")), sep = "\n")
#> # Generated by rzig::document(): begin
#> useDynLib("exportspkg",
#> hello_zig_ = "hello_zig",
#> shrink_ = "shrink",
#> weighted_mean_zig_ = "weighted_mean_zig",
#> RunningMean_ = "RunningMean",
#> RunningMean_add_ = "RunningMean_add",
#> RunningMean_mean_ = "RunningMean_mean"
#> )
#> export("hello_zig")
#> export("shrink")
#> export("RunningMean")
#> S3method("$", RunningMean)
#> S3method(print, RunningMean)
#> S3method(utils::.DollarNames, RunningMean)
#> # Generated by rzig::document(): end
#> export(weighted_mean)build <- build_zig(path)
library(build$package, character.only = TRUE, lib.loc = build$library)
shrink(c(-2, 0.2, 3))
print(shrink(c(-2, 0.2, 3), amount = 1))
#> [1] -1 0 2
weighted_mean(c(1, 2, 3), c(1, 1, 2))
#> [1] 2.25
exists("weighted_mean_zig", envir = asNamespace("exportspkg"))
#> [1] TRUE
"weighted_mean_zig" %in% getNamespaceExports("exportspkg")
#> [1] FALSE
m <- RunningMean()
m$add(c(1, 2, 3))
m$add(10)
m$mean()
#> [1] 4
m
#> <RunningMean> with the methods:
#> $add(values)
#> $mean()The build files of the scaffold are templates that the package author
may extend, for example src/Makevars.in with additional
flags. update_rzig() keeps such a file and lists it, and
rzig_status() notes it; the vignette on updating rzig shows
both. The framework files under src/rzig/framework belong
to rzig and are replaced by every update.
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.