2011-06-27 61 views
15

有沒有人在R中構造一個quine(「一個程序,它自己的源文本作爲它的完整輸出產生一個副本」:http://www.nyx.net/~gthompso/quine.htm)? (在[奎因]標籤拉了很多在Python,Java的例子,...但顯然沒有在R.)構造三角形(自我複製功能)

f <- function() { body() } 

接近:

> f() 
{ 
    body() 
} 

但缺乏函數的名稱。

最短的可能性如何?大多數混淆?

編輯:從品種下面的答案,似乎有很多種,其中它必須發生的方法來定義自我指涉和環境:

  • R環境中:功能->函數(@ bill_080)
  • 的OS /殼環境內:程序->程序[或多或少相當於->文本編程]:(@kohske)
  • 其他:功能->文本(@JoshUlrich,@詹姆斯,問題作爲d上述efined)

注:

  • thread from R-help pointed out by @Spacedman(這似乎強調了簡潔混淆)認爲identical(quine,quine())是一個很好的測試案例,雖然它的棘手,因爲環境相處攜帶:identical(quine,quine(),ignore.environment=TRUE)威力更容易。
  • 最近(OCT 2015)blog post提供了另一種答案...

回答

22

這是最短的,我可以想出:

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

使用什麼body確實爲靈感,call可以用來複制的調用指令:

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

,輸出:

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

但'f()< - function()...'是一個錯誤。 –

+0

@Joshua Ulrich Oops,現在修好了。作爲額外的好處,增加的複雜性使得閱讀變得不那麼容易並且因此更加混淆! ;) – James

1

如果你想要一個函數返回一個函數.....也許這個?

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

輸出是:

> junk() 

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


> boo <- junk(999) 
> boo 

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


>dput(boo) 

function (...) 
{ 
    structure(junk(...)) 
} 
+1

一些有用的鏈接:http://www.stat.auckland.ac.nz/~ihaka/downloads/lexical.pdf http://www.stat.auckland.ac.nz/~ihaka/downloads/Compstat- 2008.pdf –

+0

我喜歡這個,但是上面給出的具體定義是「一個能夠生成它自己的源文本副本的函數」,儘管「一個生成自身副本的函數」更接近自我再現的精神。在你的例子中,返回的函數與原始函數並不完全相同,儘管也許你可以用'...'替換'inp',它會是? –

+0

@Ben B,你說得對。 'inp'是我試圖擴展功能的原因。我會解決它。 –

21

這裏是一個真正的奎因,程序(不是函數)生成其自己的源文本的副本作爲完整的輸出。

在控制檯上,

# 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 

或許這不是最短的一個。

更新:

和稍短的版本:

(function(x){cat(x,'(',d<-intToUtf8(0x0022),x,d,')',sep='')})("(function(x){cat(x,'(',d<-intToUtf8(0x0022),x,d,')',sep='')})") 
+0

+1爲_real_奎因。 ;-) –

1

雖然我不知道這是否「罪狀」從奎因觀點(我碰到這個問題,跌跌撞撞,而試圖驗證是否它的腳本

function(){} 

將輸出function(){}。這與Joshua Ulrich的答案基本相同,只是削減了基本要素。