Skip to content

Feature request: make seedApply as a generic function #111

@Yunuuuu

Description

@Yunuuuu

It would be awosome if seedApply can recursely run based on the methods, for classes cannot be integrated with DelayedArray class, we cannot make seedApply work as usual as in the DelayedArray package.

BPCells provides three DelayedUnaryOp-like class, and five DelayedNaryOp-like class, but the slot names don't comply with DelayedArray class.
The differences are as follows:

  1. For DelayedUnaryOp-like class in BPCells, it use matrix slot as the seed slot of DelayedUnaryOp class in DelayedArray.
  2. For DelayedNaryOp-like class in BPCells, it use both slots (left and right), or use matrix_list to indicates the seeds slot of DelayedNaryOp-class in DelayedArray.

so I must regard all these classes as a single seed object and wrap them it into seed slot of BPCellsMatrix class (a DelayedArray object, which also is a DelayedUnaryOp object).

Now I have created another new_seedApply function and substitute the seedApply function in DelayedArray package when loaded.
the codes are below:

new_seedApply <- function(x, .fn, ...) {
    if (methods::is(x, "BPCellsMatrix")) {
        x <- entity(x)
    }
    if (methods::is(x, "BPCellsUnaryOpsSeed")) {
        return(Recall(entity(x), .fn, ...))
    }
    if (methods::is(x, "BPCellsNaryOpsSeed")) {
        x <- entity(x)
    }
    if (is.list(x)) {
        ans <- lapply(x, FUN = new_seedApply, .fn = .fn, ...)
        return(unlist(ans, recursive = FALSE, use.names = FALSE))
    } else {
        list(.fn(x, ...))
    }
}
rebind <- function(sym, value, ns) {
    if (rlang::is_string(ns)) {
        Recall(sym, value, getNamespace(ns))
        pkg <- paste0("package:", ns)
        if (pkg %in% search()) {
            Recall(sym, value, as.environment(pkg))
        }
    } else if (is.environment(ns)) {
        if (bindingIsLocked(sym, ns)) {
            unlockBinding(sym, ns)
            on.exit(lockBinding(sym, ns))
        }
        assign(sym, value, ns)
    } else {
        stop("ns must be a string or environment")
    }
}
.onLoad <- function(libname, pkgname) {
    old_seedApply <- DelayedArray::seedApply
    rebind("seedApply", function(x, FUN, ...) {
        assert_(FUN, is.function, "a function")
        if (methods::is(x, c("BPCellsMatrix", "BPCellsSeed"))) {
            new_seedApply(x, FUN, ...)
        } else {
            old_seedApply(x, FUN, ...)
        }
    }, "DelayedArray")
}

I want something like this:

methods::setGeneric("seedApply", function(x, FUN, ...) {
    standardGeneric("seedApply")
})
methods::setMethod("seedApply", "DelayedUnaryOp", function(x, FUN, ...) {
    x <- x@seed
    methods::callGeneric()
})
methods::setMethod("seedApply", "DelayedNaryOp", function(x, FUN, ...) {
    x <- x@seeds
    methods::callGeneric()
})
methods::setMethod("seedApply", "list", function(x, FUN, ...) {
    ans <- lapply(x, seedApply, FUN, ...)
    unlist(ans, recursive = FALSE, use.names = FALSE)
})
methods::setMethod("seedApply", "ANY", function(x, FUN, ...) {
    list(FUN(x, ...))
})

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions