Often when I'm writing OOP code using an object-manager association I find myself doing something akin to currying the arguments to some form of delegate object or head. (Building a one-argument chained call as opposed to returning functions of one argument).

Usually I do this via a Block construct but it is the sort of simple functional programming thing that Mathematica really ought to have a built-in for.

What I mean is I have something like:

c[a1, a2, a3, ..., an]

And I would like a function PseudoCurry that upon application to the previous expression would give me:

c[a1][a2][a3][...][an]

To my deep surprise I have been unable to find such a function.

Does anyone know how I can write a one-line, functional way to do this?

I'm sure the answer is dead simple but I'm blanking on it right now.

Update

Thanks to both Bob Hanlon and Mr. Wizard for the answers.

I think this from Bob:

Pseudocurry[h_[a__]] := Fold[#1[#2] &, {h, a}];
Pseudocurry~SetAttributes~HoldFirst;

is the cleanest way to do this without using deprecated functions but Mr. Wizard's

Pseudocurry[h_[a__]] := HeadCompose[h, a];
Pseudocurry~SetAttributes~HoldFirst;

is the clear winner for simplicity, although HeadCompose is deprecated.

share|improve this question
    
To clarify you don't need help getting the expression c[a1][a2][a3][...][an] to evaluate as you want but instead you wish to generate that expression from c[a1, a2, a3, ..., an]? – Mr.Wizard 3 hours ago
    
Just use a conditional downvalue with recursion or Nest – M.R. 3 hours ago
    
@Mr.Wizard exactly. For simplicity assume it's inert. – MB1965 3 hours ago
up vote 3 down vote accepted

EDIT: Modified to cover situation when an argument is a List

Use Fold

expr = c[a1, a2, a3, a4, a5];

Fold[#1[#2] &, {c, List @@ expr} // Flatten[#, 1]&]

(*  c[a1][a2][a3][a4][a5]  *)

expr2 = c[a1, a2, {a31, a32, a33}, a4, a5];

Fold[#1[#2] &, {c, List @@ expr2} // Flatten[#, 1] &]

(*  c[a1][a2][{a31, a32, a33}][a4][a5]  *)
share|improve this answer
2  
Ah, very nice, I thought Fold would be a good way to go. Might I suggest Prepend[List@@expr,Head@expr] instead, though, as the flatten would flatten any sublists in the ai? – MB1965 3 hours ago

The deprecated (but valid) function HeadCompose basically does just that:

c[a1, a2, a3, a4, a5] /. h_[a___] :> HeadCompose[h, a]
c[a1][a2][a3][a4][a5]

If you don't wish to use that then perhaps:

fn = Head @ FixedPoint[Replace[h_[x_, y___] :> h[x][y]], #] &;

c[a1, a2, a3, a4, a5] // fn
c[a1][a2][a3][a4][a5]
share|improve this answer
    
HeadCompose is almost exactly what I wanted. Any idea why it was deprecated? Unfortunately I'm rather wary of deprecated functions. – MB1965 3 hours ago
    
Hmm, wouldn't c[a1, a2, a3, a4, a5] //. h_[x_, y__] :> h[x][y] be simpler than having to use both FixedPoint[] and Replace[]? – J. M. 3 hours ago
    
@J.M. I actually wrote that and then realized that it was not general enough, e.g. c[a1 + a2, a3 + a4, a5] //. h_[x_, y__] :> h[x][y] – Mr.Wizard 3 hours ago
    
@MB1965 Wiser users than I assure me that functions like this aren't going away, so I use them. (e.g. ToHeldExpression; Compose) I would guess that this function was not thought to be widely useful and was dropped from the documentation. – Mr.Wizard 3 hours ago
1  
?? HeadCompose still gives the basic usage. – Bob Hanlon 3 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.