# How can I overload a function with multiple bracket-slots so f[a][b] and f[a] can coexist?

Maybe this is not even possible:

I want to create a function f that can have two input brackets like:

f[a_][b_:1]:= a*b


and alternatively just one input bracket:

f[a_]:= a


But with overloading the definitions the second definition interferes with the first definition, because the pattern f[a_] is replaced in a expression like:

In:

f[2][3]


Out:

2[3]


with the result of f[2] (in this case)

Of course, I could use just one bracket slot like f[a_,b_:1], instead of f[a_][b_:1], but thats not the point.

So i am asking for an optional bracket slot. Is that possible?

(BTW, I dont know the correct name of the []-Pattern, and called it bracket slot)

• Just curious, why not f[a_] and f[a_, b_], or two different functions? Feb 27, 2015 at 0:26
• Related: (5686494), (544), (9741), (42030) Feb 27, 2015 at 0:53
• @2012rcampion i know that this is a very special case, but sometimes i want to have both possibilities with the same function. Feb 27, 2015 at 1:23
• @sacratus It actually seems rather natural to me, though in my opinion one must choose between this syntax and Currying as using them concurrently (not for the same function) would be quite confusing. Feb 27, 2015 at 1:25

In the Standard Evaluation Sequence the heads of expressions are evaluated first:

1. If the expression is a raw object (e.g., Integer, String, etc.), leave it unchanged.

2. Evaluate the head h of the expression.

3. Evaluate each element of the expression in turn ...

Therefore since f[1] is the head of f[1][2] it will evaluate if it has a definition that matches. This is unavoidable in standard evaluation. To get around this requires Stack trickery that Leonid illustrated here. It works on the principle that f is the head of f[1] itself and is therefore evaluated first of all.

Here is a meta-function to automate his method:

SetAttributes[deepDefine, HoldAll]

deepDefine[s_Symbol, LHS_, RHS_] :=
s :=
With[{stack = Stack[_]},
With[{fcallArgs = Cases[stack, HoldForm[LHS] :> RHS]},
(First@fcallArgs &) & /; fcallArgs =!= {}
]
]


We now apply it like this:

ClearAll[f]

deepDefine[f, f[a_][b_: 1], a*b]

f[a_] := a


Test:

f[x]
f[x][y]
f[z][]

x

x y

z

• wow, this is impressive! i did not expected, that one found a solution for this. Thanks you very much! Feb 27, 2015 at 1:19
• @sacratus All the credit for this method goes to Leonid; please vote for his answer. I just "put a ribbon on it" with deepDefine. :-) Feb 27, 2015 at 1:21
• I allready upvoted Leonids answer, but refering to a good existing answer is also honorable :-) Feb 27, 2015 at 4:36
• @sacratus: just as an advice, I think you really should think about the last sentence in Leonids answer before building "prodution code" that relies on Stack... Feb 27, 2015 at 9:56