guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

functional streams in guile-log


From: Stefan Israelsson Tampe
Subject: functional streams in guile-log
Date: Thu, 13 Nov 2014 22:04:59 +0100

Hi all,

After my newly release of guile-log, I've started to improve on guile-log's features. One of the miss-features of guile file handling is that streams are mutable structures and mostly lack functional interfaces. Therefore backtracking and streams does not mix well. Also for a huge field of applications, the overhead of functional interfaces are dwarfed by other overhead in e.g. the parsing and compiling if we consider parsing as an application of functional streams. A feature request would be to enable functional streams in guile-log, but how?

Functional streams is my next feature goal of guile-log, and the way to implement this is to encapsulate the functional data-structure in a fluid and update the value of the fluid in a functional manner. Doing this, there is then a interface in guile-log that can for example enable a stream to backtrack, or to make sure that it stores and restores it's state in a controlled fashion as well as mimicking ordinary streams. It would be possible to have a pure data structure and get it to backtrack, but that will not mix well with normal stream code and hence code reuse of prolog program would be minimal. I also plan to introduce functional streams in the parser to make it fully functional.

Functional streams or not black magic but quite simple data-structures, these are what I define (oh yes (srfi-9 gnu) is wonderful),

(define-immutable-record-type <fstream-rw>
  (make-fstream-rw n m l r meta)
  fstream-rw?
  (n     fstream-n     set-fstream-n)
  (m     fstream-m     set-fstream-m)
  (l     fstream-l     set-fstream-l)
  (r     fstream-r     set-fstream-r)
  (meta  fstream-meta  set-fstream-meta))

(define-immutable-record-type <fstream-r>
  (make-fstream-r m r meta)
  fstream-r?
  (m     fstream-m     set-fstream-m)
  (r     fstream-r     set-fstream-r)
  (meta  fstream-meta  set-fstream-meta))

(define-immutable-record-type <fstream-w>
  (make-fstream-rw n l meta)
  fstream-rw?
  (n     fstream-n     set-fstream-n)
  (l     fstream-l     set-fstream-l)
  (meta  fstream-meta  set-fstream-meta))

A rw version can both read and write, and if we concentrate on the r and l fields we could say e.g. that at t=0, we have
l=(2 1)
r=(3 4)

Then at t=1 read will give a new state
l=(3 2 1) 
r=(4)
res = 3

At t=2  write(10) would then give
l=(10 3 2 1)
r=()
res = void

At t=3 nother write(11) would give
l=(11 10 3 2 1)
r=()
res=void

Rewind to t=1
An insert(10) at t=2b would give
l=(10 3 2 1)
r=(4)

An peek at t=3b would give
l=(10 3 2 1)
r=(4)
res=4

At opening a file a functional stream reads in the whole file and put the char
list in r in the right order, and at closing the stream the whole data-structure is written to file in the correct order, also the data-structure is symmetric in that all operations can be reversed in the other direction. The drawback with the rw version is that for backtracking patterns the memory consumption can be quite hefty, a pure read or write version is more controllable when it comes to memory consumption. Also the overhead of recreating structs with many fields for each operation is mitigated in the guile-log parser code by simply reading a chunk (line) at a time hence reduce the consing something like 4x. 

So I plan to use these functional streams in a fluid together with guile's old streams in a unified interface in guile-log's prolog, They can then be requested at stream creation and then used seamlessly beside the standard ones, but the difference is that the user can control backtracking and state management features of it and you can quite easy make sure that the stream e.g. backtracks with the logical program. That's pretty neat.

Cheers!
/Stefan







reply via email to

[Prev in Thread] Current Thread [Next in Thread]