Skip to content

Commit

Permalink
Replace use of <- by =
Browse files Browse the repository at this point in the history
  • Loading branch information
klmr committed Jun 16, 2014
1 parent 6718f97 commit a43b35a
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 62 deletions.
60 changes: 30 additions & 30 deletions functional.r
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@

# Basic helpers {{{

id <- function (x) x
id = function (x) x

# This uses R's peculiarities in argument matching explained here:
# <http://stat.ethz.ch/R-manual/R-devel/doc/manual/R-lang.html#Argument-matching>
# `.expr` starts with a dot to allow `expr` being used in the actual
# expression.
let <- function (.expr, ...)
let = function (.expr, ...)
eval(substitute(.expr), list2env(list(...), parent = parent.frame()))

#' Create a closure over a given environment for the specified formals and body.
closure <- function (formals, body, env)
closure = function (formals, body, env)
eval(call('function', as.pairlist(formals), body), env)

#' A shortcut to create a function
Expand Down Expand Up @@ -70,22 +70,22 @@ closure <- function (formals, body, env)
#'
#' @note This is the opposite from the (wrongly-named) \code{roxygen::Curry}:
#'
#' \code{minus <- function (x, y) x - y
#' \code{minus = function (x, y) x - y
#' partial(minus, 5)(1) == -4}
#'
#' But:
#'
#' \code{partial(minus, x = 5)(1) == 4}
#'
partial <- function (f, ...)
partial = function (f, ...)
let(capture = list(...),
function (...) do.call(f, c(list(...), capture)))

lpartial <- function(f, ...)
lpartial = function(f, ...)
let(capture = list(...),
function (...) do.call(f, c(capture, list(...))))

ppartial <- function (f, arg, ...)
ppartial = function (f, arg, ...)
let(capture = list(...), arg = as.character(substitute(arg)),
function (x) do.call(f, c(setNames(x, arg), capture)))

Expand All @@ -94,95 +94,95 @@ ppartial <- function (f, arg, ...)
# syntactic noise.
# Not something I would normally do but there's precedence in R; consider `c`.

p <- partial
lp <- lpartial
pp <- ppartial
p = partial
lp = lpartial
pp = ppartial

#' Compose functions \code{g} and \code{f}.
#'
#' \code{compose(g, f)(...) = g(f(...))}.
#'
#' @note Functions are applied in the inverse order of \code{roxygen::Compose}:
#' \url{http://tolstoy.newcastle.edu.au/R/e9/help/10/02/4529.html}
compose <- function (g, f)
compose = function (g, f)
function (...) g(f(...))

#' Dot operator (as in Haskell)
`%.%` <- compose
`%.%` = compose

#' Function chaining operator (as in F#)
`%|>%` <- function (g, f) compose(f, g)
`%|>%` = function (g, f) compose(f, g)

#' Pipe operator as in Bash
`%|%` <- function (x, y) y(x)
`%|%` = function (x, y) y(x)

# }}}

# Higher-order list functions {{{

#' Applies a list of functions to the same argument.
#' @TODO Extend to more than one argument
fapply <- function (x, ...)
fapply = function (x, ...)
lapply(list(...), function (f) f(x))

# What is up with the naming of these (standard R) functions?

map <- base::Map
map = base::Map

reduce <- base::Reduce
reduce = base::Reduce

# Hides `stats::filter` but I don't care.
filter <- base::Filter
filter = base::Filter

# }}}

# Helpers for working with ranges {{{

#' @TODO Handle negative indices?
boolmask <- function (indices, length)
boolmask = function (indices, length)
is.element(1 : length, indices)

indices <- seq_along
indices = seq_along

#' Conditionally count elements.
count <- length %.% which
count = length %.% which

#' Wrapper around \{order} that returns the ordered data rather than the index
#' permutation.
#'
#' Like \code{sort}, but allows specifying multiple sort keys.
sorted <- function (data, ..., decreasing = FALSE)
sorted = function (data, ..., decreasing = FALSE)
let(key = if (length(list(...)) == 0) colnames(data) else list(...),
data[do.call(order, c(lapply(key, lp(`[[`, data)), decreasing = decreasing)), ])

