Mukai Systems

Parenist養成ゼミ: 入出力

この記事は、Parenist養成ゼミシリーズの記事である。

今回は、入出力というテーマで講義を行った。プログラムで入出力ができるようになると一気に実用的なプログラムを作成することができるようになる。

入出力関数

Parenには以下に示す読み書きの関数が備わっている。

read 
    read -- read S-expression.
    read-byte -- read a byte.
    read-bytes -- reads the specified length or all the rest.
    read-char -- read a character.
    read-line -- read one line.
write
    write -- write S-expression.
    write-byte -- write a byte.
    write-bytes -- write bytes-like object.
    write-line -- write bytes-like object and new line.

stream

入出力を行う対象のことをstreamという。Parenの入出力関数はstreamを動的にsymbol$in, $outから参照する。

$in, $outの初期値は、標準入出力である$stdin, $stdoutである。

例えば、catは以下のように実装できる。

(function cat ()
  (let (byte nil)
    (while (!= (<- byte (read-byte)) -1)
      (write-byte byte))))

行単位にすると以下のようになる。

(function cat ()
  (let (line nil)
    (while (<- line (read-line))
      (write-line line))))

Parenでは標準入出力の他にfile streamとstring streamをサポートしている。

file stream

with-openmacroを用いて、$in, $outをfile streamに束縛することができる。

ファイル./parenrcの読み書きを行う例を示す。

(with-open ($out "~/.parenrc" :write)
  (import :datetime)
  (write-line (str "; parenrc. -- this This file was generated at " (.to-s (datetime.now))))
  (write '(write-line "You must have a lot of time on your hands"))
  (write '(write-line)))

(with-open ($in "~/.parenrc" :read)
  (write-line (read-line))
  (while (write (read))))

string stream

with-memory-streammacroを用いて、$in, $outをstring streamに束縛することができる。

(with-memory-stream ($in "aaline\n(+ (- 3 2) 4))")
  (write (read-byte))
  (write (read-char))
  (write (read-line))
  (write (read)))
(with-memory-stream ($out)
  (write-byte 97)
  (write-bytes "a")
  (write-line "line")
  (write (list '+ (list '- (+ 1 2) 2) (+ 2 2))))

課題