syntax query: ($var++ && next) if /match/

S

sln

So far I have decided that ($seen = 1 and next) if ... is the
best solution for me... let's see what else this thread shows up before
I commit myself!

Whats wrong with doing something like this:

next if /^paul/ and $seen = 1;

-sln
 
M

Mart van de Wege

Rainer Weikusat said:
The signal-to-noise ratio of this encoding of this particular operation
is worse than that of the equivalent statement-modifier or logical
operating using variants.

It's a bloody 'if' block, not COBOL, for crying out loud.

Mart
 
S

sln

Justin C wrote:
[...]

which prints no output. But if I change the `&&` to a comma it does as
expected.... ($seen = 1, next) if ...

I've just read perldoc perlop for Comma Operator, and for&&, but I
don't understand why one works and the other doesn't. Can anyone explain
this in simple terms?

If your intention is to perform two operations,
relying on the quirk that your first operation
evaluates to "true" is quite dirty.

I understand what you mean by 'relying on the quirk that [my] first
operation evaluates to true...' (I've been accused of that before, but
I'm open to education as to why I shouldn't be doing these things, and I
try to not repeat bad practice). But I'm not sure I am doing as you
suggest,
[...]

Performing asignment as part of a conditional expression,
even variable modification, is not really a safe bet if you
want the remainder of the expression to be evaluated.

Provided the assigment returns the required value it is perfectly
safe.
Furthermore, it lacks clarity and is hard to maintain,
even for the person who wrote it.

Could you perhaps explain why you think that 'it lacks clarity and is
hard to maintain' (instead of just asserting that it does)?
I think Perl tries to compensate its formal conditional
requirement of wrapping code in a block braces, spcifically
even 1 line, that for example C/C++ doesen't, with an offering
of code before conditional; ie: $seen=1 if (condition)

This is probably supposed to prevent the so-called 'dangling else
problem' in C or C++ where some people apparently manage to fool
themselves into believing that identation could change semantics,
namely, that

if (a)
if (b) ...;
else ...;

would mean if (a) { if (b) ...; } else ... instead of
if (a) { if (b) ...; else ...; }. But as opposed to C or C++, blocks
are not 'free' at runtime in perl, although at least the 5.10.1
compiler can meanwhile optimize a single-statement conditional block
away and statement modifiers use to be documented as having the
advantage of 'being able to avoid the overhead of entering a block.

Independently of this, they make the text easier to read[*] for short,
conditionally executed sequences.

[*] This assumes that 'reading' happens left to right from top
to bottom of a text, *not* by indentation-based 'recursive
descent parsing'.

Well, I guess Perl saved us C/C++ programmers from that
dangling else, now they offer the code block before the
conditional to compensate. Nice move.

I don't know that enterring a code block is overhead.
Traditionally, its more like skipping the block with a jump,
instead of passing through. But, who knows what Perl does.
If its that bad in condition blocks, sub calls must be a dog.

I think most compilers can optimize code blocks at compile time.
Traditionally, its a different issue if the block has runtime elements.

-sln
 
R

Rainer Weikusat

Whats wrong with doing something like this:

next if /^paul/ and $seen = 1;

It suggests that the $seen = 1 is actually part of the condition
which, in turn, will very likely make someone wonder whether or not it
was really supposed to be $seen == 1. While the '$seen = 1 and next if'
reads very 'naturally' (assuming the reader is familiar with English)
it is sort-of an abuse.
 
K

Keith Thompson

Justin C said:
Keith Thompson said:
Rainer Weikusat wrote:
[...]

) (($seen = 1) && next) if /^paul/;
[...]

($seen = 1 and next) if /^paul/;

Arguably a better idea. But the parenthesises can be dropped as well,
making this

$seen = 1 and next if /^paul/;

which I consider to be preferable.

Some might consider

if (/^paul/) {
$seen = 1;
next;
}

to be preferable.

Or

/^paul/ and $seen = 1, next;

You can put in on several lines if you're afraid your enter key might
feel lonely otherwise

/^paul/
and
$seen
=
1
,
next
;

C'mon guys, now you're getting silly. I was going for a balance between
brevity and legibility. Using a block does not have much brevity, but
has a lot of legibility - it was what my original code had (I was
younger and less experienced then). OTOH $seen = 1 and next if... is
brief to the detriment of legibility (or understandability), at least
for me. So far I have decided that ($seen = 1 and next) if ... is the
best solution for me... let's see what else this thread shows up before
I commit myself!

Personally, I consider legibility to be *much* more important than
brevity.

