Rebol anonymous function behavior is weird - functional-programming

My anonymous func test below is executed only once:
repeat i 5 [
func[test][
print test
] rejoin ["test" i]
]
I am obliged to name it to be able to execute it 5 times as expected:
repeat i 5 [
test: func[test][
print test
] test rejoin ["test" i]
]
This is weird. isn't it really possible to use anonymous function in loops ?

Your first code example simply defines the anonymous function five times. It does not invoke it. Add a do and all should be well:
repeat i 5 [
do func[test][
print test
] rejoin ["test" i]
]
test1
test2
test3
test4
test5

Related

Why isn't my code working inside a function I created, but works when I run it in the global environment?

So I have a dataframe "fish8" and I tried writing a function that excludes all empty rows for three of the dataframe's columns (BIN, collectors, country). The thing is the code isn't being run inside the function, but it runs outside of it. I have many other similar functions in the script and they work, why isn't this one working?
#so it doesn't work when I run it like this
remove_empties=function(fish8){
fish8<<-fish8[!(fish8$BIN == "" | is.na(fish8$BIN)), ]
fish8<<-fish8[!(fish8$collectors == "" | is.na(fish8$collectors)), ]
fish8<<-fish8[!(fish8$country == "" | is.na(fish8$country)), ]
}
remove_empties(fish8)
#but it runs like this
fish8<-fish8[!(fish8$BIN == "" | is.na(fish8$BIN)), ]
fish8<-fish8[!(fish8$collectors == "" | is.na(fish8$collectors)), ]
fish8<-fish8[!(fish8$country == "" | is.na(fish8$country)), ]
The problem is related to the scope of variables. In this case, the function's variable fish8 is getting assigned within the function scope. The original fish8 doesn't get touched. See https://www.r-bloggers.com/dont-run-afoul-of-scoping-rules-in-r/ :
What happens with <<- is that it starts walking up the environment tree from child to parent until it either finds a match, or ends up in the global (top) environment. This is a way to initiate a tree-walk (like automatic searching) but with dire consequences because you are making an assignment outside of the current scope! Only the first match it finds will get changed, whether or not it is at the global environment.
Your options include:
Remove the double assignment and reassign the results of the function to the original dataframe
remove_empties = function(fish8) {
fish8 <- fish8[!(fish8$x == '' | is.na(fish8$x)), ]
fish8 <- fish8[!(fish8$y == '' | is.na(fish8$y)), ]
}
fish8 <- remove_empties(fish8)
Using a different variable within the function which would be better practice than having the same variable name in two different environments.
remove_empties2 = function(fish) {
fish <- fish[!(fish$x == '' | is.na(fish$x)), ]
fish <- fish[!(fish$y == '' | is.na(fish$y)), ]
}
fish8 <- remove_empties2(fish8)
Change the variable name in the function but globally assigning the original variable. I don't like this route:
remove_empties3 = function(fish) {
fish8 <<- fish[!(fish$x == '' | is.na(fish$x))
& !(fish$y == '' | is.na(fish$y)), ]
}
remove_empties3(fish8)
My favorite option: reassigning the empty strings as NA and then using na.omit(). I'd also forgo the function call - this at most one extra line than a function call and should only have to be done once as empty strings shouldn't be re-introduced:
fish8[fish8==''] <- NA_character_
fish8 <- na.omit(fish8)
Data:
set.seed(1)
x <- sample(c('',NA_character_, letters[1:5]), 20, replace = T)
y <- sample(c('', NA_character_, letters[6:10]), 20, replace = T)
fish8 <- data.frame(x, y)

How to make blocks of unit tests in R?

