How can one store a binary operator in a variable? - r

I am pretty confused about the meaning of the %Something% operators.
How can one store a binary operator in a variable?
Something like...
binary_operator = store.binary(%in%)
c(3,9,4,1,7) binary_operator c(1:5) # would behave alike "c(3,9,4,1,7) %in% c(1:5)"
or something like
library(foreach)
binary_operator = expression(%do%) # or expression(%dopar%)
...
...
foreach (i=1:6) binary_operator { # would behave alike "foreach (i=1:6) %do% ..."
...
...
}

If you want to define your own infix operator, it must begin and end with %. This is so the parser knows how to properly pass the parameters to the function since it not the usual way code is parsed. Also, use the backtick to escape the percent signs in the variable name.
`%binary_operator%` <- `%in%`
c(3,9,4,1,7) %binary_operator% c(1:5)

Related

Can we use user input to assign variables in Julia?

ans=readline(stdin)
function g(n)
if ans==a
return 1
else
return n
end
This is my code but the readline function only takes strings and i want it to take an expression which i can use in my function. What i want is to assign an expression (a) for variable ans.
You could try something like this:
julia> function check(x)
ans = readline()
val=Main.eval(Meta.parse(ans))
println("val == $x :", val==x)
end;
julia> check(5)
2+3
val == 5 :true
Remarks:
Your functions should not reference global variables (like ans in your example) - if you need to get the value of ans - pass it as parameter.
Parsing the expression is unsafe - a user might want for an example use this functionality to delete your data. Use with care! In some scenarios you might want for an example to use regular expressions to validate user's input.

R only specify optional parameters if specified

I have an R function with optional parameters like so:
myFunc <- function(
requiredParam,
optionalParam1 = optionalValue1,
optionalParam2 = optionalValue2,
...
optionalParamN = optionalValueN) {
# implementation
}
I have another function which calls this function and has the necessary parameters stored in a dataframe:
optionalParam1 optionalParam3 optionalParam10
1 "val1" "val2" "val3"
I only want to pass the optional parameters specified in the dataframe. For the others, I want it to use the default values. How can I accomplish this without typing up all permutations of optionalParameters existing/not existing?
Call the function using do.call (not knowing what your data.frame is called I will just assume you have a list or something of the parameters called myParams):
do.call(myFunc, as.list(myParams))
You can also build your function call as a string by parsing your dataframe column names and using paste.
Then, use eval(parse(text="your string"))

checking if data types are appropriate and returning an error message if not

I want to return my error message if arguments passed to the function are not of the required type (character)
if (!typeof(param1) == "character" || !typeof(param2) == "character") {
stop("You must provide valid arguments")
}
This only works if I provide invalid arguments. How can I ensure the message is displayed if some of the parameters are missing, because if doesn't work if I call the function without any parameters ?
You can use missing() to check whether an argument is provided. This is very much preferred over the other answers that suggest using default values that are of a different type than what expected (how confusing!). Only use defaults when it makes sense to have a default.
Also, it is not a good idea to use typeof() for type checking, in general. The typeof() function returns how the data are stored in the R implementation. Usually, a function cares whether an object presents a particular API, which corresponds to the class. To check inheritance, use is(). But in this case, for both readability and just to follow conventions, consider using is.character().
So you might have something like:
if (missing(param1) || !is.character(param1)) {
stop("'param1' must be provided as a character vector")
}
Also, things to keep in mind when checking vectors:
Often we really are expecting a scalar, i.e., a length-one vector, but a vector can have arbitrary length, so we should check that it is of length one.
Vectors can contain missing values, which code often cannot handle, so we often need to ensure that the values are not missing.
You might find it useful to define helpers for this, such as this function from the S4Vectors package in Bioconductor:
isSingleString <- function (x)
{
is.character(x) && length(x) == 1L && !is.na(x)
}
Then:
if (missing(param1) || !isSingleString(param1)) {
stop("param1 must be a single, non-NA string")
}
To ensure not to have problms with misisng parameters, you should provide default arguments.
Use stopifnot, it is designed to check arguments.
here how I would do this:
func_check <-
function(param1="",param2=""){
stopifnot(typeof(param1) == "character",
typeof(param2) == "character")
}
## param2 is numeric
func_check(param1= 'a',param2=2)
## param2 is missing
func_check(param1= 1)
EDIT
In case you want to check for missing values , toy shoudl use dotted parameters. Then you can deal it with using the match.call. Here an example where I test for missings and not valid parameters.
func_check <-
function(...){
ll <- as.list((match.call()[-1]))
stopifnot(c('param1','param2' )%in% names(ll))
param1 = ll$param1
param2 = ll$param2
stopifnot(typeof(param1) == "character",
typeof(param2) == "character")
}
func_check(param1= 'a',param2=2)
If I define the following function:
myfunc <- function(param1, param2, numeric1, param3) {
if (!is.character(param1) || !is.character(param2)) {
stop("You must provide valid arguments for param1 and param2")
} else if(!is.numeric(numeric1)) {
stop("Please provide numeric input")
} else if(!is.character(param3)){
stop("Please provide character input for param3")
}
#some code here for your function, e.g.
paste0(param1, param2, numeric1, param3)
}
It throws an error whenever I don't give it 4 input parameters in the call of myfunc, including if I call it without any arguments (so the error occurs both if aguments are missing and when they are not of the correct type). Is that different from what you are looking for?

