Re: Patterns

2007-01-07 Thread Jonathan Lang

Larry Wall wrote:

Lots of interesting ideas.  But I don't think the reverse-test
situation will arise all that frequently.  How 'bout we let the user
just say:

my macro statement_control:test { when .accepts:  }

or some such...


IIRC, you don't even need .accepts for this.  You could just say

 given $pattern {
   when $a ~~ $_ { ... }
   when $b ~~ $_ { ... }
   when $c ~~ $_ { ... }
 }

...since an explicit smart-match is a boolean expression (it is, isn't
it?), and boolean expressions implicitly smart-match according to
their truth.  Right?

--
Jonathan Dataweaver Lang


Re: Patterns

2007-01-07 Thread Larry Wall
On Sun, Jan 07, 2007 at 03:33:19AM -0800, Jonathan Lang wrote:
: IIRC, you don't even need .accepts for this.  You could just say
: 
:  given $pattern {
:when $a ~~ $_ { ... }
:when $b ~~ $_ { ... }
:when $c ~~ $_ { ... }
:  }
: 
: ...since an explicit smart-match is a boolean expression (it is, isn't
: it?), and boolean expressions implicitly smart-match according to
: their truth.  Right?

Very nearly, except that ~~ merely promises to return something
that can be used as a boolean, not something that is of Bool type.
And, in fact, for a normal regex you'd get a Match object, which as
a form of Capture would then try to compare itself back to $pattern,
which is not what you want.  So you'd have to force it:

given $pattern {
  when true $a ~~ $_ { ... }
  when true $b ~~ $_ { ... }
  when true $c ~~ $_ { ... }
}

Larry


Re: Patterns

2007-01-06 Thread Jonathan Lang

Larry Wall wrote:

Anyway, that gives us:

given $pattern {
when .accepts(42) {...}
}

which given typical usage patterns of switch statements is probably
adequately huffmanized, unless we want to go for something shorter
than accepts/rejects, like

acc/rej
pix/nix
ok/bogus


...at which point, legibility becomes an issue.  .accepts() and
.rejects() seem to work well enough on a case-by-case basis - although
it occurs to me that someone who intends to put the pattern first
within a given/when construct is probably going to want to do so for
every case, or very nearly so:

 given $pattern {
   when .accepts($a) { ... }
   when .accepts($b) { ... }
   when .accepts($c) { ... }
   when .accepts($d) { ... }
 }

It would be nice if there were some way to factor out the .accepts()
in the above code.  Maybe something like:

 given $pattern {
   when $a { ... } # if $a ~~ $pattern { ... ; next }
   when $b { ... } # if $b ~~ $pattern { ... ; next }
   when $c { ... } # if $c ~~ $pattern { ... ; next }
   when $d { ... } # if $d ~~ $pattern { ... ; next }
 } is backward;

Although I don't like the fact that you have to wait until reading the
whole block to find out that the cases are being processed inside-out.

--

Would it be possible to put a closure on the left and an argument list
on the right, with the effect being that the closure gets called using
the argument list?  This would let you do something like:

 given { ^x ~~ $pattern } {
   when $a { ... } # if $a ~~ $pattern { ... ; next }
   when $b { ... } # if $b ~~ $pattern { ... ; next }
   when $c { ... } # if $c ~~ $pattern { ... ; next }
   when $d { ... } # if $d ~~ $pattern { ... ; next }
 }

or

 given { ^x = $number  ^y } {
   when 1, 2 { ... } $ if 1 = $number  2 { ... ; next }
   when 2, 3 { ... } $ if 2 = $number  3 { ... ; next }
 }

(Yes, I know that this second case could be handled more flexibly
using right-side Ranges.  TIMTOWTDI.)

The main problem that I have with this idea is its rigidity.  The
_only_ way that the topic can be used in the above is as a test for
the 'when' clauses; and it messes with the 'when *' idiom.  (But then,
any code that follows the final 'when' in a block is already the 'if
all else fails...' code; 'when *' is merely syntactic sugar to
highlight this fact.)

--

It would be nice to have something that is to 'given' as 'loop' is to
'for', letting you specify a topic and a separate case tester up
front:

 test $pattern, { $^x ~~ $_ } {
   when $a { ... } # if $a ~~ $pattern { ... ; next }
   when $b { ... } # if $b ~~ $pattern { ... ; next }
   when $c { ... } # if $c ~~ $pattern { ... ; next }
   when $d { ... } # if $d ~~ $pattern { ... ; next }
 }

Or, to avoid additional keywords, just say that a 'given' statement
with two arguments uses the first argument as its topic and the second
argument as the case tester to replace '{ $_ ~~ $^x }' in 'when'
clauses.  Better, use 'when' as is, but introduce a 'test' alternative
that is customized by the second parameter:

 given $pattern, { $^x ~~ $_ } {
   test $a { ... } # if $a ~~ $pattern { ... ; next }
   test $b { ... } # if $b ~~ $pattern { ... ; next }
   test $c { ... } # if $c ~~ $pattern { ... ; next }
   test $d { ... } # if $d ~~ $pattern { ... ; next }
   when * { ... } # if $pattern ~~ * { ... ; next }
 }

That way, 'given' and 'when' still behave exactly as currently
described; the case tester only comes into play when you explicitly
ask for it.

--

At this point, though, the case tester is looking like it might be
better as a property of the 'given' block:

 given $pattern {
   TEST { $^x ~~ $_ }
   test $a { ... } # if $a ~~ $pattern { ... ; next }
   test $b { ... } # if $b ~~ $pattern { ... ; next }
   test $c { ... } # if $c ~~ $pattern { ... ; next }
   test $d { ... } # if $d ~~ $pattern { ... ; next }
   when * { ... } # if $pattern ~~ * { ... ; next }
 }

