Code Monkey home page Code Monkey logo

mod's Introduction

mod::ule

AppVeyor build status Travis build status codecov CRAN status CRAN License Lifecycle: maturing

The mod package provides a simple and friendly way to structure program and data into flexible and independent units for programming and interactive use. Modules indtroduced by the mod package offer merits and conveniences currently absent from R.

Why?

Programs need to be oraganized into units.

A package is a very robust solution, but is formal and compliated; packages require additional knowledge to R and must be installed in the local library by install.packages(); it is not easy to manage different versions of the same package. On the other hand, simple R scripts, often executed by source(), are brittle and may create namespace conflict; They are unsuitable for building tools and applications.

Modules fills the hollow middleground by allowing programs to live separately and work together at the same time. Each module has its own scope, host is own objects, an can each use different packages without interefering with each other or the user’s global search path. They can be created either inline along other programs or from a standalone file, and can be used in the user’s working environment, as a part of a package, or in other modules.

Installation

Install the published version from CRAN with:

install.packages("mod")

Install the development version from GitHub with:

devtools::install_github("iqis/mod")

Vocabulary

The mod package has a simple UI:

  • Make a module:
    • Inline:module()/mod::ule()
    • From a file: source_module()
  • The search path:
    • Attach a module: use()
    • Detach a module: drop()
  • Inside a module:
    • Declare public objects: provide()
    • Attach a package locally: require()
    • Copy objects from another module: refer()
    • Name the module: name()

Quickstart

my_numbers <- mod::ule({
        numbers <- c(1,2,2,2,3,3,4,5,6)
})

my_plot <- mod::ule({
        refer(my_numbers)
        numbers_plot <- function(x = numbers) {
                plot(x, col = "purple", pch = 15)
                title("Numbers", ylab = "Value")
        }
})

my_numbers$numbers
#> [1] 1 2 2 2 3 3 4 5 6
my_plot$numbers_plot()

Documentation

mod website

mod's People

Contributors

iqis avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar

mod's Issues

When to use `mod` or `R6`

If you have to make copies of a module, or have mutable state, use R6.
If you need to attach different packages to an object, use mod.

Benefit of module over packages

Sometimes you may feel the need of using a package to organize your code. But you would then have to go through the formalities of making one, install it in your own machine (publish it somewhere, and instruct your collaborators to install it),
With mod, your components can ship with any existing code. Each module has their own local search path, so you can attach whatever package you need to each mod::ule, without one conflicting with another.

20190809_KEW_comments

Feel free to incorporate or dismiss these suggestions. Let me know if clarification is needed on any points.

Meta

  • more explicit, real-life examples of why and when mod is useful
  • "inst/misc/example_module.R" could be an interesting, real-life example
  • remove empty author line in DESCRIPTION
  • clarify (in docs and code) the difference between mod::ule() and mod::module()

Food for thought

  • how might mod support psyphr? That might be a good approach to building a real-world example.

Language, description, and accessibility

  • split README into vignettes
  • fix typos and syntactical and grammatical errors (how would you like me to point those out?) (e.g., "declair" = a delicious declaration at breakfast)
  • delete unnecessary phrases in README and documentation (e.g., "This is a good question.")
  • reduce the use of semi-colons and use hyphens where appropriate
  • examples of approaches to modules in other languages
  • let users know they can use require() OR library() (don't find the crowd; guide its directions)
  • what does "spare qualification" mean?
  • double-check code style in vignettes (e.g., spacing, assignment conventions, etc.)
  • use complete sentences ("Another way is using provide() function to declair public variables, while all others become private" is missing a thing or two.)
  • don't assume your readers understand immediately (e.g., "The following demonstration should be self-explanatory..."
  • consider an alternative to "we feel"; you are the sole author, and feelings have nothing to do with this.
  • move terms and definitions to beginning of README, or consider a separate vignette with only terms and definitions at start of user experience

Code

  • showing my ignorance: Why do we have to quote a mod in drop() but not in use()? (e.g., drop("my_test_mod") vs. use(my_test_mod)
  • in the 'refer()' documentation or warnings (beyond default), it would be useful to let the user know that refer() will mask assignments from the previous module.
    e.g.,
my_other_test_mod <- mod::module({
refer(my_test_mod)
a <- 1
b <- 2
})
  • In regard to above comment, you might also consider an implementation tool that helps the user compare the contents of each module before a mask occurs. I am reminded of the option to compare versions within Microsoft. Would a function that compares the contents of two modules be feasible?

20190808 CRAN Feedback

  • Thanks, please check the first sentence of your Description text. Does
    it make sense?

  • You have examples for unexported functions which cannot run in this way.
    Please either add mod::: to the function calls in the examples, omit
    these examples or export these functions.

  • You are using installed.packages():
    "This needs to read several files per installed package, which will be
    slow on Windows and on some network-mounted file systems.
    It will be slow when thousands of packages are installed, so do not use
    it to find out if a named package is installed (use find.package or
    system.file) nor to find out if a package is usable (call
    requireNamespace or require and check the return value) nor to find
    details of a small number of packages (use packageDescription)."
    [installed.packages() help page]

  • Please fix and resubmit.

allow acquire()ing packages?

pkg <- asNamespace("'pkg_name")
pkg$fun()

In corporate asNamespace() into acquire(), which would, search for package first and then module??

This will have the same behavior inside or outside a module.

Why mod::ule does not support rename on every front

Why isn't the object named how you wanted to use it in the first place? The R way is to keep things named as they are, and that's better. node.js's exports.something = something is completely redundant, and I can't count how many times I have to tell a Python novice that the name of BeautifulSoup package is not "BeautifulSoup".

De-emphasis source_module()

and promote using inline definitions of modules in examples and future functionalities.

When developing reusable components, modules should not stand alone, but rather be subordinate to a packcage.

On scoping

modules should have normal behavior as with any other R object, and maintain chain of environment, so that the user is not surprised by not being able to access names in a seemingly outer scope.

by default:

  • Inline module defined by module() live in the calling scope through parent.frame().
  • thing() too.
  • acquire(), too now.

Ban `<<-`

<<- assigns the value to the name where first found, if not, make new at global environment. BAD!
put this in the module mask.

package name: mo, mod, modu?

name the package mod so that the package can be used when not attached?
Along the vein of emo, and emo::ji(), mod and...

  • mo::dule()
  • modu::le()
  • mod::ule()?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.