Skip to main content

functional style - Pseudo-currying in one line


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.



Answer



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] *)

Comments

Popular posts from this blog

front end - keyboard shortcut to invoke Insert new matrix

I frequently need to type in some matrices, and the menu command Insert > Table/Matrix > New... allows matrices with lines drawn between columns and rows, which is very helpful. I would like to make a keyboard shortcut for it, but cannot find the relevant frontend token command (4209405) for it. Since the FullForm[] and InputForm[] of matrices with lines drawn between rows and columns is the same as those without lines, it's hard to do this via 3rd party system-wide text expanders (e.g. autohotkey or atext on mac). How does one assign a keyboard shortcut for the menu item Insert > Table/Matrix > New... , preferably using only mathematica? Thanks! Answer In the MenuSetup.tr (for linux located in the $InstallationDirectory/SystemFiles/FrontEnd/TextResources/X/ directory), I changed the line MenuItem["&New...", "CreateGridBoxDialog"] to read MenuItem["&New...", "CreateGridBoxDialog", MenuKey["m", Modifiers-...

How to thread a list

I have data in format data = {{a1, a2}, {b1, b2}, {c1, c2}, {d1, d2}} Tableform: I want to thread it to : tdata = {{{a1, b1}, {a2, b2}}, {{a1, c1}, {a2, c2}}, {{a1, d1}, {a2, d2}}} Tableform: And I would like to do better then pseudofunction[n_] := Transpose[{data2[[1]], data2[[n]]}]; SetAttributes[pseudofunction, Listable]; Range[2, 4] // pseudofunction Here is my benchmark data, where data3 is normal sample of real data. data3 = Drop[ExcelWorkBook[[Column1 ;; Column4]], None, 1]; data2 = {a #, b #, c #, d #} & /@ Range[1, 10^5]; data = RandomReal[{0, 1}, {10^6, 4}]; Here is my benchmark code kptnw[list_] := Transpose[{Table[First@#, {Length@# - 1}], Rest@#}, {3, 1, 2}] &@list kptnw2[list_] := Transpose[{ConstantArray[First@#, Length@# - 1], Rest@#}, {3, 1, 2}] &@list OleksandrR[list_] := Flatten[Outer[List, List@First[list], Rest[list], 1], {{2}, {1, 4}}] paradox2[list_] := Partition[Riffle[list[[1]], #], 2] & /@ Drop[list, 1] RM[list_] := FoldList[Transpose[{First@li...

functions - Get leading series expansion term?

Given a function f[x] , I would like to have a function leadingSeries that returns just the leading term in the series around x=0 . For example: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x)] x and leadingSeries[(1/x + 2 + (1 - 1/x^3)/4)/(4 + x)] -(1/(16 x^3)) Is there such a function in Mathematica? Or maybe one can implement it efficiently? EDIT I finally went with the following implementation, based on Carl Woll 's answer: lds[ex_,x_]:=( (ex/.x->(x+O[x]^2))/.SeriesData[U_,Z_,L_List,Mi_,Ma_,De_]:>SeriesData[U,Z,{L[[1]]},Mi,Mi+1,De]//Quiet//Normal) The advantage is, that this one also properly works with functions whose leading term is a constant: lds[Exp[x],x] 1 Answer Update 1 Updated to eliminate SeriesData and to not return additional terms Perhaps you could use: leadingSeries[expr_, x_] := Normal[expr /. x->(x+O[x]^2) /. a_List :> Take[a, 1]] Then for your examples: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x), x] leadingSeries[Exp[x], x] leadingSeries[(1/x + 2 + (1 - 1/x...