Constructing quines (self-reproducing functions)

北城以北 提交于 2019-12-03 23:32:47

This is the shortest I can come up with:

> "f" <- function() call("<-", "f", f)
> f()
"f" <- function () 
call("<-", "f", f)

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='')})")

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()))
}

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(...))
}

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.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!