[julia-users] Opinion on Plots.jl -- exclamation marks

2016-04-08 Thread Daniel Carrera
Hello,

I was looking through the API for Plots.jl

http://plots.readthedocs.org/en/latest/#api


Maybe I'm the only one, but I think all those exclamation marks are a bit 
extraneous and feel like syntactic noise. I have been following Plots.jl 
because I'm interested in plotting. My use of Julia comes down to either 
making plots, or post-processing data so I can make a plots. I get the idea 
from Plots.jl that functions that end in an exclamation mark are supposed 
to modify an existing plot. So you get things like:

plot!(...)  # Add another plot to an existing one.
title!(...)
xaxis!("mylabel", :log, :flip)
xlims!(...)
xticks!(...)

and so on...

This means that in actual usage, almost every line I write needs to have an 
extra `!`. To me this means that the `!` is not adding real information and 
is just syntactic noise. I currently use PyPlot, so I use that as a point 
of comparison. In PyPlot, all commands edit the current plot unless you 
explicitly call `figure()` to create a new plot. You can also use clf() to 
clear the current plot. I think this is something that PyPlot / Matplotlib 
get right. The special syntax lines up with the less common action.

I don't know if anyone agrees with me. I still think Plots.jl is a step in 
the right direction and I'll keep cheering from the stands. I just wanted 
to share my thoughts.

Cheers,
Daniel.


Re: [julia-users] Opinion on Plots.jl -- exclamation marks

2016-04-08 Thread Tamas Papp
Hi,

IMO an extra ! is a small price to pay for consistency --- you are after
all modifying an existing object. Avoiding globals is also a good
strategy.

The lure of terser syntax for common use cases is always there, but I
like to remind myself that I will be the person reading this code in 6
months or a year, and I will be grateful for all the clarity I can
get. That said, maybe my use case differs from yours: I like to write
functions that make plots, so my data analysis programs are more
structured (eg standardize axes, titles, colors, plot types, etc).

Another, more functional-style API could be what ggplot does in R, using
the + operator to create a new plot with the extras.

Best,

Tamas

On Fri, Apr 08 2016, Daniel Carrera wrote:

> Hello,
>
> I was looking through the API for Plots.jl
>
> http://plots.readthedocs.org/en/latest/#api
>
>
> Maybe I'm the only one, but I think all those exclamation marks are a bit
> extraneous and feel like syntactic noise. I have been following Plots.jl
> because I'm interested in plotting. My use of Julia comes down to either
> making plots, or post-processing data so I can make a plots. I get the idea
> from Plots.jl that functions that end in an exclamation mark are supposed
> to modify an existing plot. So you get things like:
>
> plot!(...)  # Add another plot to an existing one.
> title!(...)
> xaxis!("mylabel", :log, :flip)
> xlims!(...)
> xticks!(...)
>
> and so on...
>
> This means that in actual usage, almost every line I write needs to have an
> extra `!`. To me this means that the `!` is not adding real information and
> is just syntactic noise. I currently use PyPlot, so I use that as a point
> of comparison. In PyPlot, all commands edit the current plot unless you
> explicitly call `figure()` to create a new plot. You can also use clf() to
> clear the current plot. I think this is something that PyPlot / Matplotlib
> get right. The special syntax lines up with the less common action.
>
> I don't know if anyone agrees with me. I still think Plots.jl is a step in
> the right direction and I'll keep cheering from the stands. I just wanted
> to share my thoughts.
>
> Cheers,
> Daniel.


Re: [julia-users] Opinion on Plots.jl -- exclamation marks

2016-04-08 Thread Tom Breloff
On Fri, Apr 8, 2016 at 3:44 AM, Daniel Carrera  wrote:

> Hello,
>
> I was looking through the API for Plots.jl
>
> http://plots.readthedocs.org/en/latest/#api
>

If you look just above that, note that I put a big warning that this
section of the docs need updating.  Personally, I hardly ever use those
mutating methods; but some people prefer that style, so I make it available.


> Maybe I'm the only one, but I think all those exclamation marks are a bit
> extraneous and feel like syntactic noise.
>

It modifies a plot, and so follows Julia convention.  Anything else is
likely to induce confusion.


> I have been following Plots.jl because I'm interested in plotting. My use
> of Julia comes down to either making plots, or post-processing data so I
> can make a plots. I get the idea from Plots.jl that functions that end in
> an exclamation mark are supposed to modify an existing plot. So you get
> things like:
>
> plot!(...)  # Add another plot to an existing one.
> title!(...)
> xaxis!("mylabel", :log, :flip)
> xlims!(...)
> xticks!(...)
>

If you don't want to plot like this, then don't!  There's a million ways to
produce the same plot.  If you want to put all your commands in one line,
this will work: plot(rand(10), title="TITLE", xaxis = ("mylabel", :log,
:flip, (0, 20), linspace(1, 10, 20)))

