programming - 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)
Answer
In the Standard Evaluation Sequence the heads of expressions are evaluated first:
If the expression is a raw object (e.g., Integer, String, etc.), leave it unchanged.
Evaluate the head h of the expression.
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
Comments
Post a Comment