Here’s an example.
This works, and correctly evaluates to “success”:
(with-output-to-string (s) (princ "success" s))
However, this returns an empty string:
(with-output-to-string (s) (string #\1) (princ "success" s))
The issue seems to be that with-output-to-string uses the GlobalString values to implement the stringstream, and relies on them remaining intact throughout the evaluation of all of its form arguments. However, many other functions in uLisp also call startstring() and thereby overwrite GlobalString (including string, format nil and a few others).
This behavior is quite surprising, because it is not obvious from the outside which functions will interfere with the stringstream.
A few possible directions for fixing this:
- Check in
startstring()whether GlobalString is already set (non-NULL). If already set, error out. Using functions likestringinside ofwith-output-to-stringwould fail, but this is much better IMHO than generating undefined behavior. This would also have the side-benefit that nested uses ofwith-output-to-stringwould be caught. However, all functions that usestartstring()will need to be modified to unset the value when they’re done. - Turn GlobalString into a stack (i.e. list?) to support nested usage. Would also require each function that starts a new one to pop it off the stack again before return.
- As far as I can tell, with-output-to-string is the only function that allows evaluating other forms while using GlobalString. Hence, it might also be enough to maintain a second set of GlobalString variables just for stringstream. with-output-to-string would use this separate set of GlobalString variables, while other string-related functions would use the current existing one. The puts functions for printing into a string would need to be wrapped into two versions, one for each global string.
There are probably some additional complications for some of these that I missed or haven’t thought through.
If you have a preferred direction for fixing this, I can try to take a stab at making a patch…