Is it possible to separately call the default value of a variable which isn't at the end of the sequence?

Prioritizing patterns

If you only want the default values for the leading parameters (or some other order you choose), and not an arbitrary parameter at the time of the function call, you can prioritize the patterns as described here.

f[
  Shortest[u_: 1, 3],
  Shortest[v_: 2, 2],
  Shortest[w_: 3, 1]
 ] := u^2 + v^3 + w^4

f[v, w]
1 + v^3 + w^4

Workaround No.1

I am still seeking a pattern-based solution to the arbitrary parameter problem, but until and unless I find it here is a work-around you may consider:

g[Null | u_, Null | v_, Null | w_] :=
 With[{uu = # &[u, 1], vv = # &[v, 2], ww = # &[w, 3]},
  {{"u", uu}, {"v", vv}, {"w", ww}}
 ]

g[, v, w]
g[u, , w]
g[u, v,]
{{u,1}, {v,v}, {w,w}}
{{u,u}, {v,2}, {w,w}}
{{u,u}, {v,v}, {w,3}}

How this works:

  • The pattern Null | param_ is used for each parameter: if Null matches, param in the RHS is effectively replaced with Sequence[].

  • The function # & will return the first argument be there one or more than one; by specifying the optional/default values as the second paramter this will be returned iff the first is removed via Sequence[].

  • With may not always be necessary but it is used for robustness.

Workaround No.2

I think this is a bit cleaner in principle than No.1 though neither is fully satisfying.

h[Null | aa_, Null | bb_, Null | cc_] :=
  {{aa}, {bb}, {cc}} /. {{a_: 1}, {b_: 2}, {c_: 3}} :> {a, b, c}

h[5, ,]
h[, 7,]
h[, , 13]
{5, 2, 3}
{1, 7, 3}
{1, 2, 13}

Workaround No.3

I don't think this is as clean as No.2 but it should be easier to extend.

For functions without a hold attribute you could use this:

ClearAll[f]

lhs : f[___, Null, ___] :=
  With[{def = {"1", "2", "3", "4", "5", "6", "7", "8", "9"}},
    MapIndexed[# /. Null -> def[[First @ #2]] &, Unevaluated[lhs]]
  ]

f[1, , 3, 4, , 6, , , 9] // InputForm
f[1, "2", 3, 4, "5", 6, "7", "8", 9]

The list def gives defaults by position for each parameter. Here I chose numeric strings to make the positions evident while still illustrating the substitution.

If your function does have Hold attributes you will need a slightly more complicated replacement. I will make use of RuleCondition(1):

ClearAll[f]
SetAttributes[f, HoldAll]

lhs : f[___, Null, ___] :=
  Module[{i = 1, def = ToString ~Array~ 9},
    Replace[
      Unevaluated[lhs],
      {Null :> RuleCondition @ def[[i++]], x_ /; (i++; True) :> x},
      {1}
    ]
  ]

f[1, , 3, 2 + 2, , 6, , , 3^2] // InputForm
f[1, "2", 3, 2 + 2, "5", 6, "7", "8", 3^2]

Notice that 4 and 9 have been replaced with 2 + 2 and 3^2 and that these correctly remain unevaluated after the substitution.

Workaround No.4

Michael E2 showed what is perhaps the most declarative method. I don't think by itself it is as easily extensible, but then again there must be a limit to how many arguments a user is going to count anyway. Nevertheless one could automate that method with meta-programming, so let's do it.

makeDefaults[fname_Symbol, defaults_List] :=
  fname @@@ {Pattern[#, _] & /@ #, #} & @ Table[Unique["$"], {Length @ defaults}] //
     Do[
        SetDelayed @@ ReplacePart[#, {{1, n} -> Null, {2, n} -> defaults[[n]]}],
        {n, Length @ defaults}
     ] &

Now:

makeDefaults[fn, {"one", "two", "three"}]

fn[u_, v_, w_] := u^2 + v^3 + w^4

?? fn
Global`fn

fn[Null, $2_, $3_] := fn["one", $2, $3]

fn[$1_, Null, $3_] := fn[$1, "two", $3]

fn[$1_, $2_, Null] := fn[$1, $2, "three"]

fn[u_, v_, w_] := u^2 + v^3 + w^4

A simple solution

After writing a very long answer with one related method and four workarounds it suddenly hit me:
We need the behavior of a Symbol with the OneIdentity attribute!

Observe:

Attributes[foo] = {OneIdentity};

MatchQ[Null, foo[Null, i_: 1]]

True

Times is such a function, therefore we may use:

f[(Null i_: 1) | i_, (Null j_: 2) | j_, (Null k_: 3) | k_] := {i, j, k}

f[, ,]
f[, "b",]
f["a", "b",]
f["a", , "c"]
{1, 2, 3}
{1, "b", 3}
{"a", "b", 3}
{"a", 2, "c"}

Success!

An edge case

Well, there is an edge case that must be addressed: when an argument is of the form Times[Null, . . .] and one actually wants that passed to the RHS:

f[Null * "x", "b", "c"]
{"x", "b", "c"}  (* failure *)

This can be addressed by using a localized Symbol with the OneIdentity attribute:

ClearAll[f]

Module[{Star},
  Attributes[Star] = {OneIdentity};
  f[(Null⋆i_: 1) | i_, (Null⋆j_: 2) | j_, (Null⋆k_: 3) | k_] := {i, j, k}]
]

f[Null * "x", ,]
{"x" Null, 2, 3}

Meta-programming automation

Although I think this pattern is simple enough to use directly (at last!), we can also automate its creation if desired. This function uses a very general replacement on any Optional pattern; more specificity may be desired such as targeting only the left-hand-side or looking no deeper than the first level; these are omitted for clarity but can be added if requested.

SetAttributes[makeFluidDefaults, HoldFirst]

makeFluidDefaults[x_Set | x_SetDelayed] :=
  Module[{oi},
    Attributes[oi] = {OneIdentity};
    Unevaluated[x] /. op_Optional :> oi[Null, op] | op
  ]

Now:

ClearAll[f]

makeFluidDefaults[
  f[i_: 1, j_: 2, k_: 3] := {i, j, k}
]

f[, ,]
f[, "b",]
f["a", "b",]
f["a", , "c"]
f[Null*"x", "b", "c"]
{1, 2, 3}
{1, "b", 3}
{"a", "b", 3}
{"a", 2, "c"}
{"x" Null, "b", "c"}

Here's one way to get the desired behavior, although it is not done with a single pattern:

Clear[f];
f[Null, v_, w_] := f[1, v, w];
f[u_, Null, w_] := f[u, 2, w];
f[u_, v_, Null] := f[u, v, 3];
f[u_, v_, w_] := u^2 + v^3 + w^4;

f[, v, w]
f[u, , w]
f[u, v,]
f[u, ,]
f[, v,]
f[, , w]
f[, ,]
1 + v^3 + w^4
8 + u^2 + w^4
81 + u^2 + v^3
89 + u^2
82 + v^3
9 + w^4
90