I can't seem to find a way to seek in and get the position in files using Gambit (4beta11). Wouldn't this be a handy feature?
Yes, I have been planing this for a while and have just completed the implementation and documentation. Here it is:
@deffn procedure input-port-byte-position @var{port} @r{[}@var{position} @r{[}@var{whence}@r{]}@r{]} @deffnx procedure output-port-byte-position @var{port} @r{[}@var{position} @r{[}@var{whence}@r{]}@r{]}
When called with a single argument these procedures return the byte position where the next I/O operation would take place in the file attached to the given @var{port} (relative to the beginning of the file). When called with two or three arguments, the byte position for subsequent I/O operations on the given @var{port} is changed to @var{position}, which must be an exact integer. When @var{whence} is omitted or is 0, the @var{position} is relative to the beginning of the file. When @var{whence} is 1, the @var{position} is relative to the current byte position of the file. When @var{whence} is 2, the @var{position} is relative to the end of the file. The return value is the new byte position. On most operating systems the byte position for reading and writing of a given bidirectional port are the same.
When @code{input-port-byte-position} is called to change the byte position of an input-port, all input buffers will be flushed so that the next byte read will be the one at the given position.
When @code{output-port-byte-position} is called to change the byte position of an output-port, there is an implicit call to @code{force-output} before the position is changed.
For example:
@smallexample
@b{(define p @r{@i{; p is an input-output-port}}
(open-file '(path: "test" char-encoding: latin1 create: maybe)))}
@b{(list (input-port-byte-position p) (output-port-byte-position p))}
(0 0)
@b{(display "abcdefghij\n" p)} @b{(list (input-port-byte-position p) (output-port-byte-position p))}
(0 0)
@b{(force-output p)} @b{(list (input-port-byte-position p) (output-port-byte-position p))}
(11 11)
@b{(input-port-byte-position p 2)}
2
@b{(list (input-port-byte-position p) (output-port-byte-position p))}
(2 2)
@b{(peek-char p)}
#\c
@b{(list (input-port-byte-position p) (output-port-byte-position p))}
(11 11)
@b{(output-port-byte-position p -7 2)}
4
@b{(list (input-port-byte-position p) (output-port-byte-position p))}
(4 4)
@b{(write-char #! p)} @b{(list (input-port-byte-position p) (output-port-byte-position p))}
(4 4)
@b{(force-output p)} @b{(list (input-port-byte-position p) (output-port-byte-position p))}
(5 5)
@b{(input-port-byte-position p 1)}
1
@b{(read p)}
bcd!fghij @end smallexample
@end deffn
Also, while I'm making suggestions: Have you thought about implementing a simple package system, for example something like Chicken Scheme's eggs[3]?
No. I'm not saying this wouldn't be useful, just that I haven't perceived a need for it yet. There's really nothing to change in Gambit itself to implement a package system like the one Chicken uses because Gambit's installation directory (/usr/local/Gambit-C) can be used for this. The subdirectory /usr/local/Gambit-C/package would store the installed packages, and the programs would use these packages like this:
(include "~~/package/Xlib.scm") (include "~~/package/arrays.scm") ...
or
(load "~~/package/foo")
The system extension file (~~/gambcext) could also be modified for the packages that need to permanently extend Gambit (this file is loaded whenever the interpreter is started).
The most tedious in all of this is to implement the package management tool that installs the packages, compiles them if needed, checks for the latest version, checks package dependencies, etc. If you want to contribute such a tool please be my guest. What I can do is help you out in the design and host the packages that people contribute on Gambit's web site.
Of course some of this work may have to be duplicated when the R6RS module system comes out...
Marc