Or go ahead and let TEST change the behavior of 'when' within the
block, and rely on nested blocks to allow different kinds of tests
within a 'given' block:

 given $pattern
 {
   {
 TEST - $x { $x ~~ $_ }
 when $a { ... } # if $a ~~ $pattern { ... ; next }
 when $b { ... } # if $b ~~ $pattern { ... ; next }
 when $c { ... } # if $c ~~ $pattern { ... ; next }
 when $d { ... } # if $d ~~ $pattern { ... ; next }
   }
   when * { ... } # if $pattern ~~ * { ... ; next }
 }

...and someone silly enough to want to frequently change the case
tester within a given block is advised to use 'if' instead.

What do you think?

--
Jonathan Dataweaver Lang


Re: Patterns

2007-01-06 Thread Ashley Winters

On 1/5/07, Larry Wall [EMAIL PROTECTED] wrote:

Anyway, that gives us:

given $pattern {
when .accepts(42) {...}
}


I think this type of usage should be encouraged with a bit more
huffmanization. My first thought would be to add Cagainst to invert
the arguments to ~~ versus Cwith.

given @something {
   when $this { ... }# @something ~~ $this
   against $that { ... }# $that ~~ @something
}

That would help keep the ~~ DWIM table from trying to guess on which
side you really wanted @something on.

- Ashley Winters


Patterns

2007-01-05 Thread Luke Palmer

I propose that we remove the following two lines from the smart match
table in S03:

   HashAny   hash entry existence exists $_{$x}
   Array   Any   array contains item* any($_) === $x

These are the two lines with Any on the right side.  I want to remove
these so that we can have an extensible ~~ operator.

You can think of $x ~~ $y as saying $x matches $y, i.e. $y is some
data pattern and we are asking if $x conforms to it.  I want to be
able to add my own kinds of patterns, and entries with Any in the
right side undermine this.

Why?  Let's say I created a pattern  which implemented another textual
matcher alongside Perl's regexes, which was more convenient for some
things (I shouldn't have to convince you that this is possible and
useful).  Let's call it Irregex.  I want it to work just like Perl's
regexes; i.e. I want it so that if you ask whether an array matches
it, it will match against the elements of the array as though they
were characters.  So I just overload ~~ to work on (Array, Irregex)
and that overrules (Array, Any) so there is no MMD ambiguity.

