Here, I list some Forth quines, starting with the shortest ones, then eliminating various features of Forth, and see how the quines become longer. The elimination features are the section headings.
First, the empty program is a quine in Forth and some (but not all) other languages; however, apart from pointing out languages that require some overhead for doing even nothing, this is not a very interesting quine. So, the next Forth quine is:
source typeThis is an ANS Forth program (author unknown). It just takes the current input line and prints it.
Some other languages do not allow directly interpreting code, but require that code is wrapped in a function. The corresponding restriction in Forth would be to define a Forth word that outputs its own definition. Here it is:
: quine [ source ] sliteral type ;Again, this is an ANS Forth program (by Neal Bridges <12hr3sj64c0vj7f@corp.supernews.com>). In addition to accessing the current input line, this also uses the brackets to execute SOURCE at compile time, and SLITERAL to shift the string from compile-time to run-time.
: QUINE S" SEE QUINE" EVALUATE ;And it is an exact quine on Win32Forth V6.11.10 (by George Hubert <1159545962.598745.86730@c28g2000cwb.googlegroups.com>. Here are some variations of this for other Forth systems: PFE 0.33.34:
: quine S" see quine" EVALUATE ;Gforth 0.6.2:
: quine s\" see quine" evaluate ;
s" 2dup cr 115 emit 34 emit space type 34 emit space type cr" 2dup cr 115 emit 34 emit space type 34 emit space type crThis is an ANS Forth program (by Joe Knapka <654Sg.92$DU3.4@tornado.texas.rr.com>). You can eliminate the CRs for shortening the program. However, this version does not generate a word, but is interpreted directly.
s" 2constant s : quine 115 emit 34 emit space [ s ] sliteral 2dup type 34 emit type ;"2constant s : quine 115 emit 34 emit space [ s ] sliteral 2dup type 34 emit type ;This is ANS Forth code. Note that this uses
[ s ]
sliteral
instead of just s
in order to allow QUINE
to work even if the S" buffer has been overwritten by another S".
: s s" ; : quine [ char ' parse : s s' ] sliteral type 34 emit space s type 34 emit s type ;"; : quine [ char ' parse : s s' ] sliteral type 34 emit space s type 34 emit s type ;This is ANS Forth code. Here we can reference s directly, because the string is compiled into a colon definition.
: s s" ; : quine 58 emit space 115 emit space 115 emit 34 emit space s type 34 emit s type ;"; : quine 58 emit space 115 emit space 115 emit 34 emit space s type 34 emit s type ;This is ANS Forth code.
: quine s" 2dup 32 34 115 32 101 110 105 117 113 32 58 11 0 do emit loop type 34 emit 32 emit type 32 101 110 105 117 113 32 59 32 9 0 do emit loop" 2dup 32 34 115 32 101 110 105 117 113 32 58 11 0 do emit loop type 34 emit 32 emit type 32 101 110 105 117 113 32 59 32 9 0 do emit loop ; quineSimplified by Anton Ertl:
: quine s" 2dup 32 34 115 32 101 110 105 117 113 32 58 11 0 do emit loop type 34 emit type ;"2dup 32 34 115 32 101 110 105 117 113 32 58 11 0 do emit loop type 34 emit type ;Also ANS Forth code. Of course, with a shorter word name, this can be quite a bit shorter:
: q s" 2dup 32 34 115 32 113 32 58 7 0 do emit loop type 34 emit type ;"2dup 32 34 115 32 113 32 58 7 0 do emit loop type 34 emit type ;
36 base ! create d 1M c, W c, 35 c, W c, 1A c, Y c, W c, 1F c, 1I c, W c, 2Q c, 2P c, 37 c, 2T c, W c, X c, W c, 2R c, 36 c, 2T c, 2P c, 38 c, 2T c, W c, 2S c, W c, Y c, W c, 2S c, W c, 1E c, 1U c, W c, 1C c, W c, 2S c, 33 c, W c, 2S c, 39 c, 34 c, W c, 2X c, W c, 2R c, 2W c, 2P c, 36 c, 37 c, W c, 17 c, W c, 2R c, 1S c, W c, 1A c, W c, 1A c, Y c, W c, 2R c, 18 c, W c, Y c, W c, 30 c, 33 c, 33 c, 34 c, W c, 2S c, W c, 1E c, 1U c, W c, 38 c, 3D c, 34 c, 2T c, W c, 1N c, W c, 35 c, : q ." 36 base ! create d " d 2B 0 do dup i chars + c@ . ." c, " loop d 2B type ; q
: quiche s" : quiche % 2dup bounds ?DO I c@ 37 = IF 's emit 34 emit space type 34 emit ELSE I c@ emit THEN LOOP ; quiche" 2dup bounds ?DO I c@ 37 = IF 's emit 34 emit space type 34 emit ELSE I c@ emit THEN LOOP ; quicheThis solution uses some common extensions. A solution in standard Forth:
: quine s" : quine s% 2dup over + swap DO I c@ 37 = IF 34 emit space type 34 emit ELSE I c@ emit THEN LOOP ;" 2dup over + swap DO I c@ 37 = IF 34 emit space type 34 emit ELSE I c@ emit THEN LOOP ;Instead of replacing a macro character, one can also just know the position where to insert the string and the quotes (by Bernd Paysan <0o63v3-ln5.ln1@vimes.paysan.nom>):
: quine s" : quine over 8 type 115 emit 34 emit space 2dup type 34 emit 8 /string type ;" over 8 type 115 emit 34 emit space 2dup type 34 emit 8 /string type ;A slightly shorter variant (by Anton Ertl):
: quine s" : quine s over 9 type 34 emit space 2dup type 34 emit 9 /string type ;" over 9 type 34 emit space 2dup type 34 emit 9 /string type ;Instead of having one string and picking it apart, one can also have two strings:
: x 83 emit 34 emit space type 34 emit ; : quine S" : x 83 emit 34 emit space type 34 emit ; : quine "S" 2swap 2dup type x 2dup x type ;"2swap 2dup type x 2dup x type ;It is a little shorter if we put the strings in reverse order:
: x 83 emit 34 emit space type 34 emit ; : quine S" 2dup type 2over x x type ;"S" : x 83 emit 34 emit space type 34 emit ; : quine "2dup type 2over x x type ;A version using escaped strings (by Anton Ertl) is:
: s s\" : quine .\\\" : s s\\\\\\\" \" 0 xpos ! s c-\\type .\\\" \\\" ; \" s type ;" ; : quine .\" : s s\\\" " 0 xpos ! s c-\type .\" \" ; " s type ;This works in Gforth (0.6.2).