Help us understand the problem. What is going on with this article?

PrologなNoSQLサーバを立てる

More than 5 years have passed since last update.

はじめに

なんの需要があるかわかりませんが,あるとき突然,Prologサーバを立てたくなる時があります.例えば,サーバ側では,大量の述語をデータベース代わりに持っていて,TCP通信でクエリを投げてその結果を得ることができたらな,と思うわけです.

データとして以下の述語を与えます.

tag_name(oppai).
tag_name(bikini).

picture(aaa).
picture(bbb).
picture(ccc).

tag(X, Y) :- tag_name(X), picture(Y).

tag(oppai, aaa).
tag(oppai, bbb).
tag(oppai, ccc).
tag(bikini, bbb).
tag(bikini, ccc).

tagの第一引数はタグの名前で,第二引数は画像の名前です.特定のタグの付けられた画像を検索する場合,以下の述語で推定することができます.

tag(bikini, X).
% X = tag(bikini, bbb);
% X = tag(bikini, ccc);

速度的に何千万件のデータを扱うのは難しいかもしれませんが,NoSQLの試みとして面白いなと思ったわけです.

サーバ側の実装

サーバ側で起動しておくPrologのソースコードです.

create_server(Port) :-
    tcp_socket(Socket),
    tcp_bind(Socket, Port),
    tcp_listen(Socket, 5),
    tcp_open_socket(Socket, AcceptFd, _),
    dispatch(AcceptFd).

dispatch(AcceptFd) :-
    tcp_accept(AcceptFd, Socket, _Peer),
    thread_create(process_client(Socket, Peer), _,
        [ detached(true)
        ]),
    dispatch(AcceptFd).

process_client(Socket, Peer) :-
    setup_call_cleanup(tcp_open_socket(Socket, In, Out),
       handle_service(In, Out),
       close_connection(In, Out)).

close_connection(In, Out) :-
    close(In, [force(true)]),
    close(Out, [force(true)]).

handle_service(In, Out) :-
    read(In, Chars),
    findall(Chars, Chars, L),
    write(Out, L),
    writeln(L).

% 以下,データベース用の述語を定義する

Prologのコンソールから,以下のコードを実行すると,ポート3333でListenします.

create_server(3333).

クライアント側の実装

クライアント側はTCP通信でポートを指定して接続します.ここではRubyですが,他の言語については頑張って実装してください.

require "socket"

while gets
  s = TCPSocket.open("localhost", 3333)
  s.write($_)
  puts s.gets
  s.close
end

このソースコードを実行すると,TCPソケットを開いてユーザからの入力を待ちます.Prologの述語を書くと,localhostで実行しているPrologサーバに述語を送信し,その内容を推定し,結果を返します.

tag(X,Y).
[tag(oppai,a),tag(oppai,b),tag(oppai,c),tag(bikini,b),tag(bikini,c)]

Prologの将来

Prologの推定は,他のRDBMSやNoSQLにはない機能です.似たような処理は確かに他でも書くことは可能ですが,Prologほど簡潔には書けません.例えば,SQLであれば以下の様なクエリになると思います.

select picture.name from picture, tag where tag.picture_id = picture.id;

Prologと比べるといかに冗長であるということがわかると思います.

また,先のデータベース用の述語では,tag_nameとpictureを定義していましたが,別にきちんとスキーマが決まっていれば,この2種類の述語は必要ありません.その点で,NoSQL並みの柔軟さがあり,(使い方さえわかれば)簡潔なクエリを投げることが出来ます.

あとはほぼ速度やアーキテクチャの問題なので,いつかPrologがNoSQLで脚光を浴びるんじゃないかなぁとか思うのですがどうでしょう? Prologプログラミング自体は悟りが必要なので難しいかもしれませんが,シンプルな方法であれば十分に使用に耐えられると思います.

GRGSIBERIA
なんでもやる人.元未踏クリエータ.三次元幾何学と音響工学を少々.
http://www.grgsiberia.net/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした