15

Has anyone constructed a quine ("A program that generates a copy of its own source text as its complete output": http://www.nyx.net/~gthompso/quine.htm) in R? (The [quine] tag pulls up lots of examples in Python, Java, ... but apparently none in R.)

f <- function() { body() }

comes close:

> f()
{
    body()
}

but lacks the name of the function.

How about the shortest possibility? Most obfuscated?

edit: from the variety of answers below, it seems that there are a variety of ways to define self-referentiality and the environment in which it must occur:

  • within the R environment: function -> function (@bill_080)
  • within the OS/shell environment: program -> program [more or less equivalent to program -> text]: (@kohske)
  • other: function -> text (@JoshUlrich, @James, problem as defined above)

Notes:

  • The thread from R-help pointed out by @Spacedman (which seems to emphasize obfuscation over brevity) suggests that identical(quine,quine()) is a good test case, although it's tricky because environments get carried along: identical(quine,quine(),ignore.environment=TRUE) might be easier.
  • A recent (Oct 2015) blog post provides another answer ...
Ben Bolker
  • 211,554
  • 25
  • 370
  • 453

5 Answers5

22

This is the shortest I can come up with:

> "f" <- function() call("<-", "f", f)
> f()
"f" <- function () 
call("<-", "f", f)
Joshua Ulrich
  • 173,410
  • 32
  • 338
  • 418
21

Here is a real Quine, a program (not a function) that generates a copy of its own source text as its complete output.

On console,

# y1.R is a quine program
$ cat y1.R
(function(x){cat(x);cat('(');cat(intToUtf8(0x0022));cat(x);cat(intToUtf8(0x0022));cat(')')})("(function(x){cat(x);cat('(');cat(intToUtf8(0x0022));cat(x);cat(intToUtf8(0x0022));cat(')')})")

# execute y1.R and show output
$ /usr/bin/R --vanilla --slave < y1.R
(function(x){cat(x);cat('(');cat(intToUtf8(0x0022));cat(x);cat(intToUtf8(0x0022));cat(')')})("(function(x){cat(x);cat('(');cat(intToUtf8(0x0022));cat(x);cat(intToUtf8(0x0022));cat(')')})")

# save the output of the execution of y1
$ /usr/bin/R --vanilla --slave < y1.R > y2.R

# compare input and output -- exactly same.
$ diff y1.R y2.R

probably this is not the shortest one.

UPDATED:

and slightly shorter version:

(function(x){cat(x,'(',d<-intToUtf8(0x0022),x,d,')',sep='')})("(function(x){cat(x,'(',d<-intToUtf8(0x0022),x,d,')',sep='')})")
kohske
  • 65,572
  • 8
  • 165
  • 155
6

Using what body does as inspiration, call can be used to reproduce the calling command:

f <- function () 
{
    call("<-", as.name(as.character(sys.calls()[[1]])), sys.function(sys.parent()))
}

Which outputs:

> f()
f <- function () 
{
    call("<-", as.name(as.character(sys.calls()[[1]])), sys.function(sys.parent()))
}
James
  • 65,548
  • 14
  • 155
  • 193
  • @Joshua Ulrich Oops, fixed it now. As an added bonus the added complexity makes it less easy to read and therefore more obfuscated! ;) – James Jun 27 '11 at 16:58
1

While I'm not sure if this "counts" from a quine perspective (I stumbled across this question while trying to verify if it does), the script

function(){}

will output function(){}. This works on the same principle as Joshua Ulrich's answer, just pared down to the essentials.

Empiromancer
  • 3,778
  • 1
  • 22
  • 53
1

If you want a function that returns a function.....maybe this?

junk <- function(...) {
  function(...) {
    structure(junk(...))
  }
}

The output is:

> junk()

function(...) {
    structure(junk(...))
  }
<environment: 01ef8e50>


> boo <- junk(999)
> boo

function(...) {
    structure(junk(...))
  }
<environment: 020e1048>


>dput(boo)

function (...) 
{
    structure(junk(...))
}
bill_080
  • 4,692
  • 1
  • 23
  • 30
  • 1
    Some useful links: http://www.stat.auckland.ac.nz/~ihaka/downloads/lexical.pdf http://www.stat.auckland.ac.nz/~ihaka/downloads/Compstat-2008.pdf – bill_080 Jun 27 '11 at 17:46
  • I like this, but the specific definition given above is "a function that generates a copy of its own source text", even though "a function that generates a copy of itself" is closer to the spirit of self-reproducibility. In your example the returned function is not quite identical to the original function although perhaps you could replace `inp` with `...` and it would be? – Ben Bolker Jun 27 '11 at 18:06
  • @Ben B, You're right. `inp` was from me screwing around trying to extend the capabilities. I'll fix it. – bill_080 Jun 27 '11 at 18:14
  • Since this doesn't really answer the question, maybe I should delete it? – bill_080 Jun 27 '11 at 18:31