using callCC with higher-order functions in R

I'm trying to figure out how to get R's callCC function for short-circuiting evalutation of a function to work with functions like lapply and Reduce.
Motivation
This would make Reduce and and lapply have asymptotic efficiency > O(n), by allowing you to
exit a computation early.
For example, if I'm searching for a value in a list I could map a 'finder' function across the list, and the second it is found lapply stops running and that value is returned (much like breaking a loop, or using a return statement to break out early).
The problem is I am having trouble writing the functions that lapply and Reduce should take using a style that callCC requires.
Example
Say I'm trying to write a function to find the value '100' in a list: something equivalent to
imperativeVersion <- function (xs) {
for (val in xs) if (val == 100) return (val)
}
The function to pass to lapply would look like:
find100 <- function (val) { if (val == 100) SHORT_CIRCUIT(val) }
functionalVersion <- function (xs) lapply(xs, find100)
This (obviously) crashes, since the short circuiting function hasn't been defined yet.
callCC( function (SHORT_CIRCUIT) lapply(1:1000, find100) )
The problem is that this also crashes, because the short circuiting function wasn't around when find100 was defined. I would like for something similar to this to work.
the following works because SHORT_CIRCUIT IS defined at the time that the function passed to lapply is created.
callCC(
function (SHORT_CIRCUIT) {
lapply(1:1000, function (val) {
if (val == 100) SHORT_CIRCUIT(val)
})
)
How can I make SHORT_CIRCUIT be defined in the function passed to lapply without defining it inline like above?
I'm aware this example can be achieved using loops, reduce or any other number of ways. I am looking for a solution to the problem of using callCC with lapply and Reduce in specific.
If I was vague or any clarification is needed please leave a comment below. I hope someone can help with this :)
Edit One:
The approach should be 'production-quality'; no deparsing functions or similar black magic.
I found a soluton to this problem:
find100 <- function (val) {
if (val == 100) SHORT_CIRCUIT(val)
}
short_map <- function (fn, coll) {
callCC(function (SHORT_CIRCUIT) {
clone_env <- new.env(parent = environment(fn))
clone_env$SHORT_CIRCUIT <- SHORT_CIRCUIT
environment(fn) <- clone_env
lapply(coll, fn)
})
}
short_map(find100, c(1,2,100,3))
The trick to making higher-order functions work with callCC is to assign the short-circuiting function into the input functions environment before carrying on with the rest of the program. I made a clone of the environment to avoid unintended side-effects.
You can achieve this using metaprogramming in R.
#alexis_laz's approach was in fact already metaprogramming.
However, he used strings which are a dirty hack and error prone. So you did well to reject it.
The correct way to approach #alexis_laz's approach would be by wrangling on code level. In base R this is done using substitute(). There are however better packages e.g. rlang by Hadley Wickham. But I give you a base R solution (less dependency).
lapply_ <- function(lst, FUN) {
eval.parent(
substitute(
callCC(function(return_) {
lapply(lst_, FUN_)
}),
list(lst_ = lst, FUN_=substitute(FUN))))
}
Your SHORT_CIRCUIT function is actually a more general, control flow return function (or a break function which takes an argument to return it). Thus, I call it return_.
We want to have a lapply_ function, in which we can in the FUN= part use a return_ to break out of the usual lapply().
As you showed, this is the aim:
callCC(
function (return_) {
lapply(1:1000, function (x) if (x == 100) return_(x))
}
)
Just with the problem, that we want to be able to generalize this expression.
We want
callCC(
function(return_) lapply(lst, FUN_)
)
Where we can use inside the function definition we give for FUN_ the return_.
We can let, however, the function defintion see return_ only if we insert the function definition code into this expression.
This exactly #alexis_laz tried using string and eval.
Or you did this by manipulating environment variables.
We can safely achieve the insertion of literal code using substitute(expr, replacer_list) where expr is the code to be manipulated and replacer_list is the lookup table for the replacement of code.
By substitute(FUN) we take the literal code given for FUN= for lapply_ without evaluating it. This expression returns literal quoted code (better than the string in #alexis_laz's approach).
The big substitute command says: "Take the expression callCC(function(return_) lapply(lst_, FUN_)) and replace lst_ in this expression by the list given for coll and FUN_ by the literal quoted expression given for FUN.
This replaced expression is then evaluated in the parent environment (eval.parent()) meaning: the resulting expression replaces the lapply_() call and is executed exactly where it was placed.
Such use of eval.parent() (or eval( ... , envir=parent.frame())) is fool proof. (otherwise, tidyverse packages wouldn't be production level ...).
So in this way, you can generalize callCC() calls.
lapply_(1:1000, FUN=function(x) if (x==100) return_(x))
## [1] 100
I don't know if it can be of use, but:
find100 <- "function (val) { if (val == 100) SHORT_CIRCUIT(val) }"
callCC( function (SHORT_CIRCUIT) lapply(1:1000, eval(parse(text = find100))) )
#[1] 100

R unary operator overload: risks?

In my continuing quest to avoid using parentheses for some simple commands, I wrote up the following operator to create a new graphics window. My question is: am I at risk of "breaking" anything in R, other than the obvious inability to execute the "not" function on my variable "newdev"?
# function to overload "!" for one purpose only
#this is adapted from the sos package code for "???", credited to Duncan Murdoch.
# Example of how to create a specialized unary operator that doesn't require
# parentheses for its argument. So far as I can tell,
#the only way to do this is to overload an existing function or
# operator which doesn't require parentheses. "?" and "!" meet this requirement.
`!` <- function (e1, e2) {
call <- match.call()
# match.call breaks out each callable function in argument list (which was "??foo" for the sos package "???",
# which allows topicExpr1 to become a list variable w/ callable function "!" (or "?" in sos)
original <- function() {
call[[1]]<-quote(base::`!`)
return(eval(call, parent.frame(2)))
}
# this does preclude my ever having an actual
# variable called "newdev" (or at least trying to create the actual NOT of it)
if(call[[2]] =='newdev') {
windows(4.5,4.5,restoreConsole=T)
}else{
return(original()) # do what "!" is supposed to do
}
}
I executed "!" = function(a){stop("'NOT' is used")} and executed the replications function, which uses the ! operator, and this worked fine. So it looks like it is safe to override "!".
Still you probably want to use classes, which you can do as follows:
# Create your object and set the class
A = 42
class(A) = c("my_class")
# override ! for my_class
"!.my_class" = function(v){
cat("Do wathever you want here. Argument =",v,"\n")
}
# Test ! on A
!A
with
makeActiveBinding
you can replace ls() by e.g LS w/o need of unary operators

Resources