Ruby 2.0、65 76 164 キャラクター
eval r="gets p;$<.pos=0;`ruby -c 2>&0`;p$?==0&&$_!='eval r=%p'%r"
これは、Rubyの組み込み構文チェッカー(ruby -c
)を使用して入力の構文をチェックします。つまり、コードは評価されません。
基本的な使用例:
ruby syntax.rb <<< foo
true
ruby syntax.rb <<< "'"
false
ruby syntax.rb < synxtax.rb # assumes the file was saved without trailing newline
false
説明
このソリューションは、(以前は)標準のRuby quineに基づいていました。
q="q=%p;puts q%%q";puts q%q
%p
書式指定子のためであるarg.inspect
と比較することができる、uneval
とき:eval
によって返された文字列をINGのarg.inspect
、あなたは(通常は)再び元の値を取得しますが。したがって、q
それ自体を引数として使用して文字列をフォーマットすると、文字列の%p
内部は引用符で囲まれた文字列自体に置き換えられます(つまり、のようなものになります"q=\"q=%p;puts q%%q\";puts q%q"
)。
このタイプのクインを一般化すると、次のような結果になります。
prelude;q="prelude;q=%p;postlude";postlude
ただし、このアプローチには大きな欠点が1つあります(少なくともcode-golfでは):すべてのコードを複製する必要があります。幸いにも、eval
これを回避するために使用できます。
eval r="some code;'eval r=%p'%r"
ここで何が起こるかは、evalに渡されたコードが呼び出されるr
前に 内部に保存さeval
れることです。その結果、eval
ステートメントの完全なソースコードをで取得できます'eval r=%p'%r
。eval
dコード内でこれを行い、最上位レベルが1つのeval
ステートメントのみで構成されていることを確認すると、渡された追加のコードeval
はすでに内に格納されているため、その式は実際にプログラムの完全なソースコードを提供しますr
。
補足:このアプローチでは、実際にルビークインを26文字で書くことができます。 eval r="puts'eval r=%p'%r"
ここで、このソリューションでは、内部で実行される追加のコードeval
は4つのステートメントで構成されています。
gets p
まず、STDINからすべての入力を読み取り、暗黙的にに保存し$_
ます。
$<.pos=0
次に、STDINを巻き戻して、次のステップで開始するサブプロセスで入力を再び使用できるようにします。
`ruby -c 2>&0`
これにより、Rubyは組み込みの構文チェックモードで起動し、stdinからソースコードを読み取ります。供給されたスクリプト(ファイル名またはSTDIN)のシンタックスがOKであれば、印刷Syntax OK
(親プロセスによって取得される)、そのstdoutにするが、構文エラーの場合、エラーの記載を印刷さstderrの -う見えるようにするため、2>&0
代わりにnirvana()にリダイレクトします。
p$?==0&&$_!='eval r=%p'%r
その後、サブプロセスの終了コードを確認$?
します。構文に問題がなければ0になります。最後に、先ほど読んだ入力($_
)を独自のソースコード(前に説明したように、で取得できる)と比較します'eval r=%p'%r
。
編集:@histocratのおかげで14文字が節約されました!