However!  Let's say I'm using a payroll library (or something, sorry
for the mundane examples; I'm trying to keep it realistic) which sends
a notification if any user's status matches a pattern, and it is
implemented like so:

   method notify(Any|Junction $pattern) {
   if @.users.status ~~ $pattern {
   # send notification
   }
   }

This is perfectly fine, elegant code given the ~~ table.  But it
breaks since we have added our new pattern type!  It doesn't check if
any user's status matches, it checks if the users' statuses'
concatenated considered as atoms matches, totally wrong!

So, I'm essentially asking for ~~ to be singly-dispatched based on its
right argument, which gets to pick how to interpret the left one.  In
order to encourage this usage, I propose a design like so:

   role Pattern {
   method match($item) {...}
   }
   # Code, Bool, Undef, Whatever, Num, Junction, Str, Hash, ... ...
all do Pattern

   sub *infix:~~ ($item, Pattern $pat) {
   $pat.match($item);
   }

So to add a new pattern, you just implement the Pattern role, and you are safe.

If you are very attached do those two rows of the smart match table,
we can reimplement them as Pattern objects, at the expense of some
unreadability:

   given @array {
   when 42 { ... }
   }

Becomes:

   given @array {
   when contains 42 { ... }
   }

etc.

Luke


Re: Patterns

2007-01-05 Thread Larry Wall
On Fri, Jan 05, 2007 at 08:47:18PM +, Luke Palmer wrote:
: I propose that we remove the following two lines from the smart match
: table in S03:
: 
:HashAny   hash entry existence exists $_{$x}
:Array   Any   array contains item* any($_) === $x
: 
: These are the two lines with Any on the right side.  I want to remove
: these so that we can have an extensible ~~ operator.
: 
: You can think of $x ~~ $y as saying $x matches $y, i.e. $y is some
: data pattern and we are asking if $x conforms to it.  I want to be
: able to add my own kinds of patterns, and entries with Any in the
: right side undermine this.

It's much worse than just those two entries, because any entry not marked
with * is currently considered reversible.  However, I think you're
the path toward sanity.

: Why?  Let's say I created a pattern  which implemented another textual
: matcher alongside Perl's regexes, which was more convenient for some
: things (I shouldn't have to convince you that this is possible and
: useful).  Let's call it Irregex.  I want it to work just like Perl's
: regexes; i.e. I want it so that if you ask whether an array matches
: it, it will match against the elements of the array as though they
: were characters.  So I just overload ~~ to work on (Array, Irregex)
: and that overrules (Array, Any) so there is no MMD ambiguity.
: 
: However!  Let's say I'm using a payroll library (or something, sorry
: for the mundane examples; I'm trying to keep it realistic) which sends
: a notification if any user's status matches a pattern, and it is
: implemented like so:
: 
:method notify(Any|Junction $pattern) {
:if @.users.status ~~ $pattern {
:# send notification
:}
:}
: 
: This is perfectly fine, elegant code given the ~~ table.  But it
: breaks since we have added our new pattern type!  It doesn't check if
: any user's status matches, it checks if the users' statuses'
: concatenated considered as atoms matches, totally wrong!

I'm not so worried about extensibility as I am about consistency between
compile time and run time, such that the optimizer can optimize without
surprising the user.  But this also argues against any anonymous Any on
the right.  If all the when expressions are Num, the optimizer wants to
be able to evaluate the given in a numeric context whether or not you
put + on the front of it.

: So, I'm essentially asking for ~~ to be singly-dispatched based on its
: right argument, which gets to pick how to interpret the left one.  In
: order to encourage this usage, I propose a design like so:
: 
:role Pattern {
:method match($item) {...}
:}
:# Code, Bool, Undef, Whatever, Num, Junction, Str, Hash, ... ...
: all do Pattern
: 
:sub *infix:~~ ($item, Pattern $pat) {
:$pat.match($item);
:}

One little problem here is that .match is currently defined the reverse
of that for the method form of m//.

: So to add a new pattern, you just implement the Pattern role, and you are 
: safe.
: 
: If you are very attached do those two rows of the smart match table,
: we can reimplement them as Pattern objects, at the expense of some
: unreadability:
: 
:given @array {
:when 42 { ... }
:}
: 
: Becomes:
: 
:given @array {
:when contains 42 { ... }
:}
: 
: etc.

Rather than special casing array matching, I'd say we want a general form
for explicitly reversing the figure/ground.  If .match demands a pattern on
the left, then

given @array {
when .match(42) {...}
}

will already reverse the test to mean 42 ~~ @array.  As I say, we need to
figure out what to do with foo.match(/bar/) though.

Larry


Re: Patterns

2007-01-05 Thread Larry Wall
At the moment I'm leaning toward:

$pattern.accepts($thing)
$pattern.rejects($thing)

and going the other way

$thing ~~ $pattern
$thing.match($pattern)
$thing.subst($pattern)

and most generally, something like:

$thing.does($pattern)
$thing.when($pattern)

By the way, the Pattern type is already called Selector in the
synopses.  Or perhaps Selector is a bit more general.  Arguably Pattern
is the role that defines .accepts and .rejects,  but Selector is
really the Pattern|Junction type you use in a signature.  But we can't
just have Pattern does Junction or everything turns into a junction.  :/

Or maybe they should be the other way around, where Selector is the role
and Pattern is the sig type.  Or maybe the sig type should be Where so
we can say

multi grep (Where $where, [EMAIL PROTECTED]) {...}

and call it with :where{...} or where = {...}.  Selector is kind of
a stupid name in any event.

Anyway, that gives us:

given $pattern {
when .accepts(42) {...}
}

which given typical usage patterns of switch statements is probably
adequately huffmanized, unless we want to go for something shorter
than accepts/rejects, like

acc/rej
pix/nix
ok/bogus

Of course, all of the .rejects() variants could simply be spelled
.accepts().not, but that seem unnecessarily cruel.

Larry


Re: dis-junctive patterns

2005-11-22 Thread TSa

HaloO,

Gaal Yahas wrote:

In pugs, r7961:

 my @pats = /1/, /2/;
 say MATCH if 1 ~~ any @pats; # MATCH
 say MATCH if 0 ~~ any @pats; # no match

So far so good. But:

 my $junc = any @pats;
 say MATCH if 1 ~~ $junc; # no match
 say MATCH if 0 ~~ $junc; # no match

Bug? Feature?


Ohh, interesting. This reminds me to my proposal
that junctions are code types and exert their magic
only when recognized as such. The any(@pats) form
constructs such a code object right in the match while
the $junc var hides it. My idea was to explicitly
request a code evaluation by one of

  my junc = any @pats; # 1: use code sigil
  say MATCH if 1 ~~ junc;

  say MATCH if 1 ~~ do $junc; # 2: do operator

  say MATCH if 1 ~~ $junc();  # 3: call operator

But this might just be wishful thinking on my side.
--


Re: dis-junctive patterns

2005-11-22 Thread Larry Wall
On Tue, Nov 22, 2005 at 09:31:27AM +0200, Gaal Yahas wrote:
: In pugs, r7961:
: 
:  my @pats = /1/, /2/;
:  say MATCH if 1 ~~ any @pats; # MATCH
:  say MATCH if 0 ~~ any @pats; # no match
: 
: So far so good. But:
: 
:  my $junc = any @pats;
:  say MATCH if 1 ~~ $junc; # no match
:  say MATCH if 0 ~~ $junc; # no match
: 
: Bug? Feature?

Feels like a bug to me.  The junction should autothread the ~~ even if ~~
weren't dwimmy.  And ~~ ought to be dwimmy about junctions even if they
didn't autothread.  Maybe they're just doing the hallway dance.

Larry


dis-junctive patterns

2005-11-21 Thread Gaal Yahas
In pugs, r7961:

 my @pats = /1/, /2/;
 say MATCH if 1 ~~ any @pats; # MATCH
 say MATCH if 0 ~~ any @pats; # no match

So far so good. But:

 my $junc = any @pats;
 say MATCH if 1 ~~ $junc; # no match
 say MATCH if 0 ~~ $junc; # no match

Bug? Feature?

-- 
Gaal Yahas [EMAIL PROTECTED]
http://gaal.livejournal.com/


Re: Junctions, patterns, and fmap again

2005-09-20 Thread Stuart Cook
On 20/09/05, Luke Palmer [EMAIL PROTECTED] wrote:
 The basic idea is that, alongside Functor, you have a Zippable theory
 which defines:
 
 theory Zippable[::T] {
 multi zip (T[::A], T[::B] -- T[:(::A, ::B)]) {...}
 }
 
 Where that last coloney madness is a yet-to-be-proposed tuple type
 (but tuples can be emulated if they are not in the core language, so
 it's no biggie).  That is, zip takes two structures and figures out
 how to combine them in a reasonable way into pairs of values.  So:
 
 zip([1,2,[3,4]], [[a,b], c, d])
 
 Gives:
 
 [[:(1,a), :(1,b)], :(2,c), [:(3,d), :(4,d)]]

Oh, looks like I was way off. So in this particular scenario, when one
side 'runs out' of structure, that part degenerates to a one-side fmap
using the leaf value as the non-hyper arg.

Of course, this is the behaviour for /built-in/ arrays--it's up to the
person defining fzip to determine how to handle their own Zippable
types. So, if they want fzip to fail() on incompatible structures, or
do some other crazy thing, they can just put that in their version of
fzip.

 So it's really up to the zippable functor itself to figure out the
 best way to zip.  After the structures are zipped up, you fmap the
 binary function on each of the tuples, resulting in a reasonable
 functor structure again.

Bottom line: user-defined fzip turns two structures into one
structure of pairs (in whatever way the user deems reasonable), and
then fmap transforms the tuples of that one structure.

For things like `foo(»$x«, »$y«, »$z«)` (assuming it ends up being
supported), you would either extend fzip over n-tuples, or just use
pair-fzip repeatedly and reduce the nested pairs into a single
n-tuple.

 Nope.  Here it is.  And it was 22 lines. :-)
 
 http://svn.luqui.org/svn/misc/luke/work/code/haskell/hyper.hs

Thanks, that made it a lot clearer. Haskell++ :)

I just hope you and I aren't the only ones who think this is a great idea...


Stuart


Re: Junctions, patterns, and fmap again

2005-09-19 Thread Stuart Cook
On 19/09/05, Luke Palmer [EMAIL PROTECTED] wrote:
 Part 1: fmap
 
 I have a plan for the $x »+« $y form (and also foo(»$x«, »$y«, »$z«)),
 but I don't want to go into that right now.  It basically involves
 zipping the structures up into tuples and applying the function to the
 tuples.

Does this mean that 'unary' (one-side) hyper would be
structure-preserving, but 'binary' (two-side) hyper would not? Or
would you take the final list of tuples and re-build a structure?

I guess it comes down to whether you want to allow binary-hyper on
values that aren't structurally equivalent.  Either you flatten both
structures to lists (which might be semantically dubious), or you
disallow binary-hyper on structurally distinct arguments (which might
prohibit some useful operations). Or you do something inconsistent.

(Have you written any of these deep details up somewhere? I'd love to
read them.)


 Part 2: Junctions
 
 So my proposal is to make a Junction into a plain old Functor.  So
 what used to be:
 
 if any(@values) == 4 {...}
 
 Is now:
 
 if any(@values) »== 4 {...}
 
 And the only thing that makes junctions different from Sets (which are
 also Functors) is their behavior in boolean context (and their ability
 to be Patterns; see below).

I think this is really nice: we get rid of invisible junction magic,
yet accessing that magic explicitly is only one or two characters
away. Being able to pass junctions around as values (safely) is a nice
bonus too.


Stuart


Re: Junctions, patterns, and fmap again

2005-09-19 Thread Luke Palmer
On 9/19/05, Stuart Cook [EMAIL PROTECTED] wrote:
 On 19/09/05, Luke Palmer [EMAIL PROTECTED] wrote:
  Part 1: fmap
 
  I have a plan for the $x »+« $y form (and also foo(»$x«, »$y«, »$z«)),
  but I don't want to go into that right now.  It basically involves
  zipping the structures up into tuples and applying the function to the
  tuples.
 
 Does this mean that 'unary' (one-side) hyper would be
 structure-preserving, but 'binary' (two-side) hyper would not? Or
 would you take the final list of tuples and re-build a structure?

Well, I've written up the details in a 40 line Haskell program to make
sure it worked.  I think I deleted the program, though.

The basic idea is that, alongside Functor, you have a Zippable theory
which defines:

theory Zippable[::T] {
multi zip (T[::A], T[::B] -- T[:(::A, ::B)]) {...}
}

Where that last coloney madness is a yet-to-be-proposed tuple type
(but tuples can be emulated if they are not in the core language, so
it's no biggie).  That is, zip takes two structures and figures out
how to combine them in a reasonable way into pairs of values.  So:

zip([1,2,[3,4]], [[a,b], c, d])

Gives:

[[:(1,a), :(1,b)], :(2,c), [:(3,d), :(4,d)]]

In order to be consistent with the specced semantics.  In order to
keep with the specced semantics of junctions, you'll probably see:

zip(1|2, 34)

Give:

(:(1,3)  :(1,4)) | (:(2,3)  :(2,4))

So it's really up to the zippable functor itself to figure out the
best way to zip.  After the structures are zipped up, you fmap the
binary function on each of the tuples, resulting in a reasonable
functor structure again.

Hmmm, that should probably be fzip or something. 

Luke


Re: Junctions, patterns, and fmap again

2005-09-19 Thread Luke Palmer
On 9/19/05, Luke Palmer [EMAIL PROTECTED] wrote
 Well, I've written up the details in a 40 line Haskell program to make
 sure it worked.  I think I deleted the program, though.

Nope.  Here it is.  And it was 22 lines. :-)

http://svn.luqui.org/svn/misc/luke/work/code/haskell/hyper.hs

Luke


Junctions, patterns, and fmap again

2005-09-18 Thread Luke Palmer
Okay, due to some discussion on #perl6, I'll assume that the reason my
fmap proposal was Warnocked is because a fair number of people didn't
understand it.  Also, for the people who did understand, this message
includes a complete proposal for the workings of Junctions that will
fluster Damian again.  :-)

