5

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)

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
sacratus
  • 1,556
  • 10
  • 18

1 Answers1

6

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

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • wow, this is impressive! i did not expected, that one found a solution for this. Thanks you very much! – sacratus Feb 27 '15 at 01: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. :-) – Mr.Wizard Feb 27 '15 at 01:21
  • I allready upvoted Leonids answer, but refering to a good existing answer is also honorable :-) – sacratus Feb 27 '15 at 04:36
  • 1
    @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... – Albert Retey Feb 27 '15 at 09:56