I dislike the "$seen = 1 and ..." solutions partly because the
"and" is used only for sequencing; it's depends on the left operand
being true. If you tried to use the same thing elsewhere, but with
"$seen = 0" instead, you'd have to restructure the code.

I consider

if (/^paul/) {
$seen = 1;
next;
}

to be *much* better than your suggested

($seen = 1 and next) if /^paul/;

If the condition (/^paul/) is true, you want to do two things: set $seen
to 1 and "next". That kind of thing is what if statements are for.

Of course TMTOWTDI, but some Ways To Do It are kinder to readers and
future maintainers than others.
 
S

sln

It suggests that the $seen = 1 is actually part of the condition
which, in turn, will very likely make someone wonder whether or not it
was really supposed to be $seen == 1. While the '$seen = 1 and next if'
reads very 'naturally' (assuming the reader is familiar with English)
it is sort-of an abuse.

Thats true, it does read better but doesen't emit a (asignment) warning.
That can probably be turned off though.
I still prefer a block in this case.

-sln
 
C

C.DeRykus

Thats true, it does read better but doesen't emit a (asignment) warning.
That can probably be turned off though.


Similiarly, I've used 'and' chains
to sneak in a side effect :

/^paul/ and $seen=1 and next;


but it's still ambiguous and harder to
see what's going on at a glance.
I still prefer a block in this case.

Ditto.

Or even: do {$seen=1; next } if /^paul/;
 
B

blmblm

Justin C said:
Rainer Weikusat wrote:

[...]

) (($seen = 1) && next) if /^paul/;

[...]

($seen = 1 and next) if /^paul/;

Arguably a better idea. But the parenthesises can be dropped as well,

(You do know that the plural is actually "parentheses", right?)
A text doesn't become easier to understand by adding more
non-alphanumeric characters to it.

Presumably you mean "program text" here (since if you could also mean
natural language text I would respectfully disagree and I suspect you
would too since as this sentence is meant to demonstrate punctuation
can be very helpful in making sense of long sentences and indeed in
separating sentences not to mention that without nonalphanumerics
you couldnt spell contractions right).

Just sayin'.

The case is perhaps less clear for program text, but I would argue
that judicious use of parentheses, even when not needed, is an
aid to understanding. Then again, I'm probably biased by the fact
that I'd rather put in some unnecessary parentheses from time to
time than try to keep in my head a table of operator precedences.
For example, I would rather just write

(a && b) || (c && d)

than try to remember which of the operators has higher precedence.
I'm aware that not everyone agrees with me. :)?

Why this, since it does exactly what its literal meaning appears to
be:

$seen = 1 and next if /^paul/

I would say that this line of code has an unambiguous literal
meaning only to someone who knows the relative precedence of all
the operators. And (as someone else pointed out) what if the
assignment was "$seen = 0"? even if the meaning would be clear
to someone who understands what "and" means in context, it seems
like a bit of work to remind oneself that here "and" is an
operator with short-circuit behavior rather than the ordinary
English word "and".
(set $seen to 1 and execute next if $_ matches /^paul/)

But isn't that sentence also potentially ambiguous? Isn't there
some ambiguity about whether the "if" applies to both "set $seen
to 1" and "execute next", or just to "execute next"?
 
D

Dr.Ruud

I've used 'and' chains
to sneak in a side effect :

/^paul/ and $seen=1 and next;

Who's still afraid of the comma operator?

$seen = 1, next if /^paul/;


(non-summary: I am just repeating what someone else already wrote, it
was already suggested before, if you go back in the thread you'll find
it, and if not then look again)

--
Ruud


Nice block clash:

perl -MO=Deparse -e'do { $seen = 1, next } if /^paul/;'

if (/^paul/) {
$seen = 1, next;
}
 
R

Rainer Weikusat

[...]
A text doesn't become easier to understand by adding more
non-alphanumeric characters to it.

Presumably you mean "program text" here (since if you could also mean
natural language text I would respectfully disagree and I suspect you
would too since as this sentence is meant to demonstrate punctuation
can be very helpful in making sense of long sentences and indeed in
separating sentences not to mention that without nonalphanumerics
you couldnt spell contractions right).
,,!`!I%%^^^actu;;;;!ly```````mea::mad::mad:n#~~tt\||||||ext$$

[...]

The case is perhaps less clear for program text, but I would argue
that judicious use of parentheses, even when not needed, is an
aid to understanding. Then again, I'm probably biased by the fact
that I'd rather put in some unnecessary parentheses from time to
time than try to keep in my head a table of operator precedences.
For example, I would rather just write

(a && b) || (c && d)