Part 1: fmap

De-symmetricalize hyper.  So, what used to be @foo »+« 1 is now @foo
»+ 1; the hyper marker is only on the side of the operator that is
being hypered over.  Of course, we still have @foo »+« @bar.

An object may do the role[1] Functor, in which case it defines a
method 'fmap' which is a generalization of map.  For instance, let's
try it with a tree.

class Tree does Functor {
method fmap (code) {...}
}
class Branch is Tree {
has Tree $.left;
has Tree $.right;
method fmap (code) {
# Return an identical tree with the leaves mapped with code
return Branch.new(
left  = $.left.fmap(code),
right = $.right.fmap(code),
);
}
}
class Leaf is Tree {
has $.data;
method fmap (code) {
# Just apply code to the value in the leaf
return Leaf.new( data = code($.data) )
}
}

Now if we have a $tree that looks like:

+---+---3
|   +---4
+---5

$tree.fmap:{ $_ * 2 } returns:

+---+---6
|   +---8
+---10

The formal signature of fmap is, if T is a Functor:

multi fmap (T[::U], code:(::U -- ::V) -- T[::V])

That is, it takes a T of some type, and a code that maps some type to
some other type, and returns a T of that other type.

Now, hypers are just syntactic sugar for various forms of fmap:

$x »+ $y# $x.fmap:{ $_ + $y }
$x +« $y# $y.fmap:{ $x + $_ }
foo(»$x«)   # $x.fmap:{ foo($_) }

I have a plan for the $x »+« $y form (and also foo(»$x«, »$y«, »$z«)),
but I don't want to go into that right now.  It basically involves
zipping the structures up into tuples and applying the function to the
tuples.

