Luke Palmer wrote:

Rod Adams writes:



Or you could avoid the global modifier and write your tests in <( )>
blocks instead... after all, that's what it's there for.


I *knew* I had seen a syntax for that before... I just didn't see it when I scanned S05 for it.

I still want the :z modifier for matching zero length strings. That makes sense to be global.

The really big problem, however, is the lack of generators.

I'll establish a working definition of "generator" as "something which
offers a possible value, giving the new value each time the expression
is backtracked over, and fails when there are no more values to give".



One generator is the * combinator. It gives the longest string, then
the next shorter, then the next shorter...


I agree that * works that way... when you're matching against a string... which I'm not. I intend for the basic call to be something like C< "" ~~ /<test(1)>/ >, or more likely just C< /<test(1)>/ >. I won't care what the current topic is. I'll match the empty string, and everything that includes it, or nothing at all. My entire rule set will be a series of really complex zero-length assertions.


Clearly, desirable generators include lazy lists, arrays, and
closures. All of which P6RE supports as ways of attempting different
rules/strings to match against, but not as different values to assign
a given $<var> to feed into later rules. Capturing assumes a string to
match and capture against. Capturing the null string that I "match" is
not terribly useful.

The only suggestion I can give for how to do this is by introducing the
hyper operator. I'm very open to other ideas, because this one does not
sit well with me, but it's all I've got at the moment. So, to give an
array as a generator, one could write:

/:a {$<x> Â=Â @values} <test($<x>)>/



You could do all of this with a library of rules.

/ $<x>:=<generate(@values)> <test($<x>)> /


I don't think this does what I want. In this, &generate returns a rule or string of some kind, matches the string being tested, captures what matches, and then binds the capture to $<x>.

I have no underlying string, so the match fails right there. I want to bind/assign to the variable _without_ matching, but _with_ backtracking and iteration over several values.

I also now notice that I would need a C< let > in my example above.

How the <generate> rule is actually written is getting into some rule
engine internal stuff, but we're making sure that the rule engine has
enough hooks to do that.


There were some thoughts in the back of my head about how I actually wanted a closure to be handled as a generator. I see the need to initialize it many separate times, once on each forward attempt, can be repeated if something after it fails, and something before it has an alternative. But I wanted the basic concept out there before I tried diving into that kind of detail.

Maybe we could unify the pattern proposal and your generation ideas for logic programming.


There might be unification with logical programming to be had, but I'm not sure it's with the generation part of things.


@array[$^i] # returns a lazy pattern of everything in @array, bound
# together with the corresponding $i


How is this any different from just @array ?

   (@array[$^i]).GENERATE   # generates every element of @array

Now, let's just combine that with another array pattern:

   @a[$^i] + @b[$^i]  # returns lazy pattern of everything in @a
                      # added to its corresponding element in @b
   (@a[$^i] + @b[$^i]).GENERATE  # vector sum

Now if we just spell .GENERATE with ÂÂ:

   Â @a[$^i] + @b[$^i] Â

We have my tensor-hyper proposal back.


This example is easily done as:

   @a Â+Â @b

But it's also not terribly far removed from my hyperthreader operator in the Junctions thread (oh, when, oh when is Damian coming back?). There are differences, but see if that does what you need.

Not to mention that   are already taken in that context as q:w// operators.

Now ÂÂ could have a similar meaning within rules, which would give you
your generator.

# print everything in @array that matches test()
/ $<x> := [EMAIL PROTECTED] <( test($<x>) )> { say $<x>; fail } /


Problems with this:
1) Â Â in RE's are already taken for non-capturing meta's. And binding doesn't work if you don't capture.
2) you're still trying to match the value against the string.


Not really a problem, but I had C< <test($<x>)> >, not C< <(test($<x>))> > on purpose. I was feeding into a rule, not a function.

The biggest question is how this interacts with sub calls.  We can't
really expect sub calls to be pattern-aware: that puts constraints on
what we're allowed to do in a sub (no side-effect constraints; gee,
those kinds of constraints really go a long way).  But &test could
certainly implement a GENERATE method:

   sub is_prime(
       $x will GENERATE { primes() }
   )
   {
       ?grep { $_ == $x } primes()
   }

The will generate says that the sub can accept a generic pattern and
will fill it in on the spot.


I don't see what this gives me over a regular lazy list generation with gather/take.

-- Rod Adams



Reply via email to