That's not a suitable example because the parentheses in the original
code were not used to clarify the precedence within a complex
expression but to separate a statement/expression [$seen = 1 and next]
from a statement modifier.

[...]
I would say that this line of code has an unambiguous literal
meaning only to someone who knows the relative precedence of all
the operators.

To someone who is aware of the concept of 'operators with different
precedence' but who doesn't really now what the precedence happens to
be *and* who isn't willing to look it up in the manual, no code
sequence has an unambigious meaning. But - imagine that - people
actually use language for everyday communication and manage to make
this work.

And (as someone else pointed out) what if the
assignment was "$seen = 0"?

The assignment isn't $seen = 0. Making uninformed changes to working
code (such as turning $seen = 1 and next into $seen = 0 and next) may
(and likely will) result in code which doesn't work anymore.

[...]
But isn't that sentence also potentially ambiguous?

'Potentially ambiguous' is a combination of terms which makes no
sense (everything is 'potentially ambiguous'). Generally, sentences
don't have an unambiguous meaning outside of the (con)text they were
meant to be part of and this is still the statement + statement
modifier situation.
 
R

Rainer Weikusat

Rainer Weikusat said:
[...]
And (as someone else pointed out) what if the
assignment was "$seen = 0"?

The assignment isn't $seen = 0.

Additional clarfication: My opinion on this is that using the and
logical operator as sequence binder in a context where this happens to
be possible because the first of the to-be-sequenced expressions
happens to evaluate to a true value is a rather unfortunate idea and
that the proper operator for this purpose should be used instead which
would be , in one of the two posted variants, namely

$seen = 1, next if /^paul/;

or

/^paul/ and $seen = 1, next;

But that's an entirely a matter of what I consider to be a sensible
coding style and does not imply that something is technically wrong
with the originally posted code (except the operator precedence
problem, of course).
 
C

C.DeRykus

Who's still afraid of the comma operator?

     $seen = 1, next if /^paul/;


The rarity of the comma operator makes it just
a bit harder to spot IMO. And, in this case,
I think a {} or do{} is "easier on the eyes and
arguably the brain" which trumps the brevity of
the comma operator.
 
R

Rainer Weikusat

Jürgen Exner said:
I disagree. This isn't one operation, it is two and they are quite
different. One assignment and one loop control jump.

Nobody ever claimed that they weren't.
And therefore it should look and feel like two operations, i.e. be
separated into two statements.

Perl has four operators which can be used to bind two different but
(in a certain context) related things together, '&& || and or
,'. Interpreted as general as it stand there, the sentence could as
easily apply to

if ($a == 1 && $b ne 'Huehnerdieb') { }

two different comparisons which are executed in sequence and thus,
should be two statements instead of this confusing conglomerate:

if ($a == 1) {
if ($b ne 'Huehnerdieb') { }
}

Consequently, this statement should be less general so that it is
applicable to assignment and loop-control operators but not to chained
comparisons.
You can easily see how confusing it is to munge them together: in just
this very thread there are already at least three different
interpretions of what the OP intended the code to do.

I'm not aware of any, but the OP stated quite plainly what he wanted
to do (as paraphrase: Why does it work with , but not with &&?) and
if at least three people existed who didn't understand a particular
text, presumably, because they jumped to conclusions about its
probable meaning before they finished reading it, is not an argument
for or against anything: Whatever is said, someone will not listen and
misunderstand it.
It is just not worth this confusion. Consice code that is easy to
understand is way more important than shorting the code to the max.
Unless you are playing Perl golf, of course.

