LoginSignup
1
0

並列Lispでスクリーンに出力するには。

Last updated at Posted at 2024-05-11

副作用も必要

副作用は竹内関数(たらいまわし)のように値だけが問題ならば必要ないのですが、何らしかの表示をしようとすると画面表示のための副作用が必要となります。ところが子Lispの出力はPipeで親Lispにつながっています。このままでは出力を画面表示することができません。さて、どうしましょうか?

親Lisp経由

ChatGPTと相談しつつ、いくつかの方法を検討しました。Pipeの代わりにソケットを使う、あるいは共有メモリが使えば標準出力が子Lispにおいても使えます。しかし、そうすると全面的に書き直さないといけません。Pipeを使う方法はお手軽です。

そこで、Pipeを使いつつ画面表示のためのプロトコルを決めて、親Lispの標準出力により画面出力をすることにしました。アスキーコードx02が使えることがわかりました。これだと他に影響を与えません。x02で挟まれた文字を見つけたらはそれは標準出力に書き出すこととしました。親Lisp側の recieve_from_pipeを書き換えました。次のように改良してあります。

int read_from_pipe(int n)
{
    char buffer[256];
    int i,j;

    // set nonblock mode
    int flags = fcntl(pipe_c2p[n][R], F_GETFL, 0);
    fcntl(pipe_c2p[n][R], F_SETFL, flags | O_NONBLOCK);

    int bytes_read;
    reread:
    // wait until get result
    while ((bytes_read = read(pipe_c2p[n][R], buffer, 256)) == -1 && errno == EAGAIN);
    buffer[bytes_read] = '\0';

    
    if (buffer[0] == '\x02'){
        i = 1;
        rewrite:
        while(buffer[i] != '\x02' && i < 256){
            putc(buffer[i],stdout);
            i++;
        }
        i++;
        if (buffer[i] == '\x02'){
            i++;
            goto rewrite;
        }
        else if (buffer[i] == '\0'){
            /* still not recieve result */
            for(i=0;i<256;i++){
                buffer[i] = 0;
            }
            goto reread;
        }
        else {
            /* already recieved result */
            j = 0;
            while(buffer[i] != '\0'){
                buffer[j] = buffer[i];
                i++;
                j++;
            }
            buffer[j] = '\0';
        } 
               
    }
    
    return(make_str(buffer));
}

format関数の独自拡張

format関数に独自拡張を加えることとしました。(format (standard-output) str ...) のstrの部分で~!で囲まれた部分につきアスキーコードのx02で挟むこととしました。

(format (standard-output) "~!Hello World~! )

テスト

並列構文のmp-execを使って試しました。1秒まって子Lispからメッセージを出力するものです。

(defun bar (x y)
    (mp-exec (uoo x) (uoo y)))

(defun uoo (x) 
    (format (standard-output) "~! test1 ~A ~%~!" x)
    (finish-output (standard-output))
    (sleep 1)
    (format (standard-output) "~! test2 ~A ~%~!" x)
    (finish-output (standard-output))
    (sleep 1)
    t)
    
Easy-ISLisp Ver3.92
> (mp-create 2)
T
> (load "./tests/para.lsp")
T
> (bar 1 2)
 test1 1 
 test2 1 
 test1 2 
 test2 2 
T
> 

実装

Easy-ISLispはOSSです。修正BSDライセンスのもとで自由にお使いください。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0