Posted 2016-12-23 21:57:44 GMT

方言の系統

Conniver

主要開発者

Drew V. McDermott、Gerald J. Sussman

登場時期

1972年

特徴

Plannerから続くAI向け言語。Lispをベースにデータベースとユーザーが操作可能な制御フローを持つ

後続への影響

Lisp Machine Lisp

概要

Conniverは、Plannerに影響を受けつつ、BobrowとWegbreitの制御機構(多分スパゲティスタック)や、Muddle(MDL)のオプショナル引数等を取り込み、さらにデータベースと、ジェネレータ等を持つLisp系言語です。

基本的にLispだそうですが、データを登録していく仕組みが組込まれていて、 add や、 remove で追加/削除できます。

それらのデータを元に、Possibilities Listを作成しデータを問合せたり制御を移したりしますが、そこにジェネレータが使われます。

関数の定義は、MACLISP系の defun と似た感じの cdefun で、ジェネレータは、 cdefgen で定義します。

MDLから影響を受けた、ラムダリストがあり、“OPTIONAL”、“REST”、“AUX”が使えます。なお“AUX”は、ラムダリスト内ではなくボディで利用。

MDLでは、“REST”ではなく、“TUPLE”でしたが、Common Lispの &rest の祖先はConniverということになりそうです。

( cdefun foo ( "optional" foo "rest" args ) "aux" ( x y z ) ... )

は、Common Lispで書くと

( &optional foo &rest args &aux x y z ) ... defun foo...

になります。

let のネストが減るので、 cdefun の“aux”は割合に良いかもしれないですね。

ボディ部は暗黙の prog になっていることが多く cdefun を始め、 cond の節まで暗黙の prog でタグを記述することができ、 go で飛ぶことが可能です。

下記は、マニュアルにあるアイテムのデータベースへの登録/削除とジェネレータ呼び出しを含む例ですが、手続き型の制御機構を強化した印象が強いです。

( player square ) "aux" ( ( context ( push-context context ) ) ) ( add ' ( has ,player ,square ) ) remove ' ( free ,square ) ( makemove ( other player ) ) return ( winmoves player ) nil try-next cdefun forcewin (cdefgen winmoves (player) "aux" (square1 p1 square2 p2 x) (csetq p1 (fetch '(has ,player ?square1))) :outerloop (try-next p1 '(adieu)) (csetq p2 (fetch '(has ,player ?square2))) :innerloop (try-next p2 '(go 'outerloop)) (cond ((lessp square1 square2) (cond ((csetq x (third-in-row square1 square2)) (cond ((present '(free ,x)) (note x))))))) (go 'innerloop))

Conniverで良く知られている機構に、Hairy Control Structureというものがありますが、Scheme方面では継続の操作として整理された所です。

呼び出した関数から途中で一度抜けて、残りを実行したりしていますが、

( ) "aux" ( place ) cond ( csetq place ( zowie ) ) go place cdefun printfoobar (cdefun zowie () (print 'foo) (return (tag 'printbar)) :printbar (print 'bar) nil) (printfoobar)

Schemeだとこんな感じでしょうか(Scheme力が弱くていまいち)

define ( printfoobar ) ( zowie ) define place ( place ) values (define (zowie) (call/cc (lambda (return) (print 'foo) (call/cc (lambda (printbar) (return printbar))) (print 'bar) (lambda () #f)))) (pirntfoobar)

ConniverからベースのLisp処理系の関数は任意に呼び出せますが、LispからConniverの関数を呼ぶには、 @ 構文等を使いる等作法があるようです。

Micro-Plannerでもそんな感じでしたが、今でいうとShenが似たような感じかなあと思います(LispからShenを呼ぶ方法は用意されていないですが)

後続のLispに影響を与えていそうなところ

closure 構文がありますが、これはLisp Machine Lispの closure 構文と似た感じです。しかし、取り込む変数の指定がないので、環境全部を取り込むのかもしれません。

また、関数と変数の文脈の曖昧さ/意図せぬシャドウを無くすために call がありますが、MACLISPの funcall はこれに影響を受けて導入されたのかもしれません。

もしそうならMACLISPにも call という名前そのままで導入して欲しかったかも。

体験

Sail Dartにソースらしきものがありますが新しめのMACLISPでは動きませんでした。

是非、誰か動かしてみて下さい……。

まとめ

今回は、Conniverを紹介してみました。

Planner→Conniver→Scheme→Racketと続く命名シリーズですが、Conniverはちょっと影が薄いかもしれないですね。

ただ、多様な制御機構については、Schemeに受け継がれていった気はします。

参考文献

■

