quineを書く一般的な方法
- 言語固有の機能を使い特殊な方法でquineする場合は考えない
- とりあえず書ければいい人向け
外観
quineは
eval("program(data)") #=> "program(data)"
となるprogram
部とdata
部に分けられる
詳細
program
とdata
はたいてい以下のように動く
python風言語で示す
. eval("program(data)")
-> program(data)
= print(format(str(data), repr(data)))
-> print(format("program", "data"))
-> print("program(data)")
#=> "program(data)"
実装
つまり、基本的に、実装/決定すべきは、
- 適当な入力
data
- 変換関数
str : data -> "program"
- 変換関数
repr : data -> "data"
- 結合関数
format : ("program", "data") -> "program(data)"
- 適当な出力
print
である
str
,repr
,format
等の役割の境界は曖昧である
言語によってはprint
とformat
にprintf
を採用し1つにまとめるなどできる
これらはたいてい、
data = quote("program")
str = id
repr = quote
format = append, format
print = print
が使われる
実装量が少なく楽だからである
また、一般的なprint
が存在しない言語では、好みの方法で出力すれば良い
例
分かりやすい例 haskell
show
が言語内に有るので非常に楽である
main = putStrLn $ (\ x -> x ++ show x) "main = putStrLn $ (\\ x -> x ++ show x) "
data = "main = putStrLn $ (\\ x -> x ++ show x) "
str = id
(省略)repr = show
format = (++)
print = putStrLn
少し長い例 python
標準関数のrepr
は高機能すぎて、quineには利用できなかったのでrepr
を実装
接続には{}
で指定してformat
を使用
#!/usr/bin/python3
show = lambda q: '"""' + q.replace('\\','\\\\').replace('\"','\\\"') + '"""'
q = """#!/usr/bin/python3
show = lambda q: '\"\"\"' + q.replace('\\\\','\\\\\\\\').replace('\\\"','\\\\\\\"') + '\"\"\"'
q = {}
print(q.format(show(q)))"""
print(q.format(show(q)))