Already late to the party, but here is another approach:
ClearAll[f]
f[x_, y_: Automatic] :=
If[y === Automatic, {x, x}, {x, y}]
Another Optional
trick is the following:
ClearAll[f]
f[x : (y_) : 1] := {x, y}
Here the colon is used twice. Once as shorthand for Pattern
and once as shorthand for Optional
. This is not appropriate for you question. I just wanted to mention it.
Edit 1:
Since optional arguments are all about pattern matching, here a list of possible patterns and allowed syntax:
InputForm | FullForm
-----------|---------
x | x
_*x | Times[Blank[], x]
(_.)*x | Times[Optional[Blank[]], x]
_ | Blank[]
x*_ | Times[x, Blank[]]
_x | Blank[x]
x . _ | Dot[x, Blank[]]
_ . x | Dot[Blank[], x]
_. | Optional[Blank[]]
x*(_.) | Times[x, Optional[Blank[]]]
x_. | Optional[Pattern[x, Blank[]]]
_:x | Optional[Blank[], x]
x_ | Pattern[x, Blank[]]
x:(_.) | Pattern[x, Optional[Blank[]]]
x /. _ | ReplaceAll[x, Blank[]]
x /. _. | ReplaceAll[x, Optional[Blank[]]]
_ /. x | ReplaceAll[Blank[], x]
_. /. x | ReplaceAll[Optional[Blank[]], x]
Edit 2:
Another alternative is the following:
Default[f] = def;
f[x_, y_.] := Block[{def = x}, {x, y}]
Probably this is the best form of all I've listed here.