SPUG: flip-flops

dancerboy dancerboy at strangelight.com
Wed Feb 6 15:40:29 CST 2002

First, I was not attempting anything even approaching a formal 
definition of good coding style, only an informal outline of what 
seem to me to be useful guidelines.  So to the more obvious 
objections to those guidelines, I can only give a sort of hand-wavy 
"well, of *course* I didn't mean them to apply in *that* situation!"

Still, I think it's useful (to me, at least) to examine in slightly 
more detail what I did and didn't mean by those guidelines:

At 12:00 pm -0800 2/6/02, Colin Meyer wrote:
>Hi Jason,
>On Wed, Feb 06, 2002 at 04:15:10AM -0800, dancerboy wrote:
>>  OTOH, my complaint may be that, if I understand the docs correctly
>>  (and again, I'm not sure that I do), it appears that the .. and ...
>>  operators implicitly maintain state information from previous uses of
>>  the operator.  I consider that to be a Bad Thing:  the result of an
>>  operator should be completely determined by its *current* operands,
>>  regardless of any previous uses of the operator. 
>Am I to understand that you'd avoid the /g modifier switch to the
>matching operators? /g certainly causes the matching operators (actually
>their operands) to maintain state.

/g doesn't maintain state in the sense I mean:  the result of 
m/$foo/g is completely determined by the current value of $foo (and 
whether it's in a list or scalar context), regardless of what matches 
may have occurred previously.  A better example would be the /c 
switch, which, yes, I do avoid.

It seems to me that part of the implicit contract for an operator (as 
opposed to an object method, and possibly a function, though that's 
more of a grey area) is, or should be, that if you know the value of 
the operands (and, in Perl, whether it's used in a list or scalar 
context) then you will know the return value of the operator, without 
having to know anything else about the surrounding logic.  [Insert 
necessary hand-waves and disclaimers about the -X "operators".]

I find it somewhat wrong that:

	for my $i ( 1 .. 4 ) {
		$foo = $bar->a() .. $bar->b();

has different semantics from:

	for my $i ( 1 .. 2 ) {
		$foo = $bar->a() .. $bar->b();
		$foo = $bar->a() .. $bar->b();

>   while ($s =~ s/(\w+)/g) {
>     print "Found some word characters: $1\n";
>   }
>>  Any sort of state information should be made explicit (such as storing
>>  it in a variable, e.g. $in_foo in your example above, or encapsulating
>>  it in an object).
>By this thought, the above snippet might be rendered:
>   my $still_looking=1; # here's the state information
>   my $s_copy = $s;   
>   while ($still_looking) {
>     if ($s_copy =~ s/.*?(\w+)//) {
>       print "Found some word characters: $1\n";
>     }
>     else {
>       $still_looking=0;
>     }
>   }

Again, the first example doesn't violate my proposed guidelines: the 
state is *explicitly* stored in $s.  It's not hidden in the way that 
the state of scalar .. is hidden.

>By taking advantage of operators that can maintain state, one can
>clear their code of extra distractions.

Perhaps, in some cases.  Just remember that brevity is not the same 
thing as clarity.

>btw, How do you consider encapsulating state information in an object
>different than encapsulating state information in an operator?
>   my $matcher = REGEX::withState->new(qr/(\w+)/);
>   while ($match = $matcher->get_next_match($s)) {
>     print "Found some word characters: $match\n";
>   }

For one thing, I could, in theory, peek at the state by creating an 
accessor method.  E.g.:

   my $matcher = REGEX::withState->new(qr/(\w+)/);
   while ($match = $matcher->get_next_match($s)) {
     print "Found some word characters: $match\n";
      "Still have "
      . $matcher->get_remaining_chars($s)
      . " characters to search.\n"

Whereas with an operator, I can't do anything like:

   $foo = $bar .. $baz;
    "The current flip-flop state is "
    .  ..->get_state()
    . "\n"

Even if ..->method() were legal, it wouldn't do what I want, because 
it's testing the wrong operator.  I'd need some way to refer to the 
operator in the previous line, but because it's an operator, there's 
no way to do that.

>  But operators can be objects too.

Well, IMO they shouldn't be.  An operator is an operator.  An object 
is an object.  By blurring the distinction between them, you're 
taking away important semantic cues that would otherwise help a human 
being understand the code.

The purpose of an object is to encapsulate state information.  When 
you see $foo->bar(), it's understood that the return value is 
dependant on the internal state of $foo. (And if it's not, you're 
probably misusing the object syntax.  Another peeve of mine is how 
many "OO" interfaces on CPAN don't actually encapsulate anything: 
they're just namespaces.  Yes, objects in Perl are *implemented* as 
namespaces -- i.e. packages -- but that doesn't mean that that's how 
they should be used.)

The purpose of an operator is to perform a function on a set of 
operands.  When I see $a <operator> $b , my natural assumption is 
that the result is a simple function of $a and $b.  If the operator 
itself has state information, then you're essentially introducing a 
*completely* hidden operand -- one that you cannot access in any way 
other than by actually evaluating the expression containing the 

>However, I will continue to use handy operators, like scalar .., the
>hook operator (trinary ?::), and m//g.

Hey, I never said anything against ?: or m//g -- I use them all the 
time as well  :)


 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     POST TO: spug-list at pm.org       PROBLEMS: owner-spug-list at pm.org
      Subscriptions; Email to majordomo at pm.org:  ACTION  LIST  EMAIL
  Replace ACTION by subscribe or unsubscribe, EMAIL by your Email-address
 For daily traffic, use spug-list for LIST ;  for weekly, spug-list-digest
     Seattle Perl Users Group (SPUG) Home Page: http://seattleperl.org

More information about the spug-list mailing list