Part 2: Junctions

A Junction is a set of values together with a logical operation to be
applied when the Junction is in boolean context.  When you add to a
Junction, you add to each of its values.  When you pass a Junction to
a function, you call the function for each of its values and
reconstruct based on the return values.  All in all, a Junction sounds
like a perfect candidate to be a Functor.  Except all the fmapping is
implicit, which is what makes Junctions break the transitivity of ,
the orthogonality of the patterns 1 and 2, and all that other
stuff that people like me covet so.

So my proposal is to make a Junction into a plain old Functor.  So
what used to be:

if any(@values) == 4 {...}

Is now:

if any(@values) »== 4 {...}

And the only thing that makes junctions different from Sets (which are
also Functors) is their behavior in boolean context (and their ability
to be Patterns; see below).

Yeah, it's a little teeny bit longer, but I think it is pretty easy to
get used to.  And now junctinve threading looks like threading (just
like with hypers).  The best part is that now it is okay to pass
Junctions to functions since they don't screw with your logical
assumptions, and the signature (Junction $x) is no longer semantically
special; it is a type check just like any other typed signature (and
optional just like any other typed signature :-).

Part 3: Patterns

Like I've said before, a Pattern is a thing that can be on the right
side of a ~~ operator.  Most builtin things are Patterns: numbers,
strings, regexes, lists (maybe), booleans, closures, classes, and
junctions.  Pattern is really a role[2] that requires a match(Any --
Bool).  So then $x ~~ $y is equivalent to $y.match($x).

Here is a table of standard Patterns:

numbers, strings:  eqv
regexes:   match (note this gives us /foo/.match($str) for free)
lists: dunno
booleans:  boolean truth (ignores left side)
closures:  apply closure and test truth
classes:   .does
junctions: see below

A Junction of Patterns does Pattern under its logical operation.  So
$x ~~ any($y,$z) is equivalent to $x ~~ $y || $x ~~ $z.  This is the
only autothreading operation.  And that is so you can say:

given $value {
when 1 | 2 | 3   {...}
when /^foo/ | /^bar/ {...}
}

The signature of grep is:

sub grep (Pattern $pat, [EMAIL PROTECTED]) {...}

So then these all make sense:

grep /foo/, @values;
grep 1|2,   @values;
grep Node,  @objects

And the regular closure form of grep is only for straight boolean
tests against the argument:

grep { lc eq 'foo' } @strings;

This really doesn't give us anything new.  But in my opinion, it
solidifies what we already have greatly, and makes it much easier to
think about and work with (no more guessing :-).  It also trivializes
the smart match table in S04.

Luke

[1] Really

Re: Argument Patterns

2005-03-09 Thread Leopold Toetsch
Luke Palmer [EMAIL PROTECTED] wrote:

 I think we should replace our multimethod system with a more general
 pattern matcher, a variadic multimethod system of sorts.  Multimethods
 need to be variadic anyway, because we want pugs's quicksort example to
 work.

I'd not say replace. The dispatcher will very likely be a Parrot PMC.
The default dispatcher dispatches on types, matching variadic signatures
should be possible too.

All infix operators are multi subs. I can't imagine that we want to pay
the penalty for simple operations like:

  $a = $b + $c

to inspect the values of operands, constraints, rules and what not.

[ dispatching on rules ]

If the involved types need a more fancy dispatcher, their meta-class
should say so.

 Luke

leo


Re: Argument Patterns

2005-03-09 Thread Luke Palmer
Leopold Toetsch writes:
 Luke Palmer [EMAIL PROTECTED] wrote:
 
  I think we should replace our multimethod system with a more general
  pattern matcher, a variadic multimethod system of sorts.  Multimethods
  need to be variadic anyway, because we want pugs's quicksort example to
  work.
 
 I'd not say replace. The dispatcher will very likely be a Parrot PMC.
 The default dispatcher dispatches on types, matching variadic signatures
 should be possible too.
 
 All infix operators are multi subs. I can't imagine that we want to pay
 the penalty for simple operations like:
 
   $a = $b + $c
 
 to inspect the values of operands, constraints, rules and what not.

Having written several multi dispatch systems, I know that this is easy
to optimize.  If nobody has defined + on any fancy subtypes, then we can
quickly fall back to a bitset-intersection dispatch algorithm on the
types (or even, eew, direct lookup).  If + has been defined on fancy
subtypes, then we compile the quickest way to figure out whether none of
the arguments are one of them, and fall back.  This is a little tricky,
but some elementary graph theory gets us there.

Essentially, what dispatcher we're using for + depends on what kinds of
+s people have defined.  That's how it should be; otherwise you'll get
people globally overriding + so they can stick their own dispatcher in
there, which isn't a portable solution.

But we always have enough knowledge to optimize the hell out of this,
and they're not not handwavy we can probably optimizations.  They're
real, and they're pretty darn easy.

Luke


Re: Argument Patterns

2005-03-09 Thread Thomas Sandlaß
Luke Palmer wrote:
But we always have enough knowledge to optimize the hell out of this,
and they're not not handwavy we can probably optimizations.  They're
real, and they're pretty darn easy.
I fully agree. But I like to add that a single 'where' on general
types like Int, Str or even Any can seriously harm performance
because than the dispatcher has to check it always and everywhere!
So the Perl 6 type system let's you have your rope and tie yourself.
Well, that is late binding :)
--
TSa (Thomas Sandla)



Re: Logic Programming with Rules (and Argument Patterns)

2005-03-09 Thread Luke Palmer
Rod Adams writes:
 Indeed, a great deal of logical testing can be performed with the
 current P6RE definition.
 
 For instance:
 
rule Equal  ($x, $y) {{ $x ~~ $y or fail }};
rule Substr (Str $str, Str $in) {{ $in ~~ /$str/ or fail }};
rule IsAbsValue (Num $x, Num $y) {
{$x ==  $y or fail} |
{$x == -$y or fail} };
 
 There are some things that are lacking, however. The first is that all
 of the Cor fail's will get very old for typing and viewing. I would
 propose that we add :a/:assert as a rule modifier, making all closures
 assertions that behave exactly as if you typed a C or fail  at the
 end of each of them.

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

 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...

 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) /

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.

