2011-06-27 12 views
15

Có ai xây dựng một quine ("Một chương trình tạo ra một bản sao của văn bản nguồn của nó như là sản lượng hoàn chỉnh của nó": http://www.nyx.net/~gthompso/quine.htm) trong R? (The [Quine] tag kéo lên rất nhiều ví dụ bằng Python, Java, ... nhưng dường như không ai trong R.)Xây dựng quines (chức năng tự tái tạo)

f <- function() { body() } 

đến gần:

> f() 
{ 
    body() 
} 

nhưng lại thiếu tên của hàm .

Làm thế nào về khả năng ngắn nhất? Hầu hết các obfuscated?

chỉnh sửa: từ sự đa dạng của câu trả lời dưới đây, có vẻ như có rất nhiều cách khác nhau để xác định tự tham chiếu qua và môi trường mà nó phải xảy ra:

  • trong môi trường R: chức năng -> chức năng (@ bill_080)
  • trong môi trường hệ điều hành/vỏ: chương trình -> chương trình [ít nhiều tương đương với chương trình -> văn bản]: (@kohske)
  • khác: chức năng -> văn bản (@JoshUlrich, @ James, vấn đề như d efined trên)

Ghi chú:

  • Các thread from R-help pointed out by @Spacedman (mà dường như để nhấn mạnh obfuscation qua ngắn gọn) gợi ý rằng identical(quine,quine()) là một trường hợp thử nghiệm tốt, mặc dù nó khó khăn vì môi trường được thực hiện cùng: identical(quine,quine(),ignore.environment=TRUE) sức dễ dàng hơn.
  • Một gần đây (tháng 10 năm 2015) blog post cung cấp câu trả lời khác ...

Trả lời

22

Đây là ngắn nhất tôi có thể đưa ra:

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

Sử dụng những gì body không làm nguồn cảm hứng, call có thể được sử dụng để tái tạo các lệnh gọi:

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

Những kết quả đầu ra:

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

Nhưng 'f() <- function() ...' là lỗi. –

+0

@Joshua Ulrich Rất tiếc, đã sửa nó ngay bây giờ. Như một phần thưởng thêm, độ phức tạp thêm vào làm cho nó dễ đọc hơn và do đó bị làm xáo trộn hơn! ;) – James

1

Nếu bạn muốn hàm trả về hàm ..... có thể đây?

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

Đầu ra là:

> junk() 

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


> boo <- junk(999) 
> boo 

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


>dput(boo) 

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

Một số liên kết hữu ích: http://www.stat.auckland.ac.nz/~ihaka/downloads/lexical.pdf http://www.stat.auckland.ac.nz/~ihaka/downloads/Compstat- 2008.pdf –

+0

Tôi thích điều này, nhưng định nghĩa cụ thể ở trên là "một hàm tạo bản sao văn bản nguồn của chính nó", mặc dù "một hàm tạo bản sao của chính nó" gần gũi hơn với tinh thần tự tái tạo . Trong ví dụ của bạn hàm trả về không hoàn toàn giống với hàm ban đầu mặc dù có lẽ bạn có thể thay thế 'inp' bằng' ... 'và nó sẽ là? –

+0

@Ben B, bạn nói đúng. 'inp' là từ tôi đang cố gắng mở rộng khả năng. Tôi sẽ sửa chữa nó. –

21

Đây là một Quine sản, một chương trình (không phải là một chức năng) tạo bản sao văn bản nguồn của chính nó làm đầu ra hoàn chỉnh của nó.

Mở giao diện điều khiển,

# 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 

lẽ đây không phải là ngắn nhất.

CẬP NHẬT:

và phiên bản ngắn hơn một chút:

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

+1 cho qu {_real_. ;-) –

1

Trong khi tôi không chắc chắn nếu điều này "đếm" từ góc độ Quine (tôi stumbled trên câu hỏi này trong khi cố gắng xác minh nếu nó có), tập lệnh

function(){} 

sẽ xuất function(){}. Điều này làm việc trên nguyên tắc tương tự như câu trả lời của Joshua Ulrich, chỉ cần bỏ qua các yếu tố cần thiết.