I have started to make unit-tests for my functions in R, using svUnit (docs). I have done the test for the functions in a file, then for the ones in another file, and I have created a mainTest, where I call all the tests. So my project looks like this:
proj
|-src
| |-functions1 (containing some functions)
| |-functions2 (containing some other functions)
| |-functions3 (containing some more functions)
| |-mainFile (here I call the functions in the files above)
|-tests
|-functions1Test (containing tests for functions in functions1 file)
|-functions2Test (containing tests for functions in functions2 file)
|-functions3Test (containing tests for functions in functions3 file)
|-mainTest (containing the function that runs all the tests)
a functionsXTest file looks like this:
source('functionsX.R')
test(fun1) <- function(){
# call the fun1 function and check the result
}
test(fun2) <- function(){
# call the fun2 function and check the result
}
# ...
functions1Tests <- svSuite(svSuiteList()) # here
The mainTests looks like this:
library('svUnit')
source('functions1Tests.R')
source('functions1Tests.R')
source('functions1Tests.R')
launchTests <- function(){
clearLog()
runTest(functions1Tests)
runTest(functions2Tests)
runTest(functions3Tests)
Log()
}
I thought that the last line at the end of the file functionsXTest.R is grouping the unit tests in a variable, but it seems that it is grouping all the tests in that variable, so functions1Tests is containing the tests for all the functions in functions1.R, and functions2Tests is containing the tests in functions1.R and functions2.R. Is there a possibility to have all the tests in a file grouped in a variable and the run the tests on each variable, so it will be easier to find the problematic test?
I have found that if I add the names of the tests in svSuite, it is separates the different tests, so doing:
functions1Tests <- svSuite("fun1", "fun2")
on the last line of the functionsXTest.R file, functions2Tests will not contain the tests for functions1Test.R.
But now I am wondering if there is a possibility to split the test in the Log, because now it will display something like:
> launchTests()
= A svUnit test suite run in less than 0.1 sec with:
* testfun1 ... OK
* testfun1 ... OK
* testfun2 ... OK
* ...
== testfun1 (in runitfunctions1Test.R) run in less than 0.1 sec: OK
//Pass: 7 Fail: 0 Errors: 0//
== testfun1 (in runitfunctions2Test.R) run in less than 0.1 sec: OK
//Pass: 4 Fail: 0 Errors: 0//
== testfun2 (in runitfunctions1Test.R) run in less than 0.1 sec: OK
//Pass: 10 Fail: 0 Errors: 0//
...

test that function in r does not work