I think you'll be interested in where my 'Argument Patterns' proposal
was going next, before I ran off to class (and got scared of posting it,
because people would get scared of me).  But it seems to be related to
what you're talking about.  Maybe we could unify the pattern proposal
and your generation ideas for logic programming.

[WARNING: highly speculative, abstract, scary content ahead]

You can create patterns outside of argument lists, too.  One kind of
pattern that we're already familiar with is the junction (that's right,
I just redefined what a junction is). If you give a pattern to an array
as a subscript, it returns the pattern that matches each thing
referenced by any subscript pattern, if that makes sense.  

Now, certain types of patterns can be generated.  What exactly can be
generated depends on what types of patterns implement a GENERATE method
that succeeds when you call it.  

Allow me to use $^ as a 'pattern variable' marker for outside of
parameter lists.

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

(@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.

Not only does it work with arrays, it works with any combination of
things that can be generated.  This includes arrays whose shapes are not
declared, hashes, even roles if their implementor decides to implement
GENERATE.

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 } /

Of course, that can much more easily be done with a grep, but hey,
TMTOAWTDI*, right?

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.

That's my first-order approximation.  There is probably some higher
order stuff that proves that I'm way off.

In particular, it would be great if this stuff could be crammed into a
library, but I understand that that would be very hard for such
features...

Luke

* A = Awkward


Re: Argument Patterns

2005-03-09 Thread Luke Palmer
Thomas Sandla writes:
 Luke Palmer wrote:
 But we always have enough knowledge to optimize the hell out of this,
 and they're not not handwavy we can probably optimizations.  They're
 real, and they're pretty darn easy.
 
 I fully agree. But I like to add that a single 'where' on general
 types like Int, Str or even Any can seriously harm performance because
 than the dispatcher has to check it always and everywhere!  So the
 Perl 6 type system let's you have your rope and tie yourself.  Well,
 that is late binding :)

Only if you define an AUTOLOAD on your subtypes.  The way to think about
multimethod implementation problems is inside-out from how you think
about single dispatch.  The *method* is the one that knows everything,
not the object.  So definitions on subtypes of general types only check
for those subtypes when dispatching to the methods defined in them.

Luke


Re: Argument Patterns

2005-03-09 Thread Thomas Sandlaß
HaloO Luke,
you wrote:
[..]  The *method* is the one that knows everything,
not the object.  So definitions on subtypes of general types only check
for those subtypes when dispatching to the methods defined in them.
I stand corrected. Lax usage of Any is fair. Defining subtypes
of general types and using them to constrain e.g. params of subs
is fine, too. But defining a multi branch on a very common operator
like +, * or grep for a predicate---i.e. using where---subtype
is penalized. Sounds reasonable to me.
MfG
--
TSa (Thomas Sandla)



Re: Logic Programming with Rules (and Argument Patterns)

2005-03-09 Thread Rod Adams
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 

Re: Logic Programming with Rules (and Argument Patterns)

2005-03-09 Thread Luke Palmer
Rod Adams writes:
 
 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.

You're right.  We probably need something like:

/ generate($x, @values)  test($x) /

I don't know when $x is hypotheticalized there, if at all.  It needs
to be.

 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.

I was decently insane last night.  This generator stuff probably isn't
going anywhere.  It's too abstract, and not precise enough, to be a
truly powerful part of the language.

Luke


Re: Logic Programming with Rules (and Argument Patterns)

2005-03-09 Thread Larry Wall
On Wed, Mar 09, 2005 at 08:56:22AM -0700, Luke Palmer wrote:
: I was decently insane last night.  This generator stuff probably isn't
: going anywhere.  It's too abstract, and not precise enough, to be a
: truly powerful part of the language.

I suspect it's another one of the many things we just try to
stay within hailing distance of without trying to solve for 6.0.0.
The worst that can happen is that someone later defines use coolness
to turn their program into something that doesn't interoperate
with standard Perl 6.  Then we either bend Perl 6 to where it is
interoperable, or someone rewrites all the libraries for coolness.
Biologically, it comes down to more sex and a bigger gene pool,
or less sex and more speciation and specialization.  Sex is fun,
but it probably doesn't solve all your problems.

Larry


Re: Logic Programming with Rules (and Argument Patterns)

2005-03-09 Thread Rod Adams
Larry Wall wrote:
I suspect it's another one of the many things we just try to
stay within hailing distance of without trying to solve for 6.0.0.
 

That's cool.
I was just relaying the observation that the P6RE was fairly close to 
being able to implement Logical Programming, which several people seem 
to be trying to get into Perl in some fashion or another. I can easily 
wait until 6.2 for this to happen (for now at least).

-- Rod Adams



Re: Logic Programming with Rules (and Argument Patterns)

2005-03-09 Thread Ovid
--- Rod Adams [EMAIL PROTECTED] wrote:
 I was just relaying the observation that the P6RE was fairly close to
 being able to implement Logical Programming, which several people
 seem to be trying to get into Perl in some fashion or another.

When I get a chance to talk to someone about logic programming, there's
frequently an aha! moment where they start to see some of the
potential, but then I inevitably get the question if it's so powerful,
why ain't it rich? (or something like that.)

The answer, I think, is that it's generally not available in the tools
that most people use.  SQL, regexen and makefiles all dance around
logic programming -- well, makefiles sort of stumble -- but if LP was
more readily available, people would be more likely to appreciate it. 
Unfortunately, while Prolog is a piece of cake to learn, this thread
made my head hurt.

Cheers,
Ovid

If this message is a response to a question on a mailing list, please send
follow up questions to the list.

Web Programming with Perl -- http://users.easystreet.com/ovid/cgi_course/


Argument Patterns

2005-03-08 Thread Luke Palmer
All this Haskell programming has opened my eyes to what our multimethod
dispatch could be.  As we have seen with Csort, the dispatch system is
a pattern matcher.  But it's a pretty terrible one. 

