# Version inconsistency with optional arguments: what if the default value doesn't match the pattern?

I just came across some weird behaviour. Take this function definition:

ClearAll[f]
f[vs_List : All] := "match"


The default value of vs is All. Now think about what f[] should return. Should it evaluate? You might say yes, vs will just take the default value. But you might say, wait, All doesn't even match _List so this is nonsense!

It turns out that different versions behave differently:

Version 9.0.1:

{$VersionNumber,$ReleaseNumber}
f[]
(* {9., 1} *)
(* f[] *)


Version 10.0.2:

{$VersionNumber,$ReleaseNumber}
f[]
(* {10., 2} *)
(* f[] *)


Version 10.2.0:

{$VersionNumber,$ReleaseNumber}
f[]
(* {10.2, 0} *)
(* "match" *)


Version 10.3.1:

{$VersionNumber,$ReleaseNumber}
f[]
(* {10.3, 1} *)
(* "match" *)


I don't have version 10.1.0 to try with.

Question: Is there a bug somewhere? Which should be the correct behaviour?

Ultimately this is of course a GIGO situation because the pattern arguably doesn't make sense. The solution is easy: just use f[vs : (_List | All) : All] := "match". But I made a mistake and used _List : All instead. Then much later I discovered that my test suite failed in version 10.0 while it was passing in 10.3.

What would be the most user-friendly behaviour in my opinion is for Mathematica to show a warning when it encounters this situation. Either way, it would be nice to have a mention of this behaviour in the documentation.

-
Related: (4937) – Mr.Wizard Feb 29 at 11:32
A really interesting observation! Version 10.1.0 under Windows also gives "match". – Mr.Wizard Feb 29 at 11:33
Also related: (17707) – Leonid Shifrin Feb 29 at 11:42
This change was intentional, and per request of the boss. – Daniel Lichtblau Feb 29 at 17:10
@Daniel Thanks! Could we please have this noted in the documentation somewhere, if it is not already? – Mr.Wizard Mar 1 at 2:32

This change was intentional, and per request of the boss.

I can find no mention of this in the documentation, though I am still looking. My guess is that the old behavior was a common source of problems and someone's fix was to implement the new behavior in version 10.1.0.

On the surface at least I like the change as it shortens and simplifies code. A notable difference is that with the new short scheme the default value is not seen as a valid explicit argument:

f[All]

(* Out:   f[All]   -- 10.1.0 under Windows *)


I think this actually may prove useful but I can also imagine it being a new source of confusion.

Perhaps this change makes behavior more consistent than it was in the past.
Consider this behavior in older versions (here v7):

ClearAll[f, val]

f[vs_List: val] := vs
val = {1, 2, 3};
f[]

(* Output:   f[]   -- no match *)

ClearAll[f, val]

f[vs : (_List | HoldPattern[val]) : val] := vs
val = "foo";
f[]

(* Output:   "foo"   *)


I find both cases unexpected even if explainable. The new more permissive behavior makes these cases more similar as both evaluate using the current value of val.

-