Hasan Al-Baghdadi
Hasan Al-Baghdadi

Reputation: 452

Is there some sort of null IOStream in Julia?

In the Julia module I'm working on, I need to be able to store multiple files that I can write to dynamically at different parts in the code. So I've created a mutable struct that looks something like this.

mutable struct foo
    file_1::IOStream
    file_2::IOStream
    file_3::IOStream
end

how would I go about initialising something like this before I generate the IOStream, I've tried the following, but they don't seem to work.

foobar = foo(undef,undef,undef)

foobar = foo(nothing, nothing, nothing)

foobar = foo(0,0,0)

But none of them seem to work.

Upvotes: 1

Views: 252

Answers (2)

Bogumił Kamiński
Bogumił Kamiński

Reputation: 69949

If you want to allow for creation of an uninitialized mutable struct you can define an inner constructor fro example like this:

mutable struct foo
    file_1::IOStream
    file_2::IOStream
    file_3::IOStream

    foo() = new()
end

And now when you have:

julia> foobar = foo()
foo(#undef, #undef, #undef)

Of course before accessing fields of foobar you have to assign some value to it.

You can check if field of foobar is assigned using isdefined, e.g. isdefined(foobar, :field_1). The only small inconvenience is that isdefined will also work if you write something like isdefined(foobar, :field_100) and return false (so you have to be sure that you are checking an existing field, e.g. by using the fieldnames function or the hasfield function; the latter is available only in Julia 1.2)

An alternative is to define foo in the following way:

mutable struct foo
    file_1::Union{IOStream, Nothing}
    file_2::Union{IOStream, Nothing}
    file_3::Union{IOStream, Nothing}

    foo(file_1=nothing, file_2=nothing, file_3=nothing) =
        new(file_1, file_2, file_3)
end

(you could omit defining an inner constructor in this case)

Now you can write:

julia> foobar = foo()
foo(nothing, nothing, nothing)

The benefit of this approach is that you can safely access fields of foobar and test for their value, e.g.:

julia> foobar.file_1 === nothing
true

EDIT

Returning to your original question from another angle there is a devnull variable that discards all data written to it. However its type is Base.DevNull which is a subtype of IO. Therefore, you could also write:

mutable struct foo
    file_1::Union{IOStream, Base.DevNull}
    file_2::Union{IOStream, Base.DevNull}
    file_3::Union{IOStream, Base.DevNull}

    foo() = new(devnull, devnull, devnull)
end

In this way you can write to file_1, file_2 and file_3 all the time and by default what you write is discarded.

Upvotes: 3

Hasan Al-Baghdadi
Hasan Al-Baghdadi

Reputation: 452

I found out I can make an empty IOStream ans edit it late so that it would look something like this:

foobar = foo(IOStream(string()),IOStream(string()),IOStream(string()))

Upvotes: 0

Related Questions