I think we should replace our multimethod system with a more general
pattern matcher, a variadic multimethod system of sorts.  Multimethods
need to be variadic anyway, because we want pugs's quicksort example to
work.

Here's my proposal:

Inside an argument list, the first mention of a variable introduces its
binding.  Later arguments require a match.  We can now define 'equal':

sub equal ($x, $x) { 1 }
sub equal ($x, $y) {  }

That's one of the MTOWs at least.  The evaluation order of the patterns
still needs to be thought out.

There are more types of patterns.  Types are patterns, and from this we
see that following a pattern by a variable binds the variable to
whatever matched that pattern.  Constants are also patterns.  Junctions
of patterns are also patterns.  Lists of patterns are patterns, as are
hashes of patterns.  In fact, the last two give us slurpy scalars:

sub length () { 0 } 
sub length (*[ $x, [EMAIL PROTECTED] ]) { 1 + length @rest }

And +$name parameters:

sub length (*{ name = $name }) { }

Cwhere constrains a pattern:

sub factors ($x where { is_prime($x) }) { $x }
...

(The object in question is given as the topic of the where block:

sub factors ($x where { .is_prime }) { $x }
...

)

There will also be hooks to allow arbitrary pattern objects.

# does $x match our pattern?
method Pattern::MATCHES ($x) { ... }

And now here's the cool part.  A type is defined to be a pattern (a
'class' is different, though, but it creates an identically-named type).
So instead of definining these multis (I seek to banish the 'multi'
keyword, since I seek to banish the idea of an invocant), you could also
pretend that they're methods on subtypes.  A 'role' is just a collection
of methods on a type, a pattern:

role ($x where {.is_prime}) {
method factors() { $?SELF }
}

This is exactly equivalent to:

sub factors($x where {.is_prime}) { $x }

And of course, if you define a role with a name, then it becomes an
abstract type:

role Serializable {
method serialize() {...}
method clone() { restore(.serialize) }
}

And you have to tell objects that they're Serializeable. 

Luke


Re: Argument Patterns

2005-03-08 Thread Rod Adams
Luke Palmer wrote:
All this Haskell programming has opened my eyes to what our multimethod
dispatch could be.  As we have seen with Csort, the dispatch system is
a pattern matcher.  But it's a pretty terrible one. 

I think we should replace our multimethod system with a more general
pattern matcher, a variadic multimethod system of sorts.  Multimethods
need to be variadic anyway, because we want pugs's quicksort example to
work.
Here's my proposal:
Inside an argument list, the first mention of a variable introduces its
binding.  Later arguments require a match.  We can now define 'equal':
   sub equal ($x, $x) { 1 }
   sub equal ($x, $y) {  }
That's one of the MTOWs at least.  The evaluation order of the patterns
still needs to be thought out.
 

I thought Larry already declared that we are not making Perl act like ML 
(yet).

-- Rod Adams 




Re: Argument Patterns

2005-03-08 Thread Autrijus Tang
On Tue, Mar 08, 2005 at 04:55:28PM -0600, Rod Adams wrote:
 I thought Larry already declared that we are not making Perl act like ML 
 (yet).

And that was re: type inferencing, not re: pattern matching. :)

Thanks,
/Autrijus/


pgp3tE8H37UB0.pgp
Description: PGP signature


Re: Argument Patterns

2005-03-08 Thread Rod Adams
Autrijus Tang wrote:
On Tue, Mar 08, 2005 at 04:55:28PM -0600, Rod Adams wrote:
 

I thought Larry already declared that we are not making Perl act like ML 
(yet).
   

And that was re: type inferencing, not re: pattern matching. :)
Thanks,
/Autrijus/
 

Sorry about that. Comcast has decided I only get internet connectivity 
for a random 1 minute roughly every 1/2hr today, so I can't perform any 
back searches. I'll make a more detailed response to the original post 
shortly.

-- Rod Adams


Patterns and junctions

2003-04-04 Thread Adam D. Lopresto
I've had an idea brewing for a while, and since talk seems to have turned
to reg^H^H^Hpatterns and rules again, I figured this might be the time to
mention it.

A while ago someone asked about whether backtracking semantics are
mandatory in any implementation, or whether it would be legal to build an
implementation that, for instance, has no preference among alternatives.
I propose that since the empty pattern is no longer legal (and about
time), we use | in patterns to indicate alternation without
preference, and || to indicate try the first, then the second, etc.
So

cat dog fox ~~ /( fox | dog | cat )/;

might match any of the three, and in fact is quite likely to match cat
(since scanning the string could be a very long process), but

cat dog fox ~~ /( fox || dog || cat )/;

would be guaranteed to first try fox, then if that fails backtrack and
try dog, and if that fails backtract to try cat.  The choice of symbols
parallels the junction and short-circuiting or operators, and in most
cases when an alternation is specified, the programmer has no preference
among the alternatives (indeed, in most cases only would could match
anyway), so it seems silly to force the engine to prefer the first one.
I'm imagining that in the first example, the implementation would
probably build an FSA and process each letter as it comes, while the
second would rely on backtracking.

What think you all?
-- 
Adam Lopresto
http://cec.wustl.edu/~adam/

There's too much blood in my caffeinestream.


Re: Patterns and junctions

2003-04-04 Thread Paul

--- Adam D. Lopresto [EMAIL PROTECTED] wrote:
 I propose that since the empty pattern is no longer legal (and
 about time), we use | in patterns to indicate alternation without
 preference, and || to indicate try the first, then the second,
 etc.

Hmm 
A neat idea, but can you elaborate on when it would matter?

 So
   cat dog fox ~~ /( fox | dog | cat )/;
 might match any of the three, and in fact is quite likely to match
 cat (since scanning the string could be a very long process), but
   cat dog fox ~~ /( fox || dog || cat )/;
 would be guaranteed to first try fox, then if that fails backtrack
 and try dog, and if that fails backtract to try cat.  The choice of
 symbols parallels the junction and short-circuiting or operators,
 and in most cases when an alternation is specified, the programmer
 has no preference among the alternatives (indeed, in most cases only
 would could match anyway), so it seems silly to force the engine to
 prefer the first one.

