Temporarily redirect write/1 or current_output to a file

You have code that uses write/1 which writes to the predefined stream current_output but you want write/1 to write to a file. You could change all of write/1 to write/2 but there is another option.

Since write/1 writes to current_output you can temporarily substitute in another stream for current_output. How you ask. Use setup_call_cleanup/3, stream_property/2, open/4, set_stream/2 or set_output/1 and close/1. Also see Predefined stream aliases

Example code

setup_call_cleanup(
    (
        stream_property(Original,alias(current_output)),
        open('file_name',write,S,[]),
        set_stream(S,alias(current_output))
    ),
    write('Hello, World!'),
    (
        close(S),
        set_stream(Original,alias(current_output))
    )
)

Also note that

set_output(S)

can be used instead of

set_stream(S,alias(current_output))

Noted in case you read code and see this, there is no difference AFAIK.


A use case for this is when using portray/1 for which it is not uncommon to see used with write/1. I don’t have enough experience with portray/1 to claim that write/1 is commonly used with portray/1.

The specific use for which I need this is to parse ABNF to a term/structure using DCGs, then use portray/1 to convert the term/structure back into text. Then parse the created text again and check to make sure that both the outputs from portray/1 are identical, or for those in the know to reach a fixed point.


EDIT

Example of using with_output_to/2 as noted by SWI for fixed_point_check/1

You can also use with_output_to/2. It is very useful, especially for test cases when the goal produces a certain output and you want the test suite to verify this.

1 Like

Yep, with_output_to/2 does the same thing.

I should rewrite this to redirect input now that you stole the show. Don’t tell me there is a with_input_from/2. :wink:

EDIT

Found with_input_from/2

We really should write that cookbook. :thinking:

1 Like

hehehe, you are funny :slight_smile:

1 Like