#' Like \code{c}, for dictionaries (\code{list}s with names).
#'
#' @examples
#' cdict(list(a=1, b=NULL), list(a=NULL, b=2), list(c=3)) # list(a=1, b=2, c=3)
cdict <- function (...) {
lists <- list(...)
names <- reduce(union, map(names, lists))
cdict = function (...) {
lists = list(...)
names = reduce(union, map(names, lists))

nonnull <- function (n, a, b) if (is.null(a[[n]])) b[[n]] else a[[n]]
nonnull = function (n, a, b) if (is.null(a[[n]])) b[[n]] else a[[n]]
reduce(function (a, b) map(function (n) nonnull(n, a, b), names), lists)
}

# }}}

#' Create an item selector function for a given item
item <- lp(p, `[[`)
item = lp(p, `[[`)

items <- lp(p, `[`)
items = lp(p, `[`)

#' Negate a function.
#'
#' Similar to \code{base::Negate}
neg <- p(compose, `!`)
neg = p(compose, `!`)

#' @TODO Add %or% and %and% analogously

#' Use the first value if present, else the second
#'
#' Corresponds to the null-coalesce operator \code{??} in C#
`%else%` <- function (a, b)
`%else%` = function (a, b)
if(is.null(a) || is.na(a) || is.nan(a) || length(a) == 0) b else a
18 changes: 9 additions & 9 deletions graphics.r
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@
import('./functional', attach = TRUE)

# Color helper functions {{{
transparent <- function (colors, alpha = 0.5) {
c <- col2rgb(colors)
transparent = function (colors, alpha = 0.5) {
c = col2rgb(colors)
rgb(c['red', ], c['green', ], c['blue', ], alpha * 255, maxColorValue = 255)
}

lighten <- function (colors, factor = 0.5) {
c <- col2rgb(colors)
l <- function (c) 255 * factor + c * (1 - factor)
lighten = function (colors, factor = 0.5) {
c = col2rgb(colors)
l = function (c) 255 * factor + c * (1 - factor)
rgb(l(c['red', ]), l(c['green', ]), l(c['blue', ]), maxColorValue = 255)
}

darken <- function (colors, factor = 0.5) {
c <- col2rgb(colors)
d <- function (c) c * (1 - factor)
darken = function (colors, factor = 0.5) {
c = col2rgb(colors)
d = function (c) c * (1 - factor)
rgb(d(c['red', ]), d(c['green', ]), d(c['blue', ]), maxColorValue = 255)
}

hsv2col <- function (col)
hsv2col = function (col)
apply(col, COLS, lpartial(do.call, hsv) %.% as.list)
# }}}
22 changes: 11 additions & 11 deletions io.r
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# I/O helper functions

#' Add \code{ext}ension parameter to \link{\code{base::file.path}}
file.path <- function (..., ext = NULL, fsep = .Platform$file.sep) {
dots <- list(...)
file.path = function (..., ext = NULL, fsep = .Platform$file.sep) {
dots = list(...)
if (! is.null(ext)) {
ilast <- length(dots)
dots[ilast] <- sprintf('%s.%s', dots[ilast], sub('^\\.', '', ext))
ilast = length(dots)
dots[ilast] = sprintf('%s.%s', dots[ilast], sub('^\\.', '', ext))
}

do.call(base::file.path, c(dots, fsep = fsep))
Expand All @@ -16,18 +16,18 @@ file.path <- function (..., ext = NULL, fsep = .Platform$file.sep) {
#' For the moment, only separators are handled based on the file extension.
#' This might change in the future to be more powerful, think Python’s
#' \code{csv.Sniffer} class.
read.table <- function (file, ..., text) {
args <- list(...)
read.table = function (file, ..., text) {
args = list(...)
if (missing(file))
return(do.call(utils::read.table, c(args, text = text)))

if (! ('sep' %in% names(args))) {
separators <- list('.csv' = ',',
'.tsv' = '\t')
extension <- rxmatch('\\.(\\w+)$', file)
args$sep <- separators[[extension]]
separators = list('.csv' = ',',
'.tsv' = '\t')
extension = rxmatch('\\.(\\w+)$', file)
args$sep = separators[[extension]]
}

args$file <- file
args$file = file
do.call(utils::read.table, args)
}
8 changes: 4 additions & 4 deletions seq.r
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Sequence analysis basics

#' Reverse complement sequences
revcomp <- function (strs) {
rc <- function (str) {
bases <- strsplit(str, '')[[1]]
compl <- vapply(bases, partial(switch, A='T', C='G', G='C', T='A'), '')
revcomp = function (strs) {
rc = function (str) {
bases = strsplit(str, '')[[1]]
compl = vapply(bases, partial(switch, A='T', C='G', G='C', T='A'), '')
paste(rev(compl), collapse = '')
}
vapply(strs, rc, '')
Expand Down
12 changes: 6 additions & 6 deletions strings.r
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@

import('./functional', attach = TRUE)

lstrip <- lp(sub, '^ +', '')
lstrip = lp(sub, '^ +', '')

rstrip <- lp(sub, ' +$', '')
rstrip = lp(sub, ' +$', '')

strip <- lstrip %.% rstrip
strip = lstrip %.% rstrip

# FIXME Vectorize
rev <- p(paste, collapse = '') %.% base::rev %.% item(1) %.% p(strsplit, '')
rev = p(paste, collapse = '') %.% base::rev %.% item(1) %.% p(strsplit, '')

capitalize <-
capitalize =
p(fapply, toupper %.% p(substring, 1, 1), p(substring, 2)) %|>%
lp(do.call, paste0)

#' @TODO Make vectorised
readable <- capitalize %.% lp(gsub, '_|-', ' ')
readable = capitalize %.% lp(gsub, '_|-', ' ')
4 changes: 2 additions & 2 deletions system.r
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#' Silence all output from an expression by redirecting the sink
silent <- function (.expr) {
silent = function (.expr) {
on.exit(sink())
sink(file = (if (Sys.info()['sysname'] == 'Windows') 'NUL' else '/dev/null'))
sink(if (Sys.info()['sysname'] == 'Windows') 'NUL' else '/dev/null')
eval(.expr, envir = parent.frame())
}

0 comments on commit a43b35a

Please sign in to comment.