library(Rcpp)
cppFunction("
int fib(int n)
{
if (n < 2)
return(n);
return( fib(n-1) + fib(n-2) );
}
")
My task is to write several tests to show whether the case is wrong or not.
However, the wrong messages are as follows.
Error during wrapup: Test failed: 'Test cppFunction'
* Not expected: 3 not equal to equals(2)
Modes of target, current: function, numeric
target, current do not match when deparsed.
* Not expected: 5 not equal to equals(5)
Modes of target, current: function, numeric
target, current do not match when deparsed.
* Not expected: 10 not equal to equals(55)
Modes of target, current: function, numeric
target, current do not match when deparsed.
* Not expected: 8 code did not generate an error.
* Not expected: 6 code did not generate an error.
* Not expected: 9 code did not generate an error.
###test that###
library(testthat)
context("Test cppFunction")
##do not know why??
test_that("Test cppFunction",{
expect_equal(3,equals(2))
expect_equal(5,equals(5))
expect_equal(10,equals(55))
expect_error(8,equals(20))
expect_error(6,equals(7))
expect_error(9,equals(25))
})
I cannot figure out why the test that does not work.
First of all, you never even call you fib function in the tests. You should have something like
test_that("Test cppFunction",{
expect_equal(fib(3),2)
expect_equal(fib(5),5)
expect_equal(fib(10),55)
})
Also usage of expect_error is wrong, since fib function is not supposed to produce errors as it is implemented now. I suspect that you wanted to test for non-equality. But that does not make sense, if function does not produce the wrong result you expect, it does not mean that function is right. I would advice just to write more expect_equal tests. If you still want to do that, just write something like
expect_false(fib(10) == 22)
In the end your test should look something like
test_that("Test cppFunction",{
expect_equal(fib(3),2)
expect_equal(fib(5),5)
expect_equal(fib(10),55)
expect_false(fib(8) == 20)
expect_false(fib(6) == 7)
expect_false(fib(9) == 25)
})

Create output file in matlab containing numeric and string cells

I am currently working on a project where I have to program the same tool both in Matlab and R and compare both software options.
I started in R and now I am translating the code to Matlab but I am now stuck at the most important part. The output file that the tool creates after doing the analysis.
Basically, my tool makes an analysis that loops n times, and after each loop I get many variables that go into an output table. So, to be more clear, after each loop I get variables:
A = 123
B = 456
C = 'string1'
D = 'string2'
E = 789
The values in each variable change after each loop, I just want to make clear that the variables are both numeric and string values since this is what causes my problem.
In R what I do after each loop is:
outp <- cbind(A,B,C,D,E)
and create a data frame containing each variable in one cell arranged horizontally to afterwards add the result of each loop vertically in a new data frame:
outp2 <- rbind(outp2,outp)
so in the end I get a data frame (outp2) with A,B,C,D,E columns and n rows containing the values of each variable after each loop. So at the end of the looping process I can use write.csv function and create an output file of outp2 that contains both numeric and string columns.
I tried to do this in Matlab but I cannot find a function that can join the data in the same way I am doing it in R because using brackets '[]' only allows me to join numeric kind of variables. So basically my question is: How can I replicate what I am doing in R in Matlab?
I hope I was clear enough, I found it a bit hard to explain.
You can append your output with a cell array, first using curly brackets to declare your cell format (empty {} or containing your data {...}), then using brackets [...] to concatenate the output (one line after the others using ;).
out_array = {}; %initialize empty
%vertical concatenation with ";"
for ii = 1:3
out_array = [out_array; {123, 456, 'string1', 'string2', 789}];
end
This gives
out_array =
[123] [456] 'string1' 'string2' [789]
[123] [456] 'string1' 'string2' [789]
[123] [456] 'string1' 'string2' [789]
Don't now if this solves your problem, but in Matlab you can do things like
oupt = {123, 456, 'string1', 'string2', 789}
Just use curly braces instead of square brackets.
As they have said before, use curly braces to create a cell array. I imagine A, B, C, D, and E are your table headers and you already have the data that goes under them, so I'd do it like this:
outp = { A , B , C , D , E };
# This next step is only to have some data...
outp2 = magic(5);
outp2 = num2cell(outp2);
output = [ outp ; outp2 ]
output =
[123] [456] 'string1' 'string2' [789]
[ 17] [ 24] [ 1] [ 8] [ 15]
[ 23] [ 5] [ 7] [ 14] [ 16]
[ 4] [ 6] [ 13] [ 20] [ 22]
[ 10] [ 12] [ 19] [ 21] [ 3]
[ 11] [ 18] [ 25] [ 2] [ 9]

If statement with multiple actions in R

I would like to write an if statement of the following form:
a=5
b=2
la<-function(a,b){
if(a>3){a}
else{b}
}
Now what I would like to do is not only have one action in the if statement but two, for example:
if(a>3){a and c<<-1000}
In this case to return 'a' and also write 1000 in variable 'c'
My question is how to put in multiple actions after the if statement.
You should use the semicolon
if(a>3){c<-1000;a}
The last statement is the return value.
EDIT This works for multiple statements, too. You can omit the semicolon if you use line breaks, as in
if(a>3) {
c<-1000
d<-1500
a
} else {
e <- 2000
b
}
EDIT: this should work with ifelse too. You would have to keep in mind that you are operating on a vector, though. Here is an example:
x <- sample(10, 100, replace=TRUE)
ifelse(x>3, {y <- 100; y+x}, x)
This adds 100 only to those elements of x that are larger than 3.

Resources