# Bug in RepeatedNull?

RepeatedNull appears to be buggy (versions 8.0, and 9.0).

Define f as follows:

In[1]:= f@s:{h_@___...} := List @@@ s


f is intended to accept (possibly empty) List of non-atomic (possibly empty) expressions with the same head and change that head to List. It seems to work properly at first:

In[2]:= f@{g[x], g[y]}
Out[2]= {{x}, {y}}


(Calculates as intended.)

In[3]:= f@{g[x], h[y]}
Out[3]= f[{g[x], h[y]}]


(Pattern does not match.)

However, f behaves unexpectedly on an empty List:

In[4]:= f@{}
Out[4]= {1}


The pattern does match, as it should, but the appearance of 1 is a complete mystery. I expected f@{} to be List @@@ {}, which is {}. Tracing didn't tell me anything:

In[5]:= Trace[f@{}, TraceInternal -> True]
Out[5]= {f[{}], List@@{1}, {1}}


It's probably a bug. Defining f@{} as a special case seems to fix the problem. However, 1) it's not actually a special case, and 2) I'm not sure in the correctness of the definition since there may be something wrong with the pattern I picked.

1. Was {h_@___...} the right choice of pattern for “(possibly empty) List of non-atomic (possibly empty) expressions with the same head”?

2. Is there a plausible explanation where does 1 come from?

UPD:

To clear things up I'll elaborate on a test example by @m_goldberg (from the answer) and a note by @sebhofer (from a comment):

In[6]:= ReleaseHold[ClearAll /@ Hold[test1, test2]];
In[7]:= test1[patt1: {h_@___ ...}] := Row@{"With named head: ", patt1}
test2[patt2: {_@___ ...}] := Row@{"Without named head: ", patt2}


Results vary with use of named vs unnamed pattern. That's one aspect convincing me to calssify the issue as bug:

In[9]:= {test1@{}, test2@{}} // Column


(Here and after, output formatting is adjusted manually.)

What also concerns me is that existing definitions don't get overwritten:

In[10]:= ClearAll@test
In[11]:= test[patt1 : {h_@___ ...}] := Row@{"With named head: ", patt1}
test[patt2 : {_@___ ...}] := Row@{"Without named head: ", patt2}
DownValues@test
Out[13]= {HoldPattern[test[patt2:{_[___]...}]]  :> "Without named head:" patt2,
HoldPattern[test[patt1:{h_[___]...}]] :> "With named head:" patt1}
In[14]:= test@{}


DownValues is prepended with the subsequent ones:

In[15]:= test[patt1 : {h_@___ ...}] := Row@{"Newdef, with named head: ", patt1}
test[patt2 : {_@___ ...}] := Row@{"Newdef, without named head: ", patt2}
DownValues@test
Out[17]= {HoldPattern[test[patt2:{_[___]...}]]  :> "Newdef, without named head:" patt2,
HoldPattern[test[patt1:{h_[___]...}]] :> "Newdef, with named head:" patt1,
HoldPattern[test[patt2:{_[___]...}]]  :> "Without named head:" patt2,
HoldPattern[test[patt1:{h_[___]...}]] :> "With named head:" patt1}
In[18]:= test@{}
Out[18]= "Newdef, without named head:" {}


While output satisfactorily corresponds to new definition, this probably should not happen due to 1) unpredictability; 2) garbage accumulation.

(Additional examples of unstable pattern matching with RepeatedNull may be found in comments.)

• That's not a problem with the pattern. Try List @@@ Sequence[] – sebhofer Nov 11 '13 at 23:30
• @rm-rf Can do, I thought we might want to keep the OP puzzling for a bit :) – sebhofer Nov 11 '13 at 23:36
• Ok, I vote for bug. Smallest example {} /. s : {h_ ...} :> s gives Sequence[] – Rojo Nov 12 '13 at 3:21
• @Rojo, good example. Interesting that both {} /. s : {h ...} :> s and {} /. s : {_ ...} :> s behave as expected – Simon Woods Nov 12 '13 at 14:10
• @RolfMertig The bug woundn't that it matches, but what the label s matches to – Rojo Nov 12 '13 at 15:06

Here is some evidence concerning what is going wrong.

ff[arg : {(h : _)@___ ...}] := Row @ {h, " : ", arg}

ff @ {u[x]}

u : {u[x]}

ff @ {{x}}

List : {{x}}

ff @ {{}}

List : {{}}


All the above show what one would expect, but

ff @ {}

{} :


In this last case, I conclude that h has been matched with {} and arg has been matched with Sequence[]. I can not but think that this is a bug.

• Perhaps I misunderstood your last phrase. If arg had been matched with {} and h with Sequence[] everything would be fine. But it was the other way around, and that's the bug. – Rojo Nov 12 '13 at 5:38
• @Rojo. Good catch, I corrected my typo. – m_goldberg Nov 12 '13 at 5:43