|
From: Arun P. <ape...@lb...> - 2012-04-30 22:21:53
|
Hi
I just ran across the following problem:
do for [i=5:1] {
print i
}
prints "5" instead of doing nothing. Is this the intended behavior?
This seems due to the use of a "do {} while" structure in
src/command.c:do_command, instead of perhaps a while or for.
Other places in gnuplot where "for" is used, don't seem to do this:
plot for [i=5:1] sin(i*x)
=> nothing is plotted.
system: linux (openSUSE Tumbleweed)
gnuplot version: from 2012-04-30 (ff262a693106d from
https://github.com/gnuplot/gnuplot.git)
just FYI:
I came across this using the following
do for [i=1:N] {
do for [j=(i+1):N] { # (i+1 will be N+1 during the last i-iteration)
print "doing ".i." ".j
}
}
ARUN
|
|
From: Ethan A M. <sf...@us...> - 2012-05-02 21:16:12
|
On Monday, April 30, 2012 03:21:36 pm Arun Persaud wrote:
> Hi
>
> I just ran across the following problem:
>
> do for [i=5:1] {
> print i
> }
>
> prints "5" instead of doing nothing. Is this the intended behavior?
>
> This seems due to the use of a "do {} while" structure in
> src/command.c:do_command, instead of perhaps a while or for.
>
> Other places in gnuplot where "for" is used, don't seem to do this:
>
> plot for [i=5:1] sin(i*x)
set for [i=5:1] label i "Foo"
show label
label 5 "Foo" at (0, 0, 0) left not rotated back nopoint
So yes, there is an inconsistency. There are currently three "for"
constructs
do for
set for
plot for
The first two of these always iterate at least once; the third one does not.
The documentation is silent on the intended behavior.
So which to change, "plot for" or both the others?
|
|
From: Tait <gnu...@t4...> - 2012-05-03 06:56:57
|
> So yes, there is an inconsistency. There are currently three "for" > constructs > do for > set for > plot for > > The first two of these always iterate at least once; the third one does not. > The documentation is silent on the intended behavior. > So which to change, "plot for" or both the others? Given that it's called "for" I'd say the principle of least surprise dictate that it act consistently with "for" as used in most programming languages (e.g. C). |
|
From: <pl...@pi...> - 2012-05-03 22:22:42
|
On 05/03/12 08:37, Tait wrote: >> So yes, there is an inconsistency. There are currently three "for" >> constructs >> do for >> set for >> plot for >> >> The first two of these always iterate at least once; the third one does not. >> The documentation is silent on the intended behavior. >> So which to change, "plot for" or both the others? > > Given that it's called "for" I'd say the principle of least surprise > dictate that it act consistently with "for" as used in most programming > languages (e.g. C). > The illogical and inconsistent result of always executing once means that any situation where this is programmed to use variable values necessitates an additional test as the first thing within the 'for' structure, for it to be able to produce predictable output. Since these syntactical tweaks to gnuplot commands do not allow complex, structured content, it would seem best to provide a behaviour which produces consistent behaviour irrespective of variable values, avoiding the need for further tests. ie for (i=2 ; i<=1) does nothing. Clearly it needs to be the same and thoroghly documented in all contexts. Peter. |
|
From: Arun P. <ape...@lb...> - 2012-05-03 20:00:01
|
Hi
> R> for (i in 4:1) { print(i) }
> [1] 4
> [1] 3
> [1] 2
> [1] 1
>
> So that's a third option to consider.
> It's not too late to consider adopting this behavior for gnuplot also:
> for [i = start : end {: increment}]
> where increment defaults to -1 if (start > end) and +1 otherwise.
>
> Ethan
My preferred choice would be that you need to specify the -1 increment
explicitly.
If you leave it with an increment of +1 unless otherwise specified, I
also would prefer if "do for [i=5:4] {" does no iterations at all.
My application was that I had a data file with 33 columns and I wanted
to plot column i:j for the first 10 columns using
do for [i=:10] {
do for[j=(i+1):10] {
...
}
}
which plots something like an upper triangle matrix of plots, but with
an extra plot for 11:10, which I didn't expect. Can't really think of
other good examples where this would be relevant at the moment though.
An automatic switch to an increment of -1 would also be OK for me,
although I wouldn't expect it ;)
Arun
|
|
From: <pl...@pi...> - 2012-05-03 20:43:56
|
On 05/03/12 21:59, Arun Persaud wrote: > An automatic switch to an increment of -1 would also be OK for me, > although I wouldn't expect it;) > > Arun I would advise against such "special" cases. It's confusing (unexpected) and as I said before makes producing predictable output complicated. Arun's example case of the extra plot would be difficult to deal with in a general way and would probably require some testing of the values and conditional code before the "for" to stop things like that happening. The automatic switch to negative increment would probably do something unhelpful like printing both "triangles" of his matrix of plots. Or something even more unexpected. Peter. |
|
From: Ethan A M. <sf...@us...> - 2012-05-03 21:07:50
|
Tait <gnu...@t4...> wrote >
> > So yes, there is an inconsistency. There are currently three "for"
> > constructs
> > do for
> > set for
> > plot for
> >
> > The first two of these always iterate at least once; the third one does not.
> > The documentation is silent on the intended behavior.
> > So which to change, "plot for" or both the others?
>
> Given that it's called "for" I'd say the principle of least surprise
> dictate that it act consistently with "for" as used in most programming
> languages (e.g. C).
Well, C doesn't really have an automatic iterator of this form; you have to
provide an explicit initialization, an explicit while condition, and an
explicit iteration operation.
It turns out to be surprisingly hard to determine what
"most programming languages" do. Many require an explicit increment
operation, like C.
FWIW, here is what you get in R, whose syntax is close to that of gnuplot.
R> for (i in 4:1) { print(i) }
[1] 4
[1] 3
[1] 2
[1] 1
So that's a third option to consider.
It's not too late to consider adopting this behavior for gnuplot also:
for [i = start : end {: increment}]
where increment defaults to -1 if (start > end) and +1 otherwise.
Ethan
|
|
From: Petr M. <mi...@ph...> - 2012-05-04 15:31:17
|
I would strongly prefer no output for
do for [i=3:1] { print i; }
I consider one-line output as a bug.
Note -- also Octave/Matlab produce no output:
> for i=1:3 ; i, end
i = 1
i = 2
i = 3
> for i=3:1 ; i, end
>
---
Petr
|
|
From: Tait <gnu...@t4...> - 2012-05-03 22:26:42
|
> > > So yes, there is an inconsistency. There are currently three "for"
> > > constructs
> > > do for
> > > set for
> > > plot for
> > >
> > > The first two of these always iterate at least once; the third one does not.
> > > The documentation is silent on the intended behavior.
> > > So which to change, "plot for" or both the others?
> >
> > Given that it's called "for" I'd say the principle of least surprise
> > dictate that it act consistently with "for" as used in most programming
> > languages (e.g. C).
Ethan:
>
> It turns out to be surprisingly hard to determine what
> "most programming languages" do. Many require an explicit increment
> operation, like C.
>
> FWIW, here is what you get in R, whose syntax is close to that of gnuplot.
>
> R> for (i in 4:1) { print(i) }
> [1] 4
> [1] 3
> [1] 2
> [1] 1
>
> So that's a third option to consider.
Arun:
> My preferred choice would be that you need to specify the -1 increment
> explicitly.
>
> If you leave it with an increment of +1 unless otherwise specified, I
> also would prefer if "do for [i=5:4] {" does no iterations at all.
Peter:
> I would advise against such "special" cases. It's confusing (unexpected)
> and as I said before makes producing predictable output complicated.
I was thinking in terms of for [a:b] implicitly meaning for [a:b:+1], in
which case there should be zero loops executed if a > b. For example...
Perl:
perl -e "print for 0..9" => 0123456789
perl -e "print for 9..0" =>
Python:
python -c "print range(0,9) => [0, 1, 2, 3, 4, 5, 6, 7, 8]
python -c "print range(9,0) => []
Ruby:
ruby -le 'print (0..9).to_a' => 0123456789
ruby -le 'print (9..0).to_a' =>
But also R, as you mentioned, and...
PHP:
php -r 'print implode(range(0,9))' => 0123456789
php -r 'print implode(range(9,0))' => 9876543210
(...not that PHP should be a model for anything, in my personal opinion)
I do like and have often wished for R's behavior where [a:b] implies a
+1 increment if b>a and a -1 increment if a>b. I think gnuplot could
adopt this. But to address Arun and Peter's concern, for [i=9:0:1]
should do zero loops, to allow a mechansim for the author to say, "I
want Perl/Python/Ruby-like behavior, not R-like behavior." Having
for [i=9:0:1] do one loop can only be seen as broken.
|
|
From: <pl...@pi...> - 2012-05-04 04:12:37
|
On 04/05/12 00:26, Tait wrote: > Python: > python -c "print range(0,9) => [0, 1, 2, 3, 4, 5, 6, 7, 8] > python -c "print range(9,0) => [] LOL, a range of 0,9 starts at 0 and stops at 8 , brilliant ! Gnuplot should definitely follow that model of logic. Peter. |
|
From: <pl...@pi...> - 2012-05-04 04:40:20
|
On 04/05/12 00:26, Tait wrote:
>
>>>> So yes, there is an inconsistency. There are currently three "for"
>>>> constructs
>>>> do for
>>>> set for
>>>> plot for
>>>>
>>>> The first two of these always iterate at least once; the third one does not.
>>>> The documentation is silent on the intended behavior.
>>>> So which to change, "plot for" or both the others?
>>>
>>> Given that it's called "for" I'd say the principle of least surprise
>>> dictate that it act consistently with "for" as used in most programming
>>> languages (e.g. C).
>
> Ethan:
>>
>> It turns out to be surprisingly hard to determine what
>> "most programming languages" do. Many require an explicit increment
>> operation, like C.
>>
>> FWIW, here is what you get in R, whose syntax is close to that of gnuplot.
>>
>> R> for (i in 4:1) { print(i) }
>> [1] 4
>> [1] 3
>> [1] 2
>> [1] 1
>>
>> So that's a third option to consider.
>
> Arun:
>> My preferred choice would be that you need to specify the -1 increment
>> explicitly.
>>
>> If you leave it with an increment of +1 unless otherwise specified, I
>> also would prefer if "do for [i=5:4] {" does no iterations at all.
>
> Peter:
>> I would advise against such "special" cases. It's confusing (unexpected)
>> and as I said before makes producing predictable output complicated.
>
> I was thinking in terms of for [a:b] implicitly meaning for [a:b:+1], in
> which case there should be zero loops executed if a> b. For example...
> Perl:
> perl -e "print for 0..9" => 0123456789
> perl -e "print for 9..0" =>
> Python:
> python -c "print range(0,9) => [0, 1, 2, 3, 4, 5, 6, 7, 8]
> python -c "print range(9,0) => []
> Ruby:
> ruby -le 'print (0..9).to_a' => 0123456789
> ruby -le 'print (9..0).to_a' =>
>
> But also R, as you mentioned, and...
> PHP:
> php -r 'print implode(range(0,9))' => 0123456789
> php -r 'print implode(range(9,0))' => 9876543210
> (...not that PHP should be a model for anything, in my personal opinion)
>
> I do like and have often wished for R's behavior where [a:b] implies a
> +1 increment if b>a and a -1 increment if a>b. I think gnuplot could
> adopt this. But to address Arun and Peter's concern, for [i=9:0:1]
> should do zero loops, to allow a mechansim for the author to say, "I
> want Perl/Python/Ruby-like behavior, not R-like behavior." Having
> for [i=9:0:1] do one loop can only be seen as broken.
>
>
I think the C behaviour is the most predictable and clearly defined:
for [ initialisation ; end_condition ; loop_operation ]
it is executed in that order, ie end_condition is tested immediately
after initialisation
note loop_operation can be any expression : i=exp(i*i/sigma)
If there is to be the option of omitting loop_operation , I think it
has to be the unique increment i++ , not an operation that depends upon
the values of the data.
for [ range ] ; is a different thing entirely.
If that is required , I think it should be made quite distinct. probably
with a new data type for ranges. Trying to shoehorn this in as a special
case will lead to ambiguities and language problems later as gnuplot
syntax develops into a more structured language.
Peter.
|
|
From: <pl...@pi...> - 2012-05-04 04:02:38
|
On 03/05/12 20:24, Ethan A Merritt wrote:
> Tait<gnu...@t4...> wrote>
>>> So yes, there is an inconsistency. There are currently three "for"
>>> constructs
>>> do for
>>> set for
>>> plot for
>>>
>>> The first two of these always iterate at least once; the third one does not.
>>> The documentation is silent on the intended behavior.
>>> So which to change, "plot for" or both the others?
>>
>> Given that it's called "for" I'd say the principle of least surprise
>> dictate that it act consistently with "for" as used in most programming
>> languages (e.g. C).
>
> Well, C doesn't really have an automatic iterator of this form; you have to
> provide an explicit initialization, an explicit while condition, and an
> explicit iteration operation.
>
> It turns out to be surprisingly hard to determine what
> "most programming languages" do. Many require an explicit increment
> operation, like C.
>
> FWIW, here is what you get in R, whose syntax is close to that of gnuplot.
>
> R> for (i in 4:1) { print(i) }
> [1] 4
> [1] 3
> [1] 2
> [1] 1
>
> So that's a third option to consider.
> It's not too late to consider adopting this behavior for gnuplot also:
> for [i = start : end {: increment}]
> where increment defaults to -1 if (start> end) and +1 otherwise.
>
> Ethan
>
Hi,
The R example is rather artificial. It is not the 'for' structure that
automatically takes a negative increment. That is the result of the
definition of the "range" 4:1 , which rightly defines a series 4 3 2 1
, that is unique and unambiguous.
In this context the for-loop simply iterates a predetermined list , the
loop increment is still +1 .
The idea that way the code is compiled varies dependant on the values of
the data seems an aberration to me. This sort of thing should be
reserved for AI languages.
Perhaps someone could suggest how this would be advantageous.
If it is truly useful perhaps the idea of a range as a variable
structure needs to implemented as in R. Though this would probably lead
to an ambiguous syntax in for-loops which would have to have alternative
code paths for conventional integer args and ranges.
Peter.
|
|
From: sfeam (E. Merritt) <eam...@gm...> - 2012-05-04 05:46:56
|
On Thursday, 03 May 2012, pl...@pi... wrote:
> On 03/05/12 20:24, Ethan A Merritt wrote:
> > Tait<gnu...@t4...> wrote>
> >>> So yes, there is an inconsistency. There are currently three "for"
> >>> constructs
> >>> do for
> >>> set for
> >>> plot for
> >>>
> >>> The first two of these always iterate at least once; the third one does not.
> >>> The documentation is silent on the intended behavior.
> >>> So which to change, "plot for" or both the others?
> >>
> >> Given that it's called "for" I'd say the principle of least surprise
> >> dictate that it act consistently with "for" as used in most programming
> >> languages (e.g. C).
> >
> > Well, C doesn't really have an automatic iterator of this form; you have to
> > provide an explicit initialization, an explicit while condition, and an
> > explicit iteration operation.
> >
> > FWIW, here is what you get in R, whose syntax is close to that of gnuplot.
> >
> > R> for (i in 4:1) { print(i) }
> > [1] 4
> > [1] 3
> > [1] 2
> > [1] 1
>
> The R example is rather artificial. It is not the 'for' structure that
> automatically takes a negative increment. That is the result of the
> definition of the "range" 4:1 , which rightly defines a series 4 3 2 1
> , that is unique and unambiguous.
>
The "for" construct in gnuplot can be viewed this way also.
It has two forms:
do for [i = N:M]
do for [i in "FOO BAZ ARGL"]
You can view N:M in the first form as representing the set of integers
bounded by N and M, just as "FOO BAZ ARGL" in the second form represents
the set of strings "FOO" "BAZ" and "ARGL".
The fact that we iterate over the set in the specific order
N N+1 N+2 ... M is an implementation detail.
Mind you, I'm not arguing strongly that R has it right and other
languages have it wrong[*]. I'm just questioning the notion that
there's a single "obvious" or "least surprising" way to interpret
this statement.
Just for the heck of it, I'll point out that this same argument
waxed hot back in the lead-up to Fortran77. Earlier versions
of Fortran would always execute a loop at least once regardless
of the bounds in the DO statement. This was, after much argument,
changed in Fortran77 so that the DO statement had a
"minimum trip count" of zero. Unfortunately this meant that the
very same statement would produce different results if compiled
using successive versions of Fortran. Fun, eh?
I don't want to use FortranIV as a model, so I agree we
should change the code so that an explicit out-of-range iteration
like [i = 5:-5:1] executes zero times. But I think the discussion
is worthwhile as to whether [i = 0:5] and [i = 5:0] should both
iterate over the same set of six integers, although not necessarily
in the same order.
As to "least surprise", consider that gnuplot users are already
familiar with the idea that 'set xrange [0:5]' and 'set xrange [5:0]'
both span the same range, but in a different order. It should not
be a big surprise if [i = 0:5] and [i = 5:0] also span the same
range but in a different order.
Ethan
[*] Though I think we agree that python really does have it wrong.
>
>
> The idea that way the code is compiled varies dependant on the values of
> the data seems an aberration to me. This sort of thing should be
> reserved for AI languages.
>
> Perhaps someone could suggest how this would be advantageous.
>
> If it is truly useful perhaps the idea of a range as a variable
> structure needs to implemented as in R. Though this would probably lead
> to an ambiguous syntax in for-loops which would have to have alternative
> code paths for conventional integer args and ranges.
>
>
> Peter.
|