Quote-Safe Quines

Python 2 3, 181 152 130 124 122 bytes

""" """>" "or exec("oct=0");p='"""" """>" "or exec("oct=0");p=%r;a=oct==0;print(p[a:~a]%%p)#".';a=oct==0;print(p[a:~a]%p)#

Try it online! The TIO comes with a header and footer that automatically test the validity of the quine. You can clear them to just run the quine.

This code works by using the triple-quoted strings in Python. """ """ is equal to ' ' and """" """ is equal to '" '.

The code does use exec, but not for the "non-quiney" way of executing data as code, just for setting a variable from inside an expression. The exec is properly encoded in the data, too.

The first statement compares the string, possibly with a quote prepended, to " ", and sets the variable oct accordingly. (The variable could've been any short builtin.)

The rest of the code then implements the traditional Python quine using %r string formatting, with some additional code that strips the extra quotes if oct is unchanged.

An alternative version using the "cheaty" exec comes in at 126 bytes with less repeated code:

""" """>" "and exec("oct=0");s='"""" """>" "and exec("oct=0");s=%r;p=%r;exec(p)#".';p='a=oct!=0;print(s[a:~a]%(s,p))';exec(p)#

Try it online!


V, 27, 23 bytes

éPñi"éP241"qpá"lxx|xÿ

Try it online!

Since this contains some unprintable characters, here is a readable version:

éPñi"éP<C-v>241<esc>"qpá"lxx|xÿ

and here is a hexdump:

00000000: e950 f169 22e9 5016 3234 311b 2271 70e1  .P.i".P.241."qp.
00000010: 226c 7878 7c78 ff                        "lxx|x.

So the very first thing we need to do is to determine if the first character is a quote. éP inserts a 'P' character, but "éP is a NOOP. After that, we run a slight modification on the standard extendable quine, which is:

ñi<C-v>241<esc>"qpÿ

We're going to do it slightly differently though. First off we need to insert the starting "éP" text. So we do

ñ                        " Start recording into register 'q'
 i                       " Enter insert mode
  "éP<C-v>241<esc>       " Enter the following text: '"éPñ'
                  "qp    " Paste the text in register 'q'
                     á"  " Append a '"'

Here is where the branching happens. The text currently in the buffer is

"éPñi"éP<C-v>241<esc>"qpá"P
Cursor is here ----------^

Unless we wrapped it in quotes, in that case the 'P' would never have been inserted, and the buffer is:

"éPñi"éP<C-v>241<esc>"qpá"
Cursor is here ----------^

Since we are still recording, we can do whatever we want here, and it will get added to the buffer when the "qp happens. So from here it's pretty easy to conditionally delete the quotes:

l           " Move one character to the right. If there is no character to the right, 
            " then this is effectively a "break" statement, stopping playback of the recording
 xx         " Delete two characters (the '"P')
   |        " Move to the first character on this line
    x       " Delete one character
     ÿ      " End the program

StandardML, 182 176 108 bytes

";str(chr 34)^it;(print(it^it);fn x=>print(x^it^x^it))";str(chr 34)^it;(print(it^it);fn x=>print(x^it^x^it))

Unquoted version: Try it on codingground.
Quoted version: Try it on codingground.

Note that the output looks something like this

> val it = "{some string}" : string
> val it = "{some string}" : string
{output to stdout}> val it = fn : string -> unit

because the code is interpreted declaration by declaration (each ; ends a declaration) and shows the value and type of each declaration.


Background

In SML there is a quine of the form <code>"<code in quotes>":

str(chr 34);(fn x=>print(x^it^x^it))"str(chr 34);(fn x=>print(x^it^x^it))" 

and one in the form "<code in quotes>"<code>:

";str(chr 34)^it;print(it^it)";str(chr 34)^it;print(it^it)

Both rely on the fact that the <code>-part contains no quotes and can thus be quoted with out the need for escaping anything, the " needed to output the quine are given by str(chr 34).

They also heavily rely on the implicit identifier it which is used when no explicit identifier is given in a declaration.

In the first quine str(chr 34); binds it to the string containing ", fn x=> starts an anonymous function taking one argument x, then concatenates x^it^x^it and prints the resulting string. This anonymous function is directly applied to a string containing the program code, so the concatenation x^it^x^it yields <code>"<code>".

The second quine starts with just the program code as string ";str(chr 34)^it;print(it^it)"; which is bound to it. Then str(chr 34)^it; concatenates a quote to the start of the string and as again no explicit identifier is given, the resulting string "<code> is bound to it. Finally print(it^it) concatenates the string with itself yielding "<code>"<code> which is then printed.


Explanation

Edit: No longer up to date with the 108-byte version, however one might understand it too after reading this explanation.

The quote-safe quine combines both of the above approaches and is itself of the form "<code>"<code>. Putting this in again in quotes yields ""<code>"<code>", so we get an empty string and then a quine of the other form.

That means the program is either given its own source in the form "<code> by the identifier it, or it is just " and we are given our own source <code> as argument and must thus be a function which handles such an argument.

(if size it>1then(print(it^it);fn _=>())else fn x=>print(it^it^x^it^x^it))

To identify in which case we are, we check whether the size of it is larger than 1. If not then it is " and we are in the second case, so the else-part returns an anonymous function fn x=>print(it^it^x^it^x^it) which is then called because its followed by source as string. Note the leading it^it^ which is needed for the empty string at the start of the of the program.

If size it is larger than 1 we are in the then-part and just perform print(it^it), right? Not quite, because I neglected to tell you that SML is strongly typed which means that a conditional if <cond> then <exp_1> else <exp_2> must always have the same type which again means that the expressions <exp_1> and <exp_2> need to have the same type. We already know the type of the else part: An anonymous function which takes a string and then calls print has type string -> <return type of print>, and print has type string -> unit (unit is in some way similar to void in other languages), so the resulting type is again string -> unit.

So if the then part was just print(it^it) which has type unit, we would get a type mismatch error. So how about fn _=>print(it^it)? (_ is a wildcard for an argument that is not used) This anonymous function on its own has type 'a -> unit where 'a stands for an arbitrary type, so in the context of our conditional which enforces a string -> unit type this would work. (The type variable 'a gets instantiated with type string.) However, in this case we would not print anything as the anonymous function is never called! Remember, when we go in the then-part the overall code is "<code>"<code>, so the <code>-part evaluates to a function but, as nothing comes after it, its not called.

Instead we use a sequentialisation which has the form (<exp_1>; ...; <exp_n>) where <exp_1> to <exp_n-1> may have arbitrary types and the type of <exp_n> provides the type of the whole sequentialisation. From a functional point of view the values of <exp_1> to <exp_n-1> are simply discarded, however SML also supports imperative constructs so the expressions may have side effects. In short, we take (print(it^it);print) as the then-part, thus printing first and then returning the function print which has the correct type.