Behavior of set_stream/2 on output streams created on atoms

I’m using: SWI-Prolog version 8.1.12 on Mac OS

It seems that set_stream/2 is breaking the behaviour of with_output_to/2. For example, if I create a stream with output to atom and set its encoding to UTF-8:

?- with_output_to(atom(A), (set_stream(current_output,encoding(utf8)),format('hello ~w',[world]))).
A = '������������'.

Trying to output to codes gives:

?- with_output_to(codes(A), (set_stream(current_output,encoding(utf8)),format('hello ~w',[world]))).
A = [1819043176,1870078063].

Which gives a hint that internally it is still using wchar_t.

Without setting the encoding the code works as intended:

?- with_output_to(atom(A), (format('hello ~w',[world]))).
A = 'hello world'.

Do output streams created on atoms/strings/codes support set_stream(Out, encoding(x))?

3 Likes

That will indeed not work. Why would you want that? The temporary stream has an encoding that supports all characters that can be represented and thus you get consistent results. We could use a dedicated stream and prevent encoding switches. Not sure whether that is worth the trouble.

The reason I’m asking is that I’m trying to send RDF graph in XML format using HTTP POST request. So, I’m doing rdf_save/2 to atom and then http_post/4 like this:

with_output_to(atom(Atom), (current_output(Out), rdf_save(stream(Out), [graph(mygraph)]))),
http_post(URI, atom(ContentType, Atom), _, []).

Internally rdf_save/2 always sets the encoding of the stream and, hence, my atom becomes garbage.

The same code works with rdf_save_turtle/2 because it checks if stream already has encoding wchar_t and does not modify it.

Is there a better way to send RDF graph in XML in an HTTP POST? Or shall I create a pull request that fixes rdf_save/2 behaviour in this respect?

If the graphs are large, memory files, which you can also pass to a POST request will be more efficient as the huge atom will only disappear on the next atom-GC (when unreachable). Not sure whether or not that fixes this problem. When really large, using file(Type,File) would be another option.

I think that makes sense. I’'ll surely accept it. Thanks.

In this case, would it be possible to ignore any encoding changes on temporary streams so that no downstream modifications are necessary?

Technically, probably yes. Not sure. Surely we can raise a permission error. I’m not sure whether ignoring is a good idea. That depends on the reasons one may have to change the encoding.

1 Like

A raised error with a note in the docs should work. Not sure about the compat. But I guess it won’t hurt rdf_save/2 workflow much in this case.

Pushed e56da42d6ac3d3e574c30298e3211fc6db6bd32b. We’ll see whether that raises unexpected issues …

2 Likes

Created pull request #90. Instead of using stream property to pass encoding around, I use Options. open_output/4 is copied from rdf_turtle_write.pl.

1 Like