After poking around on the internet I wasn't able to find anyone who had written a quine in R (Edit: since writing this, have found several on SO, but am still interested in this one). So I figured I'd try my hand at coming up with one myself. My result was the (surprisingly short) code:
function(){}
which will output function(){} when run. This takes advantage of the fact that a function name without parens or arguments after it will return the function's source code.
However, a program that "looks at itself" is not generally considered a true quine. There are two things I realized I don't understand in the course of trying to decide whether I'd written a "real" quine: (1) What constitutes a program "looking at itself" (from a quine standpoint) beyond use of file i/o and (2) the extent to which function(){} (or similar commands like logical(0)) are self referential when they print themselves. The former seems to be too subjective for SO, but I was hoping for some clarification on the latter. So...
When I run function(){}, what exactly is happening that causes it to print its own "source code"? For example, is R loading an empty function into a local environment, evaluating that function, and then looking back at the code that defined it to print? Or, is it just looking at function(){} and echoing its definition right away? Is there a fundamental difference between this and
f<-function(){cat("f<-");print(f);cat("f()")}
f()
in terms of how they both print themselves when run?
You don't completely get what's going on here. Actually, the code
function(){}
doesn't do anything apart from constructing a function without arguments and body, returning it and deleting it immediately after it's returned. Its output would be NULL, so doesn't "recreate itself".
The output you see in the console, is not the output given by function(){} but by print.function. This is the S3 method that takes care of showing a function object in the console. What you actually do, is:
a <- function(){}
print(a)
rm(a)
A true R quine would be something like this:
m<-"m<-0;cat(sub(0,deparse(m),m))";cat(sub(0,deparse(m),m))
See also Wikipedia for this and other examples
This is not a true quine as it does not print anything to stdout. Whole point of Quine is that it can reproduce itself by printing. Program must create a new file or output in stdout containing its exact code.
Example of a javascript quine would be:
(function a(){console.log(`(${a}())`)}())
(function(x) print(substitute(x(x))))(function(x) print(substitute(x(x))))
Related
During a process, I need to copy a directory using fs::dir_copy(currentPath, newPath). Some of the time, I get the following error message:
Error in link_copy(links, path(new_path[[i]], path_rel(links, path[[i]])), :
all(is_link(path)) is not TRUE
This only happens some of the time, not always. What's more, if I replace my directory with a manual copy of itself (i.e. manually copy directory, delete original, rename the copy), then my code will work.
Could someone please explain why this could be happening? Is there a way I can sidestep that error once and for all?
This does not answer your question but may help you to further analyse what is going on. One of the great things of R is that you can easily inspect source code. Especially in a situation where unusual things appear to happen, looking at the code may be useful.
In your case, we can inspect the source code of fs::dir_copy and trace back to which code generates the error message. If you type fs::dir_copy (no parenthesis) into the console, R will print the R code of the function (if the function is not primitive). Doing that here will show you that the fs:dir_copy function calls the fs::link_copyfunction. Makes sense, as the error message comes from this function.
We can now print this function with fs::link_copy
This function generates the error message in this line:
stopifnot(all(is_link(path)))
From the error message we know that all(is_link(path)) returns FALSE. Next step is to have a look at the fs::is_link function. Here we see that the error may come from the call to the setNames function, which depends on the fs::file_info function: res <- file_info(path)
Here we see that setNames is called with a condition depending on what the file_infofunction returned:
setNames(!is.na(res$type) & res$type == "symlink", res$path)
This looks unusual as setNames takes an object and a character vector as formals. But then, I am not the developer of these functions ;-)
Perhaps there are issues with the file type on your machine and fs::file_info(path) returns something unexpected under some conditions.
I have a very odd problem. I designed a function a while back that has arguments defined as follows:
elisa<-function(
file="data.csv",
Out=paste("Elisa Analysis",Sys.time(),".xlsx"),
wd="~/Desktop",
out.folder=wd,
Rep=2,
standards=c(1,2),
orient="horizontal")
{
As you can see above, wd is defaulted to the value of the desktop, and out.folder is defaulted to the value of wd. This is so that users can specify where an output excel document goes separately from where the working directory is, but the default is that they are the same. What is weird is that I have used this function for a while, and I have several users who use this exact code (I installed it on their CPUs, and so I know that it is the exact same), and it works fine for them, but suddenly on my computer it is not working. It gives the following error when I run the function.
Error in setwd(out.folder) : object 'wd' not found
This is odd for a number of reasons. The first is that if I remove the functional enclosure and run the exact same code "naked," the code works just fine. The object wd is definitely still present by the time it gets to the line of code being referenced, which is simply just
setwd(out.folder)
Moreover, out.folder has the same definition as wd. What is even weirder is that if you read the error code, it doesn't say that out.folder is not defined or the object isn't found. It says that the other object, wd, is not found, which is odd because out.folder should have just been set to the value
"~/Desktop"
I am at a loss. A line of code early in the function uses wd just fine, but the error occurs hundreds of lines farther down at the line of code specified. If I remove it, everything functions fine, and if I run the function without the functional enclosure, everything functions fine.
Anybody have any clue what is going on?
Sample (only lines involved since the full code is so large it won't let me post it here)
elisa<-function(
file="data.csv",
Out=paste("Elisa Analysis",Sys.time(),".xlsx"),
wd="~/Desktop",
out.folder=wd,
Rep=2,
standards=c(1,2),
orient="horizontal")
{
setwd(wd)
setwd(out.folder)
setwd(wd)
}
I have found a way around it. This is really interesting. If you state the argument explicitly the same way as the default argument, the function won't work. In other words,
elisa(...,out.folder=wd)
will throw an error even though it is the default argument format. If you omit it when doing the function call, the function works, or if you give it the same value as wd without going through wd as an intermediary, it works. In other words,
elisa(...,wd="~/Desktop",out.folder="~/Desktop",...)
and
elisa(...,wd="~/Desktop",...)
both work. You just can't do
elisa(...,wd="~/Desktop",out.folder=wd,...)
even though the definition of the function arguments is
elisa<-function(
file="data.csv",
Out=paste("Elisa Analysis",Sys.time(),".xlsx"),
wd="~/Desktop",
out.folder=wd,
Rep=2,
standards=c(1,2),
orient="horizontal")
It makes no sense, but that's the way around it.
I tried using a for loop to print out a few rows. here is the code.
Weird thing is that it doesn't work for head() function. It works if I replaced head() with print().
kw_id=c('a','b')
keyword_text=data.frame(col=c('a','b'), col2=c(1,2), row.names=(c('r1','r2')))
for (i in 1:2) {
plot_data<-subset(keyword_text,col==kw_id[i])
print(plot_data)
head(plot_data)
}
Could someone help? I suspect it has something to do with head() function.
This is a relatively common class of problem that newcomers to R run into. The issue here is that R serves two mistresses: interactive console work and "true programming".
When you type a command at the console that returns a value, the console automatically calls a print method in order to display the results. When running a script, this doesn't happen unless you tell it to.
So if you changed it to print(head(plot_data)) it should work.
These are discussed in FAQ 7.16 and 7.22
Addendum lifted from the comments:
As Josh points out, copy+pasting the for loop directly to the console also fails to print any output. What's going on in that case is that for loops (like most everything in R) is actually a function, and it's return value (NULL) is returned invisibly, which means no printing. (This is mentioned in ?Control.)
I'm an R newbie using RScaLAPACK and every time I spawn a new process grid I get a message.
> sla.gridInit(2)
[1] "RScaLAPACK:Process Grid Initialized "
I'm going to put this line in a function and I don't want my function to be spitting out this message. However- I don't want to just sink("/dev/null") the call because for all I know, something somewhere could go wrong and then I'd be suppressing useful output. Basically, I want it to be silent when it succeeds and loud if it fails. What is the best way to accomplish this?
Any thoughts, including design considerations, are welcome.
edit:
sla.gridInit() isn't returning anything. The code for sla.gridInit just calls print().
edit:
I suppose capturing output is best like in suppress messages displayed by "print" instead of "message" or "warning" in R . At least I will have the output if I want to do something with it.
You can wrap this function in one of the suppress* functions, suppressMessages, suppressWarnings or suppressPackageStartupMessages. See the help pages of those functions for more details.
Is there a way, in R, to pop up an error message if a function uses a variable
not declared in the body of the function: i.e, i want someone to flag this type of functions
aha<-function(p){
return(p+n)
}
see; if there happens to be a "n" variable lying somewhere, aha(p=2) will give me an "answer" since R will just take "n" from that mysterious place called the "environment"
If you want to detect such potential problems during the code-writing phase and not during run-time, then the codetools package is your friend.
library(codetools)
aha<-function(p){
return(p+n)
}
#check a specific function:
checkUsage(aha)
#check all loaded functions:
checkUsageEnv(.GlobalEnv)
These will tell you that no visible binding for global variable ānā.
Richie's suggestion is very good.
I would just add that you should consider creating unit test cases that would run in a clean R environment. That will also eliminate the concern about global variables and ensures that your functions behave the way that they should. You might want to consider using RUnit for this. I have my test suite scheduled to run every night in a new environment using RScript, and that's very effective and catching any kind of scope issues, etc.
Writing R codes to check other R code is going to be tricky. You'd have to find a way to determine which bits of code were variable declarations, and then try and work out whether they'd already been declared within the function.
EDIT: The previous statement would have been true, but as Aniko pointed out, the hard work has already been done in the codetools package.
One related thing that may be useful to you is to force a variable to be taken from the function itself (rather than from an enclosing environment).
This modified version of your function will always fail, since n is not declared.
aha <- function(p)
{
n <- get("n", inherits=FALSE)
return(p+n)
}