# Make second argument same as first when only one argument passed to function [duplicate]

This question already has an answer here:

Clear[f]
f[n_, k_: n] :={n, k}
f[x]


{x,n}

Actually I would like to get:

{x,x}

The following is one wrong definition, I'm showing that I need the argument n not a global variable n but the same to the first argument n_.

(*Clear[f]
f[n_,k_: n_]:={n,k}
f[x]*)


If only one argument passed to f, then the second argument is the same to the first argument.

So, how could I adjust the definition of f?

Maybe something like Default?

I think Kuba's answer give one example to do this. But how to define f only once to get the same effect?

Chris Degnen's answer is one bad news.

I've tried this

Clear[f] f[n0_, k0_: 5] := Module[{n = n0, k = k0}, If[k == 5, {n, k = n0},{n, k}]]
f[x]


{x,x}

Good thing is it works well for numerical values.

f[x, 10]


{x,10}

Bad thing is it works badly for y

f[x, y]


If[y==5,{n$37693,k$37693=x},{n$37693,k$37693}]

-

## marked as duplicate by Leonid Shifrin, m_goldberg, HyperGroups, Artes, Sjoerd C. de VriesJun 28 '13 at 15:09

I have responded to Your edit. – Kuba Jun 28 '13 at 9:30
@Kuba ah, it works, I tried one number 5, so I used ==, next time I'll use SameQ firstly. Stefan have gave one answer. – HyperGroups Jun 28 '13 at 10:49

I would use something called overloading (but I'm not sure about the name)

f[n_, k_] := {n, k}
f[x_] := f[x, x]


so:

f[x]
f[x, 5]


{x, x}

{x, 5}

Edit

Reffering to Your last edit. I would use === for testing and y_:"Default" insted of y_:5 (You may need 5 someday :)).

It will work but remember that this is some kind of limitation. Now You are working on values, not the arguments as You may sometimes want to. If it is a problem depends on what You are going to do with this function. I think it is going to suit Your needs in most cases.

-
Your answer is good, I wonder if it could be done by one definition of f. – HyperGroups Jun 28 '13 at 7:30

This has been discussed before. Here is how:

Module[{def}, f[n_, k_: def] := Block[{def = n}, {n, k}]]


The Module is needed to make sure that def is not changeable from the top level. Examples:

f[x, y]

(* {x, y} *)

f[x]

(* {x, x} *)

-
saw your answer when i already updated mine...sorry about that. let's see it as an alternative to your probably best answer. – Stefan Jun 28 '13 at 11:36
ah, good to learn that, is there some links/keywords about some the former discussions? – HyperGroups Jun 28 '13 at 12:26
@HyperGroups For example, here. In fact, your question is a duplicate of that one, so I will leave a comment below it and vote to close. – Leonid Shifrin Jun 28 '13 at 12:33
ok, no problem, good to know about some duplicates. – HyperGroups Jun 28 '13 at 12:41

Roman Maeder addresses this in Programming in Mathematica (3rd ed.), page 21. Regarding default values, he writes:

f[ x_, y_:17 ] := {x, y}


"Please note that the default value cannot depend on the other parameters (x, for example). It is evaluated when the rule is given, rather than later on when the rule is used. In more complicated cases, it is better to give a second rule that computes the default value and then calls the other rule."

... as demonstrated by Kuba.

-
good to know about that. – HyperGroups Jun 28 '13 at 8:41
This is not quite true. See my answer. – Leonid Shifrin Jun 28 '13 at 11:29

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.

-
nice, why the second trick does not generate the right result for f[x,y] as {x,y}? – HyperGroups Jun 28 '13 at 10:53
the two variables x, y represent the same pattern. please have a look at this, which makes that more obvious: y : (y_) : 1 // FullForm. if you want f[x, y] correctly evaluated you have to overload f accordingly. – Stefan Jun 28 '13 at 11:09
What about when somebody calls f[x,Automatic]? :) – Corey Kelly Jun 28 '13 at 11:23
@CoreyKelly result is {x, x}. what are you asking for? – Stefan Jun 28 '13 at 11:33
ah! now i get it. yes :) ... ok. i cannot fight machiavelli. maybe an answer to this "edge"-case is: well Automatic chose automatically x, since y was set to Automatic which chooses x automatically, if y is Automatic. ;) – Stefan Jun 28 '13 at 11:58