Построение кайн (самовоспроизводящиеся функции)

Создал ли кто-нибудь quine («Программа, которая генерирует копию собственного исходного текста в качестве полного вывода»: http://www.nyx.net/~gthompso/quine.htm) в R? (Тег [quine] вызывает множество примеров на Python, Java, ... но, по-видимому, ни одного в R.)

f <- function() { body() }

подходит близко:

> f()
{
    body()
}

но отсутствует название функции.

Как насчет кратчайшей возможности? Самый запутанный?

изменить: из множества ответов ниже кажется, что существует множество способов определить самореферентность и среду, в которой она должна происходить:

  • в среде R: функция -> функция (@ bill_080)
  • в среде ОС / оболочки: программа -> программа [более или менее эквивалентна программе -> текст]: (@kohske)
  • другое: функция -> текст (@JoshUlrich, @James, проблема, как определено выше)

Примечания:

  • Тема из R-help, указанная @Spacedman (который, кажется, делает упор на обфускацию, а не на краткость) предполагает, что identical(quine,quine()) - хороший тестовый пример, хотя это сложно, потому что окружения переносятся вместе: identical(quine,quine(),ignore.environment=TRUE) может быть проще.
  • Недавнее (октябрь 2015 г.) сообщение в блоге предоставляет другой ответ ...

person Ben Bolker    schedule 27.06.2011    source источник


Ответы (5)


Это самое короткое, что я могу придумать:

> "f" <- function() call("<-", "f", f)
> f()
"f" <- function () 
call("<-", "f", f)
person Joshua Ulrich    schedule 27.06.2011

Вот настоящий Куайн, программа (а не функция), которая генерирует копию своего собственного исходного текста в качестве полного вывода.

На консоли

# 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='')})")
person kohske    schedule 27.06.2011

Используя то, что 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()))
}
person James    schedule 27.06.2011
comment
@Joshua Ulrich Упс, исправил сейчас. В качестве дополнительного бонуса повышенная сложность делает его менее легким для чтения и, следовательно, более запутанным! ;) - person James; 27.06.2011

Если вам нужна функция, которая возвращает функцию ... может быть, это?

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(...))
}
person bill_080    schedule 27.06.2011
comment
Некоторые полезные ссылки: stat.auckland.ac.nz/~ihaka/ downloads / lexical.pdf stat.auckland. ac.nz/~ihaka/downloads/Compstat-2008.pdf - person bill_080; 27.06.2011
comment
Мне это нравится, но конкретное определение, данное выше, - это функция, которая генерирует копию собственного исходного текста, хотя функция, которая генерирует копию самого себя, ближе к духу самовоспроизводимости. В вашем примере возвращенная функция не совсем идентична исходной функции, хотя, возможно, вы могли бы заменить inp на ..., и это было бы? - person Ben Bolker; 27.06.2011
comment
@ Бен Би, ты прав. inp был из-за того, что я баловался, пытаясь расширить возможности. Я это исправлю. - person bill_080; 27.06.2011
comment
Поскольку это на самом деле не отвечает на вопрос, может мне стоит его удалить? - person bill_080; 27.06.2011

Хотя я не уверен, что это «считается» с точки зрения квайна (я наткнулся на этот вопрос, пытаясь проверить, так ли это), сценарий

function(){}

выведет function(){}. Это работает по тому же принципу, что и ответ Джошуа Ульриха, только по сути.

person Empiromancer    schedule 03.11.2015