That’s a very good explanation and now I understand how to work with ulisp streams better than I did before. with-input-from-string
looks really useful. That said I have several requests and questions. The first thing I thought of was having a function that let you read up to your chosen delimeter instead of just a newline. It turns out ulisp has this internally as readstring
but its not exposed. So here’s my attempt at providing it:
object *fn_readuntil (object *args, object *env) {
(void) env;
object *obj = first(args);
gfun_t gfun = gstreamfun(rest(args));
char delim = checkchar(obj);
return readstring(delim, false, gfun);
}
const char string_readuntil[] PROGMEM = "read-until";
const char docreaduntil[] PROGMEM = "(read-until delim [stream])\n"
"Reads characters from the serial input up to the specifed delimiter character,\n"
"and returns them as a string, excluding the delimiter.\n"
"If stream is specified the line is read from the specified stream.";
//const tbl_entry_t lookup_table2[] PROGMEM = {
{ string_readuntil, fn_readuntil, 0212, docreaduntil },
//};
My second issue is with the way read-line
(and read-until
) handles string streams that don’t terminate in a newline (or delimiter), where they will show an error and return nothing. I’m not sure if that’s the most useful behavior because I would think that not finding a line or delimiter would be something that the function would expect. I suppose one can always append a newline or delimiter to the end if they don’t want the function to fail, but that seems awkward. I don’t know how to handle that scenario any better though, and that seems to be how Common Lisp handles it as well? For Arduino you get functions like find
, findUntil
, peek
, and available
. Would it make sense to implement that functionality here to help deal with that? Or what’s a good way to deal with this?