ietf-mta-filters
[Top] [All Lists]

Re: variables extension redux

2004-07-31 12:36:30

On lør, 2004-07-31 at 19:21 +0200, Kjetil Torgrim Homme wrote:

     a related question is what happens when a match fails.  the draft
     currently says that the numeric variables are reset, but this may
     be inconvenient.

[this is irrelevant if we use SETMATCH]

I wasn't thinking clearly when I wrote that, sorry ...  the SETMATCH
doesn't remove the need for implicit state, it just limits the access to
that implicit state to places in the grammar which allow actions.

a contrived example:

  if allof (address :matches "To" "ietf-*(_at_)*",
            not address :matches "To" "ietf-mta-filters(_at_)*") { ...

consider a To containing "ietf-mta-wars".  the first test is a success,
the second is not.  the implicit state is thus cleared, and we can't get
at the domain even if the allof test is successful.  neither can we get
at the "mta-wars" part.  in this case, reversing the ordering of the
tests solves the problem, so it's not hard to work around it.

on the other hand: in Perl, an unsuccessful match does not change the
implicit state.  I'm not aware of any other languages with implicit
state in this manner.  in the origin of this, sed, the scope of \1 is
restricted to the substitute operation it's used in.

one useful recipe if state is _not_ reset, is testing for fallback:

  if match-test1 { do-stuff1 }
  if match-test2 { do-stuff2 }
  if string "${0}" "0" {
     # this is true if neither match-test1 nor match-test2 were true.
     # sometimes match-test1 and match-test2 aren't mutually exclusive,
     # so if ... {} else if ... {} else ... {} isn't appropriate.
  }

of course, the programmer can use an explicit flag variable in each of
do-stuff1 and do-stuff2 instead, but I believe this will make the idiom
harder to recognise for a GUI editor.


getting back to SETMATCH, it makes accessing ${0} inconvenient to say
the least, so the above hack can't be used.  (the first match may well
be a zero-length string.)

it also requires the following example to be rewritten into nested if
tests:

  if allof (header :matches "List-ID" "*<*(_at_)example(_dot_)com>*",
            address :localpart "To" "${2}") {
      ...
  }

it becomes:

  if header :matches "List-ID" "*<*(_at_)example(_dot_)com>*" {
        setmatch ["", "listname"]
        if address :localpart "To" "${listname} {
             ...
        }
  }

I don't see this as a bad thing, really.

-- 
Kjetil T.