こんにちは、chibaです。
アクトインディ Advent Calendar 2015 の17日目の記事です。
第五世代コンピュータープロジェクトとは、1980年代前半から当時の通産省のバックアップで進められた次世代のコンピューターの研究プロジェクト(ICOT)です。
この次世代のコンピュータを指して「第五世代コンピューター」なのですが、この 世代 とは、コンピュータの発展を世代に分けて表現したもので、
と来て、第五世代は、多数のプロセッサによる超並列処理で人工知能だ!ワッショイ!という感じだったようです。
第五世代コンピュータープロジェクトでは、プログラミング言語には論理型が採用されましたが、並列プロセッサが前提であるため、並行論理プログラミング言語である、GHCやその派生であるKL1が生み出され、KL1はプロジェクトの核となる言語となりました。
このKL1をCで実装したものが、先週akiyamaが紹介したKLICになります。
社内インフラ業務でもKL1を
さて、前置きが長かったですが、日々の社内インフラ業務でも第五世代コンピューターの恩恵に浴したい訳です。
KLICが弊社システムでも動くようになったので、まずは手始めに日々のバックアップスクリプトをKL1で書いてみるかということになりました(私的に)。
ファイルのバックアップではrsync
を利用することが多いのですが、こんな感じに書けました。
:- module main.
main :- Basedir="/backup/dir",
Remotedir="user@remotehost:/files",
joinstrings(["rsync -av --delete ", Remotedir, Base_dir, ">/dev/null && echo OK || echo Something went wrong."], " ", Cmd),
unix:system(Cmd, 0).</p>
joinstrings([], Sep, Ans) :- Ans = "". joinstrings([Sa|Sd], Sep, Ans) :- join_strings(Sd, Sep, Ans1), generic:join(Sep, Ans1, Ans2), generic:join(Sa, Ans2, Ans). </code>
KLICには、unix:system
という述語がありますが、これが結構使い勝手が良いです。
さて、これをklic
でコンパイルし、実行します。
$ klic -o backitup backitup.kl1
backitup という実行ファイルができるので、後は利用するのみです。ヤッター。
KLICで生成したバイナリの便利なところ
KLICはCへのトランスレータで、Cのソースをコンパイルして実行ファイルを生成しますが、生成されたバイナリには、基本的なオプションが付きます。
helpを始めとして、GCや並列実行時のオプションを渡すことが可能ですが、-t
を付けることでトレースを掛けることが可能です。
例えば今回の場合は、
user@remotehost:~$ bin/backitup -t
1 CALL: main:main?
1 REDU: main:main :-
2 0:+join_strings(["rsync -..","user@rem..","/backup..",">/dev/n.."]," ",_6)
3 1:+unix:system(_6,0)?
2 CALL: main:join_strings(["rsync -..","user@rem..","/backup..",">/dev/n.."]," ",_6)?
2 REDU: main:join_strings(["rsync -..","user@rem..","/backup..",">/dev/n.."]," ",_6) :-
4 0:+join_strings(["user@rem..","/backup..",">/dev/n.."]," ",_1B)
5 1:+generic:generic(join(_1B,_14)," ")
6 2:+generic:generic(join(_14,_6),"rsync -..")?
4 CALL: main:join_strings(["user@rem..","/backup..",">/dev/n.."]," ",_1B)?
4 REDU: main:join_strings(["user@rem..","/backup..",">/dev/n.."]," ",_1B) :-
7 0:+join_strings(["/backup..",">/dev/n.."]," ",_2E)
8 1:+generic:generic(join(_2E,_27)," ")
9 2:+generic:generic(join(_27,_1B),"user@rem..")?
7 CALL: main:join_strings(["/backup..",">/dev/n.."]," ",_2E)?
7 REDU: main:join_strings(["/backup..",">/dev/n.."]," ",_2E) :-
10 0:+join_strings([">/dev/n.."]," ",_41)
11 1:+generic:generic(join(_41,_3A)," ")
12 2:+generic:generic(join(_3A,_2E),"/backup..")?
10 CALL: main:join_strings([">/dev/n.."]," ",_41)?
10 REDU: main:join_strings([">/dev/n.."]," ",_41) :-
13 0:+join_strings([]," ",_54)
14 1:+generic:generic(join(_54,_4D)," ")
15 2:+generic:generic(join(_4D,_41),">/dev/n..")?
13 CALL: main:join_strings([]," ",_54)?
13 REDU: main:join_strings([]," ","")?
14 CALL: generic:generic(join("",_4D)," ")?
14 REDU: generic:generic(join(""," ")," ")?
15 CALL: generic:generic(join(" ",_41),">/dev/n..")?
15 REDU: generic:generic(join(" ",">/dev/n.."),">/dev/n..")?
11 CALL: generic:generic(join(">/dev/n..",_3A)," ")?
11 REDU: generic:generic(join(">/dev/n.."," >/dev/..")," ")?
12 CALL: generic:generic(join(" >/dev/..",_2E),"/backup..")?
12 REDU: generic:generic(join(" >/dev/..","/backup.."),"/backup..")?
8 CALL: generic:generic(join("/backup..",_27)," ")?
8 REDU: generic:generic(join("/backup.."," /backu..")," ")?
9 CALL: generic:generic(join(" /backu..",_1B),"user@rem..")?
9 REDU: generic:generic(join(" /backu..","user@rem.."),"user@rem..")?
5 CALL: generic:generic(join("user@rem..",_14)," ")?
5 REDU: generic:generic(join("user@rem.."," user@re..")," ")?
6 CALL: generic:generic(join(" user@19..",_6),"rsync -..")?
6 REDU: generic:generic(join(" user@19..","rsync -.."),"rsync -..")?
3 CALL: unix:system("rsync -..",0)?
OK
3 REDU: unix:system("rsync -..",0)?
こんな感じになりますが、これは良い機能ですね。
まとめ
KL1を社内インフラ業務に使うという話でした。
実際に日々のバックアップ作業にも投入し、第五世代コンピューティングの息吹きを感じることで日々の業務のモチベーションを高めています。
なお、今回の場合、KL1というより、ほぼPrologのコードで、並列性も全然活かしていませんが、今後の発展に期待しています。
■