Nobody argued in favor of 'shorting code to the max' (a remarkably
nonsensical phrase .... shouldn't that be 'shorten it to the min'?).
Also, I am not convinced about your efficieny argument.

First and foremost, this was a statement of facts: The if-block makes
perl perform more operations than the 'block-free' variants. A
contrived example which demonstrates this (both at the 'op tree' level
and in terms of actual execution time, at least here):

-----------
use Benchmark;

my $x;

sub s1
{
if (rand(100) < 50) {
++$x;
return $x;
}
}

sub s2
{
++$x, return $x if rand(100) < 50;
}

timethese(-5, {
a => \&s1,
b => \&s2
});
-----------
For one nobody asked for the code to be as efficient as possible.

That's a different question.
And even if so I would still find it hard to believe that an if
statement is slower, because in both cases the same operations are
performed. Or actually in case of the statement modifier there is
even an additional and.

Well, you are wrong about that and I actually posted output of the
'Perl disassembler' that showed the difference. You can also get it
from the code above by using it as argument to

perl -MO=Concise,-exec,s1
perl -MO=Concise,-exec,s2

(first shows the first sub, 2nd the 2nd).
Not to mention that such micro-optimizations are rarely the right
approach. If a program is too slow then almost always a different
algorithm or a different overall approach is the answer.

Provided that a program is too slow, 'removing avoidable blocks' might
not be the best strategy in order to deal with that (although this is
by no means certain since 'wasting 1.5% at every opportunity for that'
can easily have a significant cumulative effect). But this is - at
best - a tangential aspect when technical properties of different ways
to do the same thing are discussed.
If you are really depending upon such micro-optimizations then
probably you should have chosen a different programming language,
probably one that allows lower-level control like C or assembler.

I really expect that people who write code are as concerned with using
their tools efficiently as people performing different tasks with
other tools, IOW, that the 'dominant programming problem' shouldn't be
"how to I get this to work at all" but "how can I make this work
sensibly".

This is, of course, not exactly a realistic proposition ...
 
R

Rainer Weikusat

Jürgen Exner said:
I disagree. This isn't one operation, it is two and they are quite
different. One assignment and one loop control jump.

Nobody ever claimed that they weren't.
And therefore it should look and feel like two operations, i.e. be
separated into two statements.

Perl has four operators which can be used to bind two different but
(in a certain context) related things together, '&& || and or
,'. Interpreted as general as it stand there, the sentence could as
easily apply to

if ($a == 1 && $b ne 'Huehnerdieb') { }

two different comparisons which are executed in sequence and thus,
should be two statements instead of this confusing conglomerate:

if ($a == 1) {
if ($b ne 'Huehnerdieb') { }
}

Consequently, this statement should be less general so that it is
applicable to assignment and loop-control operators but not to chained
comparisons.
You can easily see how confusing it is to munge them together: in just
this very thread there are already at least three different
interpretions of what the OP intended the code to do.

I'm not aware of any, but the OP stated quite plainly what he wanted
to do (as paraphrase: Why does it work with , but not with &&?) and
if at least three people existed who didn't understand a particular
text, presumably, because they jumped to conclusions about its
probable meaning before they finished reading it, that's not an argument
for or against anything: Whatever is said, someone will not listen and
misunderstand it.
It is just not worth this confusion. Consice code that is easy to
understand is way more important than shorting the code to the max.
Unless you are playing Perl golf, of course.

Nobody argued in favor of 'shorting code to the max' (a remarkably
nonsensical phrase .... shouldn't that be 'shorten it to the min'?).
Also, I am not convinced about your efficieny argument.

First and foremost, this was a statement of facts: The if-block makes
perl perform more operations than the 'block-free' variants. A
contrived example which demonstrates this (both at the 'op tree' level
and in terms of actual execution time, at least here):

-----------
use Benchmark;

my $x;

sub s1
{
if (rand(100) < 50) {
++$x;
return $x;
}
}

sub s2
{
++$x, return $x if rand(100) < 50;
}

timethese(-5, {
a => \&s1,
b => \&s2
});
-----------
For one nobody asked for the code to be as efficient as possible.

That's a different question.
And even if so I would still find it hard to believe that an if
statement is slower, because in both cases the same operations are
performed. Or actually in case of the statement modifier there is
even an additional and.

Well, you are wrong about that and I actually posted output of the
'Perl disassembler' that showed the difference. You can also get it
from the code above by using it as argument to

perl -MO=Concise,-exec,s1
perl -MO=Concise,-exec,s2

(first shows the first sub, 2nd the 2nd).
Not to mention that such micro-optimizations are rarely the right
approach. If a program is too slow then almost always a different
algorithm or a different overall approach is the answer.

Provided that a program is too slow, 'removing avoidable blocks' might
not be the best strategy in order to deal with that (although this is
by no means certain since 'wasting 1.5% at every opportunity for that'
can easily have a significant cumulative effect). But this is - at
best - a tangential aspect when technical properties of different ways
to do the same thing are discussed.
If you are really depending upon such micro-optimizations then
probably you should have chosen a different programming language,
probably one that allows lower-level control like C or assembler.

I really expect that people who write code are as concerned with using
their tools efficiently as people performing different tasks with
other tools, IOW, that the 'dominant programming problem' shouldn't be
"how to I get this to work at all" but "how can I make this work
sensibly".

This is, of course, not exactly a realistic proposition ...
 
J

Jim Gibson

Rainer said:
[...]
Why this, since it does exactly what its literal meaning appears to
be:

$seen = 1 and next if /^paul/

I would say that this line of code has an unambiguous literal
meaning only to someone who knows the relative precedence of all
the operators.

To someone who is aware of the concept of 'operators with different
precedence' but who doesn't really now what the precedence happens to
be *and* who isn't willing to look it up in the manual, no code
sequence has an unambigious meaning. But - imagine that - people
actually use language for everyday communication and manage to make
this work.

There is no ambiguity to the block form:

if( /^paul/ ) {
$seen = 1;
next;
}

That is the point. The three constructs are separated by braces and
semi-colons, and the order of execution does not depend upon precedence
rules.
The assignment isn't $seen = 0. Making uninformed changes to working
code (such as turning $seen = 1 and next into $seen = 0 and next) may
(and likely will) result in code which doesn't work anymore.

But if the algorithm requires that $seen be set to zero, then the
construct will not work anymore, and the programmer will have to use a
different one. That is not the case for the block form.
[...]
But isn't that sentence also potentially ambiguous?

'Potentially ambiguous' is a combination of terms which makes no
sense (everything is 'potentially ambiguous'). Generally, sentences
don't have an unambiguous meaning outside of the (con)text they were
meant to be part of and this is still the statement + statement
modifier situation.

English and other natural languages can be ambiguous. Computer
languages should minimize ambiguity.

That is the point.
 
B

blmblm

[...]
A text doesn't become easier to understand by adding more
non-alphanumeric characters to it.

Presumably you mean "program text" here (since if you could also mean
natural language text I would respectfully disagree and I suspect you
would too since as this sentence is meant to demonstrate punctuation
can be very helpful in making sense of long sentences and indeed in
separating sentences not to mention that without nonalphanumerics
you couldnt spell contractions right).

,,!`!I%%^^^actu;;;;!ly```````mea::mad::mad:n#~~tt\||||||ext$$

Ah well, I didn't realize that when you said "adding more ....
characters" you meant "at random, with no particular concern for
whether the added characters are helpful". "Whatever", maybe.
[...]
The case is perhaps less clear for program text, but I would argue
that judicious use of parentheses, even when not needed, is an
aid to understanding. Then again, I'm probably biased by the fact
that I'd rather put in some unnecessary parentheses from time to
time than try to keep in my head a table of operator precedences.
For example, I would rather just write

(a && b) || (c && d)

That's not a suitable example because the parentheses in the original
code were not used to clarify the precedence within a complex
expression but to separate a statement/expression [$seen = 1 and next]
from a statement modifier.

Oh, I think it's quite a suitable example of what I meant.

Now, if *your* statement ("a text doesn't become easier ....")
wasn't actually intended to apply fairly broadly, then okay,
examples of parentheses used to clarify precedences aren't relevant.

But this is getting contentious, for no good purpose I can think of,
so onward .... :

With reference to the specific example, I would argue that someone
whose knowledge of Perl is limited may not realize that the clause
beginning "if" is a "statement modifier" (with the implication that
it applies to the whole statement rather than some smaller unit).
Parentheses would remove that source of possible confusion.
[...]
I would say that this line of code has an unambiguous literal
meaning only to someone who knows the relative precedence of all
the operators.

To someone who is aware of the concept of 'operators with different
precedence' but who doesn't really now what the precedence happens to
be *and* who isn't willing to look it up in the manual, no code
sequence has an unambigious meaning.

True. My preference is for a style that doesn't depend quite so much
on details I don't care to remember. Others' mileage obviously varies.
But - imagine that - people
actually use language for everyday communication and manage to make
this work.

What is "this" here? Are we talking about code or natural language?
It sounds like you mean the latter, and while yes we usually *do*
manage to make that work, I've certainly been in situations in which
text-only natural-language communication went badly wrong because
the sender and receiver interpreted a particular combination of
words differently.
The assignment isn't $seen = 0. Making uninformed changes to working
code (such as turning $seen = 1 and next into $seen = 0 and next) may
(and likely will) result in code which doesn't work anymore.

Exactly. But the difference is not just that a different value is
assigned (which yes might have unwanted consequences) but that ....
Well, I think you addressed this point in a later post, and it sounds
like you agree that using "and" here was not really a good idea.
[...]
But isn't that sentence also potentially ambiguous?

'Potentially ambiguous' is a combination of terms which makes no
sense (everything is 'potentially ambiguous').

Eh, I suppose.
Generally, sentences
don't have an unambiguous meaning outside of the (con)text they were
meant to be part of and this is still the statement + statement
modifier situation.

I understood your "(set ...." line to be intended as pseudocode
or perhaps some variant of natural language. Was that not what you
meant? In that context, how is a reader supposed to know that the
"if" is a "statement modifier" rather than something that modifies
some smaller unit?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,608
Members
45,250
Latest member
Charlesreero

Latest Threads

Top