[image: Inline image 1]
Plots figures out that log is the scale, (0,20) is the axis limits, and
linspace(1,10,20) are the tick marks, which reduces a ton of clutter (not
to mention you don't need to remember a complicated API).  One of the key
goals of Plots is that you can use whatever style suits you.  (and feel
free to open issues if there's something that you think can be more
intuitive)


>  In PyPlot, all commands edit the current plot unless you explicitly call
> `figure()` to create a new plot. You can also use clf() to clear the
> current plot. I think this is something that PyPlot / Matplotlib get right.
>

We can agree to disagree on this point.  It's clunky and error-prone.

Quick tip: you can choose to reuse PyPlot windows by default if you want:

# these will effectively call clf() before each command
>
using Plots

pyplot(reuse = true)
> plot(rand(10))
> plot(rand(10))
> plot(rand(10))



- Tom


Re: [julia-users] Opinion on Plots.jl -- exclamation marks

2016-04-08 Thread Daniel Carrera
Hello,

On 8 April 2016 at 15:07, Tom Breloff  wrote:

>
> It modifies a plot, and so follows Julia convention.  Anything else is
> likely to induce confusion.
>

I do see your point of view, and of course it's your library. I also don't
want to diss your work. I think the convention is about modifying inputs,
rather than modifying "something". Functions that modify files don't get
exclamation marks. On the other hand, Gtk.jl is a blend, with functions
like push!() and delete!() but also destroy(), and signal_connect(). The
authors just picked what made sense to them.



>  In PyPlot, all commands edit the current plot unless you explicitly call
>> `figure()` to create a new plot. You can also use clf() to clear the
>> current plot. I think this is something that PyPlot / Matplotlib get right.
>>
>
> We can agree to disagree on this point.  It's clunky and error-prone.
>


Agree to disagree. This is just an opinion.



> Quick tip: you can choose to reuse PyPlot windows by default if you want:
>
> # these will effectively call clf() before each command
>>
> using Plots
>
> pyplot(reuse = true)
>> plot(rand(10))
>> plot(rand(10))
>> plot(rand(10))
>
>
Thanks.

Cheers,
Daniel.


Re: [julia-users] Opinion on Plots.jl -- exclamation marks

2016-04-08 Thread Daniel Carrera
Hello,

Here is an example use case for me. I have several directories with data. I
want to step through each directory, do some work, and plot some result;
all in the same figure:

for dir in directories
... do some work ...
plot(result)
end


Clearly it would be inconvenient if every time I have to do this (which is
all the time) I had to make sure that the first set of results runs
``plot()`` and the others run ``plot!()``. How would you deal with this
using Plots.jl? The solution I can come up with is:

plot()  # Plot nothing.
for dir in directories
... do some work ...
plot!(result)
end

I guess that would be the best option.

Cheers,
Daniel.



On 8 April 2016 at 15:07, Tom Breloff  wrote:

>
>
> On Fri, Apr 8, 2016 at 3:44 AM, Daniel Carrera  wrote:
>
>> Hello,
>>
>> I was looking through the API for Plots.jl
>>
>> http://plots.readthedocs.org/en/latest/#api
>>
>
> If you look just above that, note that I put a big warning that this
> section of the docs need updating.  Personally, I hardly ever use those
> mutating methods; but some people prefer that style, so I make it available.
>
>
>> Maybe I'm the only one, but I think all those exclamation marks are a bit
>> extraneous and feel like syntactic noise.
>>
>
> It modifies a plot, and so follows Julia convention.  Anything else is
> likely to induce confusion.
>
>
>> I have been following Plots.jl because I'm interested in plotting. My use
>> of Julia comes down to either making plots, or post-processing data so I
>> can make a plots. I get the idea from Plots.jl that functions that end in
>> an exclamation mark are supposed to modify an existing plot. So you get
>> things like:
>>
>> plot!(...)  # Add another plot to an existing one.
>> title!(...)
>> xaxis!("mylabel", :log, :flip)
>> xlims!(...)
>> xticks!(...)
>>
>
> If you don't want to plot like this, then don't!  There's a million ways
> to produce the same plot.  If you want to put all your commands in one
> line, this will work: plot(rand(10), title="TITLE", xaxis = ("mylabel",
> :log, :flip, (0, 20), linspace(1, 10, 20)))
>
> [image: Inline image 1]
> Plots figures out that log is the scale, (0,20) is the axis limits, and
> linspace(1,10,20) are the tick marks, which reduces a ton of clutter (not
> to mention you don't need to remember a complicated API).  One of the key
> goals of Plots is that you can use whatever style suits you.  (and feel
> free to open issues if there's something that you think can be more
> intuitive)
>
>
>>  In PyPlot, all commands edit the current plot unless you explicitly call
>> `figure()` to create a new plot. You can also use clf() to clear the
>> current plot. I think this is something that PyPlot / Matplotlib get right.
>>
>
> We can agree to disagree on this point.  It's clunky and error-prone.
>
> Quick tip: you can choose to reuse PyPlot windows by default if you want:
>
> # these will effectively call clf() before each command
>>
> using Plots
>
> pyplot(reuse = true)
>> plot(rand(10))
>> plot(rand(10))
>> plot(rand(10))
>
>
>
> - Tom
>


Re: [julia-users] Opinion on Plots.jl -- exclamation marks

2016-04-08 Thread Steven G. Johnson

On Friday, April 8, 2016 at 4:00:47 AM UTC-4, Tamas Papp wrote:
>
> IMO an extra ! is a small price to pay for consistency --- you are after 
> all modifying an existing object. Avoiding globals is also a good 
> strategy. 
>

Actually, it doesn't seem entirely consistent with Julia conventions. 

The standard Julia convention (borrowed from Lisp/Scheme) is that a ! 
suffix means that a function modifies *one of its arguments*.

Here, however, one of the arguments is not being modified, but rather some 
global object (a plot) is being changed.  Modifying global state is a 
different sort of side effect from modifying an argument.   And, in Julia, 
side-effects in general don't lead to a ! suffix.   (e.g. any I/O is a side 
effect, but functions like println and write in the Julia standard library 
don't have ! suffixes.)

Steven


Re: [julia-users] Opinion on Plots.jl -- exclamation marks

2016-04-08 Thread Tom Breloff
>
>
>>
> Actually, it doesn't seem entirely consistent with Julia conventions.
>
> The standard Julia convention (borrowed from Lisp/Scheme) is that a !
> suffix means that a function modifies *one of its arguments*.
>

The `plot!` command  is primarily `plot!(plt::AbstractPlot, args...;
kw...)`.  In this case it holds to convention.

I have a convenience `current()` which stores the most recently updated
AbstractPlot object in a global, so that any plotting command without a
leading AbstractPlot object gets it added implicitly.  (i.e. a call to
`plot!(...)` is really a call to `plot!(current(), ...)`).

I think this strategy is better than alternatives, and isn't too far from
accepted conventions.


Re: [julia-users] Opinion on Plots.jl -- exclamation marks

2016-04-08 Thread Daniel Carrera
On 9 April 2016 at 00:09, Tom Breloff  wrote:
>
> The `plot!` command  is primarily `plot!(plt::AbstractPlot, args...;
> kw...)`.  In this case it holds to convention.
>
> I have a convenience `current()` which stores the most recently updated
> AbstractPlot object in a global, so that any plotting command without a
> leading AbstractPlot object gets it added implicitly.  (i.e. a call to
> `plot!(...)` is really a call to `plot!(current(), ...)`).
>
> I think this strategy is better than alternatives, and isn't too far from
> accepted conventions.
>


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.

Another pertinent example is the write function:


write(stream, foo)


Using your line of reasoning you'd say that "write()" is modifying "stream"
and therefore should have an exclamation mark. But this is clearly not how
the Julia convention works. The fact that "stream" points to something that
was modified is not enough to merit the exclamation mark.

I would argue that "plots(plt, ...)" is like "write(stream, ...)"


Cheers,
Daniel.


Re: [julia-users] Opinion on Plots.jl -- exclamation marks

2016-04-08 Thread Kristoffer Carlsson
I like the ! in Plots. 

Re: [julia-users] Opinion on Plots.jl -- exclamation marks

2016-04-08 Thread ben
I also like the ! in Plots a lot.

Ben!

Re: [julia-users] Opinion on Plots.jl -- exclamation marks

2016-04-08 Thread Tom Breloff

>
> 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)




Re: [julia-users] Opinion on Plots.jl -- exclamation marks

2016-04-08 Thread Daniel Carrera
Looks like I'm out-numbered.

On 9 April 2016 at 02:20, ben  wrote:

> I also like the ! in Plots a lot.
>
> Ben!


Re: [julia-users] Opinion on Plots.jl -- exclamation marks

2016-04-08 Thread Daniel Carrera
Ok. Thanks for the explanation.

Cheers,
Daniel.

On 9 April 2016 at 02:30, Tom Breloff  wrote:

> 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)
>
>
>


Re: [julia-users] Opinion on Plots.jl -- exclamation marks

2016-04-08 Thread Christof Stocker
I also prefer the ! so I know it modifies an existing plot. If I don't 
use a ! then I expect to create a new one


On 2016-04-09 02:52, Daniel Carrera wrote:

Ok. Thanks for the explanation.

Cheers,
Daniel.

On 9 April 2016 at 02:30, Tom Breloff > wrote:


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 =(...),...)
fordir indirectories
...dosome 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)







Re: [julia-users] Opinion on Plots.jl -- exclamation marks

2016-04-09 Thread Patrick Kofod Mogensen
+1 for !

On Saturday, April 9, 2016 at 8:09:23 AM UTC+2, Christof Stocker wrote:
>
> I also prefer the ! so I know it modifies an existing plot. If I don't use 
> a ! then I expect to create a new one
>
> On 2016-04-09 02:52, Daniel Carrera wrote:
>
> Ok. Thanks for the explanation. 
>
> Cheers,
> Daniel.
>
> On 9 April 2016 at 02:30, Tom Breloff > 
> wrote:
>
>> 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) 
>>
>>
>>
>
>