>
> I understand that to you this seems intuitive, but to me it is completely
> counter-intuitive. The function that I'm calling is not changing any of its
> inputs. Telling me that behind the scenes it calls "plots!" is describing
> an implementation detail that can change and should have no bearing on the
> exposed API.
>
It's not behind the scenes or an implementation detail. The "proper,
exposed" API looks like:
plt = plot(rand(10))
plot!(plt, xlim = (0,20))
Here plt is a julia object. It's constructed during the first call, and
changed in the second call. This is the only form that should be used for
"serious" work, as you shouldn't depend on global state in general. For
your original example, you were on the right track:
plt = plot(title = "...", xaxis = (...), ...)
for dir in directories
... do some work ...
plot!(plt, result, ...)
end
You can set up the plot attributes in the first call, and then add series
(data) with your results.
In your original code, what if there's something in that "do some work"
that calls a plotting command? (answer... your code breaks) So the
mutating plot call without an AbstractPlot as the first argument is really
only meant for quick, one-off, analytic work. It's not meant to be the
primary usage pattern.
I would argue that "plots(plt, ...)" is like "write(stream, ...)"
>
In this example, plt is a julia object that is mutated, whereas stream is
effectively unchanged (it still points to the same file descriptor, or
whatever it wraps).
The better analogies (IMO) are:
plt = plot()
x = rand(10)
# these are similar
push!(x, rand())
plot!(plt, x)
# these are similar
show(io, x)
display(plt)