On Monoids and Folds

— Christopher R. Genovese

Plan #

Here we will work through the beginning of HW1 and use it as a platform for the ideas and also tooling/practices such as:

git
creating and using a repository
package
basic practice
command line driver
creating a stub that satisfies the requirements
structuring data and behavior
classes/methods or similar
types
basic type thinking

Initial steps #

Creating a package #

Create a work directory; we will create a package within that directory, separating our application code from our computational code.

use_this

install.packages("usethis")
library(usethis)
path <- file.path("pkgname")
create_package(path)
proj_activate(path)
# use_mit_license("My Name")
# use_package("ggplot2", "Suggests")
use_readme_md()
# use_news_md()
use_test("basic-test")
# use_data(x, y)  # saves data as dependencies
use_git()

Creating a git repository #

#
# configuring git
#

git config --global user.name "Your Name"
git config --global user.email "youremail@example.com"

# Visual Studio Code:
git config --global core.editor "code --wait"

# Emacs:
# There are various options here
# A good choice: put (server-start) in your init file and use
git config --global core.editor emacsclient

# Vim:
git config --global core.editor vim

# Also: core.autocrlf and credential.helper  See setup

# Create or move to a working directory
cd
mkdir ~/s750
cd ~/s750


#
# Initializing a repository
#

cd mfolds     or   cd ~/s750-lecture/mfolds
git init
git status

#
# Workflow
# change -> stage -> commit workflow
# Start with some simple files (your package)
#

git status
git diff

git add __file__
git add __file1__ __file2__ ... __filen__
git add __directory__
git add -p

git add .
git add -A

git status

git commit
git commit -m "A commit message"

Creating a driver #

  • In R, try optparse
  • In Python, optparse or click

File structure:

#!/usr/bin/env Rscript

main <- function() {
    # Simple style:  args <- commandArgs(trailingOnly = True)
    # or ... see also optparse package
    option_list <- list(
        make_option(c("-v", "--version"), action="store_true", default=FALSE,
            help="Print version and exit"),
        make_option(c("-q", "--quietly"), action="store_false",
            dest="verbose", help="Print little output"),
        make_option(c("-c", "--count"), type="integer", default=5,
            help="Number of random normals to generate [default %default]",
            metavar="number"),
        make_option("--generator", default="rnorm",
            help = "Function to generate random deviates [default \"%default\"]"),
        make_option("--mean", default=0,
            help="Mean if generator == \"rnorm\" [default %default]"),
        make_option("--sd", default=1, metavar="standard deviation",
            help="Standard deviation if generator == \"rnorm\" [default %default]")
        )

    # get command line options into a list
    # If help option encountered print help and exit;
    # otherwise if options not found on command line then set defaults,
    opt <- parse_args(OptionParser(option_list=option_list))

    # print some progress messages to stderr if "quietly" wasn't requested
    if ( opt$version ) {
        # print version and exit
        # ...
    }

    #...
}


main()
from optparse import OptionParser

# ...

parser = OptionParser()
parser.add_option("-f", "--file", dest="filename",
                  help="write report to FILE", metavar="FILE")
parser.add_option("-q", "--quiet",
                  action="store_false", dest="verbose", default=True,
                  help="don't print status messages to stdout")
parser.add_option("-q", "--quiet",
                  action="store_false", dest="verbose", default=True,
                  help="don't print status messages to stdout")

(options, args) = parser.parse_args()


if __name__ == '__main__':
    main()
# ...


######## Or with click

import click

from mypkg.__about__ import __version__

from mypkg.subcmd1 import main as subcmd1
from mypkg.subcmd2 import main as subcmd2

CONTEXT_SETTINGS = {
    "help_option_names": ["-h", "--help"]
}

@click.group(context_settings=CONTEXT_SETTINGS, invoke_without_command=True)
@click.version_option(version=__version__, prog_name="mypkg")
def main():
    pass

@main.command()
def cmd1():
    subcmd1()

@main.command()
def cmd2():
    subcmd2()

Try Puzzle 1 #

Folds and Type Specifications #

Steps before next Tuesday #

  • Finish Puzzle 1 (put functions for each in your driver and call them from main)

    Stage and commit any changes you make

  • Try Puzzle 2

  • Decide on an options parsing package and implement a simple interface for your driver, handling --help and --version for now. Without arguments or options, either print usage or the results of your puzzle 1 computations.

    Stage and commit any changes you make

  • Fill in the package metadata you need to make your package correct (e.g., DESCRIPTION for R folks). It would be good to add a README.md markdown file with some boilerplate for now.

    Stage and commit any changes you make

  • Read the assignment through at least Subtask 1 and preferably 2 or 3. Move forward on these steps if you can, but don’t worry if not.

  • Try Puzzle 3

  • Ask questions