Message Boards Message Boards

0
|
3306 Views
|
6 Replies
|
4 Total Likes
View groups...
Share
Share this post:

Pattern matching: BlankSequence in combination with Flat attribute

Posted 3 years ago

Dear all,

regardless of the sense of the following definitions:

f[x_ + y_Plus] := {x, {y}}
g[x_ + y__Plus] := {x, {y}}

Why does g not match the following expression, as it does with f:

f[a + b + c]
g[a + b + c]

Result:

{a, {b + c}}
g[a + b + c]

I would expect, g[a+b+c] is transformed to g[a + Plus(b,c)] (due to the Flat attribute of Plus) and then a matches x_ and Plus(b,c) matches y__ Plus, even because y__ Plus is less specific than y_ Plus (in case of f)

POSTED BY: Martin Guttmann
6 Replies

Dear Neil,

thank you again for your answer. In the second part you hit the point, what I try to understand:

If foo has the attribute Flat and y__foo can only match a sequence of foo than the whole expression can be transformed from foo[aa, bb, cc] to foo[aa, foo[bb, cc]] and then the matching should succeed, because the second argumnt is a sequence of one element with head foo? Also foo[aa, foo[bb], foo[cc]] is possible and y__foo can match Sequence[foo[bb], foo[cc]]].

Without the attribute Flat, it also works like that and gives True:

MatchQ[bar[a, bar[b, c]], bar[x_, y__bar]]

Please note, of course I know how to do the matching to make it working (like you showed multiple times). But I also want to understand the internal process, and why my first example failed, when a head is added after BlackSequence.

POSTED BY: Martin Guttmann

also, when matching flat functions, it is often useful to use Shortest and Longest. For example:

In[7]:= foo[aa, bb, cc,  dd] /. (foo[Longest[x_], foo[y__]] -> zz[{x, y}])

Out[7]= zz[{foo[aa, bb, cc], dd}]

Regards

POSTED BY: Neil Singer

Martin,

I'm not sure exactly what you are asking but What you are observing is a property of functions that have the Flat attribute. The pattern matcher knows that the function is Flat so it is smart enough to know that you can break Plus[a, b, c] into Plus[a, Plus[b,c]] for the purpose of pattern matching. Here is an example without using plus that should make it clear. The first few lines show that I can create a function foo that behaves like Plus.

In[18]:= SetAttributes[foo, Flat]

In[20]:= foo[aa, foo[bb], foo[cc]]

Out[20]= foo[aa, bb, cc]

In[21]:= foo[aa, foo[bb, cc]]

Out[21]= foo[aa, bb, cc]

In[24]:= foo[aa, bb, cc] /. (foo[x_, y_foo] -> zz[{x, y}])

Out[24]= zz[{foo[aa], foo[bb, cc]}]

so even though the foo operator is only used once, it can be matched as nested.

So I think what you are seeing is the affect of matching flat functions. In most cases, you must exactly match the internal representation of the expression to get a match. In the case of y__head -- this will only match a sequence with each and every element in the sequence having the head "head":

so this fails:

foo[aa, bb, cc] /. (foo[x_, y__foo] -> zz[{x, y}])

but this works:

foo[aa, bb, cc] /. (foo[x_, foo[y__]] -> zz[{x, y}])

because bb and cc do not have a head of foo but foo[bb,cc] does.

So returning to your original example, you can make g pattern match by using

g[x_ + y__] := {x, {y}}

because y is matching the sequence[bb,cc] and not Plus[bb,cc].

I hope this helps.

Regards,

Neil

POSTED BY: Neil Singer

It is clear, that BlackSequence matches a sequence, but also one element is a sequence, as it is working here:

h[x_ + y__Times] := {x, {y}}
h[a + b*c]

which gives

{a, {b c}}
POSTED BY: Martin Guttmann

Martin,

The difference is that x_ matches an expression while y__ matches a sequence. So for example, this will work:

g[x_ + Plus[y__]] := {x, {y}}

Also using Shortest and Longest helps in matching sequences.

Regards,

Neil

POSTED BY: Neil Singer
Posted 3 years ago

Martin:

Thanks for the great question.

I'm surprised that f[] matches.

FullForm[a + b + c] is Plus[a, b, c].

Of course this is equivalent to a + Plus[b, c], but I don't understand why Mathematica would have transformed Plus[a, b, c] to a + Plus[b, c] and not Plus[a, b] + c.

I'm hoping someone chimes in on this one.

POSTED BY: Mike Besso
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract