15 votes

Construire des quines (fonctions se reproduisant elles-mêmes)

A-t-il été construit un quine ("Un programme qui génère une copie de son propre texte source en tant que sa sortie complète" : http://www.nyx.net/~gthompso/quine.htm) en R? (La balise [quine] propose de nombreux exemples en Python, Java, ... mais apparemment aucun en R.)

f <- function() { body() }

s'en approche:

> f()
{
    body()
}

mais manque le nom de la fonction.

Qu'en est-il de la possibilité la plus courte? La plus obfusquée?

éditer: de la variété des réponses ci-dessous, il semble qu'il y ait diverses façons de définir l'auto-référentialité et l'environnement dans lequel elle doit se produire:

  • dans l'environnement R: fonction -> fonction (@bill_080)
  • dans l'environnement OS/shell: programme -> programme [plus ou moins équivalent à programme -> texte]: (@kohske)
  • autre: fonction -> texte (@JoshUlrich, @James, problème tel que défini ci-dessus)

Notes:

  • Le thread de R-help souligné par @Spacedman (qui semble mettre l'accent sur l'obfuscation plutôt que la brièveté) suggère que identical(quine,quine()) est un bon cas de test, même si c'est difficile car les environnements sont transportés : identical(quine,quine(),ignore.environment=TRUE) pourrait être plus facile.
  • Un récent (Oct 2015) post de blog fournit une autre réponse ...

22voto

Joshua Ulrich Points 68776

C'est le plus court que je puisse produire:

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

21voto

kohske Points 30437

Voici un vrai Quine, un programme (pas une fonction) qui génère une copie de son propre texte source en tant que sortie complète.

Sur la console,

# y1.R est un programme quine
$ 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(')')})")

# exécutez y1.R et affichez la sortie
$ /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(')')})")

# enregistrez la sortie de l'exécution de y1
$ /usr/bin/R --vanilla --slave < y1.R > y2.R

# comparez l'entrée et la sortie -- exactement identiques.
$ diff y1.R y2.R

probablement ce n'est pas le plus court.

MISE À JOUR :

et une version légèrement plus courte :

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

6voto

James Points 24725

En utilisant ce que body fait comme inspiration, call peut être utilisé pour reproduire la commande d'appel :

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

Qui affiche :

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

4voto

Spacedman Points 33792

Nous avons fait cela en 2003 :)

http://finzi.psych.upenn.edu/R/Rhelp02/archive/21116.html

La discussion contient certains de mes efforts et ceux des autres.

1voto

bill_080 Points 2670

Si vous voulez une fonction qui retourne une fonction.....peut-être ceci?

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

La sortie est:

> junk()

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

> boo <- junk(999)
> boo

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

>dput(boo)

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X