Unexpected result using with_output_to and string(S)

Loosely related, since S is a string in the example below. Note that S ends up being empty:

?- with_output_to(string(S), license).
% SWI-Prolog is covered by the Simplified BSD license:
% 
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions
(...)
% additional conditions.  These components are:
% 
%     libgmp
S = "".

Is this a feature or a bug? I guess it has to do with print_message printing to user_error.

Workaround:

new_memory_file(M), 
open_memory_file(M, write, S), 
set_stream(S, alias(user_error)), 
license, 
close(S),
memory_file_to_atom(M, A),
free_memory_file(M).

If you check the documentation for with_output_to/2 it notes

Run Goal as once/1, while characters written to the current output are sent to Output.

If you look at the code for license using listing, i.e.

?- listing(license).

is shows

 print_message(informational,
                  license(GPL,
                          LGPL,
                          Permissive,
                          Proprietary)).

and the print_message/2 documentation notes

Printing messages through this indirection instead of using format/3 to the stream user_error

Since the license text is being output to user_error, with_output_to/2 will not capture it. :slightly_smiling_face:

There seems to be a with_output_to/3, but it is not found on my system (neither linux or windows), since library(streams) is not installed.

Since really shortly, there is library(streams) that defines with_output_to/3, so we can do

?- with_output_to(string(S), license, [capture([user_error])]).
S = "% SWI-Prolog is covered by the Simplified BSD license ... "

This is part of some ongoing work towards proper parallel testing and provide a ctest like --output-on-error

For those looking for the exact date it is Dec 2, 2022

I only knew of it from checking the latest commits every morning.

All right, found it, thanks!

The name of the library is obviously misleading. library(streams) suggests that it’s been there since the 1980ies, with their tell/1, told/0, you name it :slight_smile: One would really not expect to find it only in the recent swipl-devel.

You’d preferred “new_streams” :slight_smile: I think the name is fine. Stream handling is mostly built-in. This library is about more high level stream operations. Having a library with a single predicate is a bit of an overkill. We’ll see where it goes.

1 Like