• 言語固有の機能を使い特殊な方法でquineする場合は考えない
  • とりあえず書ければいい人向け

外観

quineは

eval("program(data)") #=> "program(data)"

となるprogram部とdata部に分けられる

詳細

programdataはたいてい以下のように動く
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等の役割の境界は曖昧である 言語によってはprintformatprintfを採用し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)))

一般的な例 lazyk (iota)

次の記事

参考