I thought the requirement to prefer the first was largely an
optimization, so that it could bail when it had a match without
continuing to search. (Wouldn't you know, it was in the *last* place I
looked for it!)

Are you proposing a more DFA-ish behavior, maybe?
Some programs actually embad a DFA for a quick does it match? as
*well* as an NFA for pulling out backreferences once the DFA finds a
hit, but I doubt anybody is planning to embed a pre-matching DFA in
Perl (if so, somebody please tell me now).

 I'm imagining that in the first example, the implementation would
 probably build an FSA and process each letter as it comes, while the
 second would rely on backtracking.

Sounds like DFA/NFA to me
 
 What think you all?

Dunno. Would swell the footprint some, but might have some merit.
DFA's are generally faster, I believe, but P5's NFA is optimized to a
beautiful degree. Might be possible just by tuning the engine some
more, but then the codebase is still swelling

Dan? Parrot's pure NFA, right?

__
Do you Yahoo!?
Yahoo! Tax Center - File online, calculators, forms, and more
http://tax.yahoo.com


Re: Patterns and junctions

2003-04-04 Thread Paul

--- Luke Palmer [EMAIL PROTECTED] wrote:
[extremely large *SNIP*]
 Maybe the |/|| distinction isn't needed, and we just need a
 declarator on rules that says they are side-effect-free, and can thus
 be optimized.
[snip]
 I like this solution better than making a new operator.  In Perl
 tradition, it puts the optimization burdon on the compiler, not the
 programmer.

Agreed. Minimize the need for new grammar in the language, including
operators, but provide a way that code can DWIM the same result. 
If you build it, they will come.

__
Do you Yahoo!?
Yahoo! Tax Center - File online, calculators, forms, and more
http://tax.yahoo.com


Re: possible bugs in Exegesis 5 code for matching patterns

2002-09-21 Thread Smylers

Steve Tolkin wrote:

   { $appendline =~ s/in_marker//;
 
 I think this needs a backslash in front of the  symbol, and a space
 after in_marker, i.e. it should be: 
 
   { $appendline =~ s/in_marker/\sp/;

Isn't the replacement part of a substitution is still a string?
Having the replacement being a rule would mean that you could write
things like:

  s:e/ \* / [aeiou] /;

That would replace asterisks with 'any' vowel, without specifying which
vowel to use.  That makes no sense at all.  (Well, not unless it creates
a superposition, but surely Damian can't have intended to introduce
superpositions like this is the core language?  Can he?)

So since pointy brackets aren't special in strings, it doesn't take a
backslash; similarly spaces should just be written as spaces.

 rule fileinfo {
 out_marker3 $oldfile:=(\S+) $olddate:=[\h* (\N+?) \h*?] \n
 in_marker3  $newfile:=(\S+) $newdate:=[\h* (\N+?) \h*?] \n
 }
 
 rule out_marker { \+ sp }
 rule in_marker  {  - sp }
 
 The sp means a single literal space.  So I think out_marker3
 means look for + + +  rather than +++ which is what is really
 needed to match a Unified diff.

Yes, you look to be right to me.

 If these are bugs, then what would be the best way to
 fix the code while retaining as much reuse as possible.

This is one way:

  rule out_marker_symbol { \+ }
  rule in_marker_symbol  {  - }

  rule out_marker { out_marker_symbol sp }
  rule in_marker  { in_marker_symbol  sp }

  rule fileinfo {
  out_marker_symbol3 $oldfile:=(\S+) $olddate:=[\h* (\N+?) \h*?] \n
  in_marker_symbol3  $newfile:=(\S+) $newdate:=[\h* (\N+?) \h*?] \n
  }

[While we're on the subject of typos, it looks like the final definition
of Cfileinfo in the exegesis has C$newfile where C$oldfile is
meant.]

But it'd probably be easier just to do:

  rule fileinfo {
  \+\+\+ $oldfile:=(\S+) $olddate:=[\h* (\N+?) \h*?] \n
  ---$newfile:=(\S+) $newdate:=[\h* (\N+?) \h*?] \n
  }

That isn't a terrible cop out to repeat the symbols, since there's no
reason why the format has to use the same symbols in both places.

Smylers



possible bugs in Exegesis 5 code for matching patterns

2002-09-20 Thread Tolkin, Steve

Here is a discussion thread of Exegesis 5 
http://www.perl.com/pub/a/2002/08/22/exegesis5.html at
http://developers.slashdot.org/developers/02/08/23/1232230.shtml?tid=145
But the signal/noise is too low, with side tracks into
Monty Python etc.   

In section Smarter alternatives there is this code:
{ @$appendline =~ s/in_marker//;
I think this needs a backslash in front of the  symbol, 
and a space after in_marker, i.e. it should be: 
{ @$appendline =~ s/in_marker/\sp/;

That a small issue.  But the following is more
important because it strikes at the ease of
using inheritance of grammars (i.e. patterns).
In
http://www.perl.com/pub/a/2002/08/22/exegesis5.html?page=5#different_diffs
we see the code:
rule fileinfo {
out_marker3 $oldfile:=(\S+) $olddate:=[\h* (\N+?) \h*?] \n
in_marker3  $newfile:=(\S+) $newdate:=[\h* (\N+?) \h*?] \n
}

rule out_marker { \+ sp }
rule in_marker  {  - sp }

The sp means a single literal space.
So I think out_marker3 means look for + + +  
rather than +++ which is what is really needed
to match a Unified diff.  Similarly for in_marker3

Or am I missing something?
If these are bugs, then what would be the best way to
fix the code while retaining as much reuse as possible.

 
Hopefully helpfully yours,
Steve
-- 
Steven Tolkin  [EMAIL PROTECTED]  617-563-0516 
Fidelity Investments   82 Devonshire St. V8D Boston MA 02109
There is nothing so practical as a good theory.  Comments are by me, 
not Fidelity Investments, its subsidiaries or affiliates.