7
$\begingroup$

Is there a more concise way of achieving the following result (possibly without d |->)?

(d |-> (d@Exponent[#, Variables[expr]] &)) /@ {f1, f2}

{f1[Exponent[#1, Variables[expr]]] &, 
 f2[Exponent[#1, Variables[expr]]] &}

I tried to use Through but this gives me incorrect result - the & is in the wrong place in the output.

Through[{f1, f2}[Exponent[#, Variables[expr]] &]]

{f1[Exponent[#1, Variables[expr]] &], 
 f2[Exponent[#1, Variables[expr]] &]}
$\endgroup$
8
  • $\begingroup$ I think there might a new function in 14.0 that is relevant? $\endgroup$ Commented Mar 10, 2024 at 18:07
  • $\begingroup$ @mikado: What function? I have version 13.0. $\endgroup$ Commented Mar 10, 2024 at 18:09
  • 1
    $\begingroup$ @mikado is probably referring to Comap. $\endgroup$ Commented Mar 10, 2024 at 19:16
  • $\begingroup$ @Domen: Does Comap[{f1, f2}, Exponent[#, Variables[expr]] &] output the requested output in 14.0.? $\endgroup$ Commented Mar 10, 2024 at 20:48
  • 2
    $\begingroup$ @Domen I don't think it does. The f1/f2 need to go inside the body of the function. $\endgroup$ Commented Mar 10, 2024 at 22:18

6 Answers 6

5
$\begingroup$

You can use Composition.

Longhand

Composition[#, Exponent[#, Variables[expr]] &] & /@ {f1, f2}

Shorthand

#@*(Exponent[#, Variables[expr]] &) & /@ {f1, f2}

Both give

{f1@*(Exponent[#1, Variables[expr]] &), 
 f2@*(Exponent[#1, Variables[expr]] &)}

Hope this helps.

$\endgroup$
2
  • $\begingroup$ Yes, this is the only code in this thread that is shorter than mine. Although the output is not exactly the same it is equivalent to the requested from. $\endgroup$ Commented Mar 11, 2024 at 10:34
  • 1
    $\begingroup$ +1. It may not matter for the present context, but note that there are subtle evaluation differences between the two forms which might be important when working with symbolic expressions. e.g. ((d |-> (d[g[#]] &))@Hold)[x] vs (#@*(g[#] &) & @ Hold)[x]. $\endgroup$ Commented Mar 11, 2024 at 14:20
4
$\begingroup$
Table[{Exponent[#, Variables[expr]]} & /. List -> f, {f, {f1, f2}}]

(* {f1[Exponent[#1, Variables[expr]]] &, 
 f2[Exponent[#1, Variables[expr]]] &} *)

$\endgroup$
5
  • 1
    $\begingroup$ No need for the ReplaceAll indirection. Just do Table[f@Exponent[#, Variables[expr]] &, {f, {f1, f2}}] $\endgroup$ Commented Mar 10, 2024 at 19:49
  • 3
    $\begingroup$ @lericr: Wrong result. Who could upvote a comment without even checking it provides a correct result? $\endgroup$ Commented Mar 10, 2024 at 20:06
  • 2
    $\begingroup$ @lericr That results in {f[Exponent[#1, Variables[expr]]] &, f[Exponent[#1, Variables[expr]]] &} - I don't fully understand why it doesn't work though. $\endgroup$ Commented Mar 10, 2024 at 20:17
  • $\begingroup$ Yep, my bad. That always happens when I try to reply without having MMA in front of me. It's the HoldAll attribute that causes the problem, I think. $\endgroup$ Commented Mar 10, 2024 at 22:19
  • $\begingroup$ @lericr Seems right, since this also works: ReleaseHold@ Table[Evaluate@f@Hold@Exponent[#, Variables[expr]] &, {f, {f1, f2}}] $\endgroup$ Commented Mar 10, 2024 at 22:31
4
$\begingroup$

If you literally just want shorter, you can just use a different version of Function:

#@Exponent[#, Variables[expr]] & & /@ {f1, f2}
$\endgroup$
5
  • $\begingroup$ Again, the & is not at the position as requested. It is easy to overlook. ]] &] instead of ]] ]&. $\endgroup$ Commented Mar 11, 2024 at 10:18
  • $\begingroup$ dang it. I've updated. I thought the parens would make no difference so added for clarity, and then just visually overlooked the discrepancy. $\endgroup$ Commented Mar 11, 2024 at 15:17
  • $\begingroup$ Actually, it does work with parens if you do it this way: (#@Exponent[#, Variables[expr]] &) & /@ {f1, f2}. It's early and maybe I need more coffee, but I'm not really sure why this way works but my original doesn't. $\endgroup$ Commented Mar 11, 2024 at 15:21
  • $\begingroup$ Yes, now it is correct. $\endgroup$ Commented Mar 11, 2024 at 15:25
  • $\begingroup$ Oh, I'm an idiot. I see what was wrong with the parens now. Not sure what I was thinking. $\endgroup$ Commented Mar 11, 2024 at 15:31
3
$\begingroup$

A dirty alternative:

ComapApplyPureFunction[funcs_?VectorQ, pf_Function] := Module[{strpf},
strpf = StringDelete[ToString[pf], "&"];
ToExpression[#1 <> #2 & @@@ 
Thread[{ToString@#2@#1 & @@@ Thread[{strpf, ToString /@ funcs}], 
Array["&" &, Length@funcs]}]]]

Testing ComapApplyPureFunction:

ComapApplyPureFunction[{f1, f2}, Exponent[#, Variables[expr]] &]

(*{f1[Exponent[#1, Variables[expr]]] &, f2[Exponent[#1, Variables[expr]]] &}*)

Addendum:

Perhaps using Function instead of an anonymous function will allow you to implement what you are looking for in a more concise way. The following example can be useful:

expr = x^2 + 2  x + 1;

With[{f1 = #^2 &, f2 = #^3 &}, ReleaseHold@#2@#1 & @@@ 
Thread[{HoldForm[Function[x, Exponent[x, Variables[x]]]@expr], {f1, f2}}]]

(*{{4}, {8}}*)
$\endgroup$
3
  • $\begingroup$ These are all the wrong ones :-) $\endgroup$ Commented Mar 10, 2024 at 19:46
  • $\begingroup$ @azerbajdzan See the update, please! :-) $\endgroup$ Commented Mar 10, 2024 at 20:26
  • 2
    $\begingroup$ Nice, but is in no way more concise (I mean with the definition of ComapApplyPureFunction). Anyway (+1). $\endgroup$ Commented Mar 10, 2024 at 20:37
3
$\begingroup$

I think that in Version 14, you would be able to write

fn = Comap[{f1, f2}]@*(Exponent[#, Variables[expr]] &)

With this definition, you would the have

expr = a + b + c
(* a + b + c *)

fn[expr]
(* Comap[{f1, f2}][{1, 1, 1}] *)

which I think would be what you wanted (if Comap were defined).

I haven't tested this, as I haven't installed version 14 yet.

$\endgroup$
1
  • $\begingroup$ Comap is experimental in version 14. Its behavior may change in future versions. $\endgroup$ Commented Mar 10, 2024 at 23:30
2
$\begingroup$

Although not more concise, it might be worth noting (as pointed out by Wagner, p196) that a pure function may be made listable using Function[] syntax (but not, as far as I am aware, with either #-& or d |-> syntax).

{f1, f2} // Function[x, x[Exponent[#, Variables[expr]]] &, Listable]

(* {f1[Exponent[#1, Variables[expr]]] &, f2[Exponent[#1, Variables[expr]]] &} *)

The following will also work:

myfn = Function[x, (x[Exponent[#, Variables[expr]]] &), Listable];

myfn[{f1, f2}]

(* {f1[Exponent[#1, Variables[expr]]] &, f2[Exponent[#1, Variables[expr]]] &} *)

But (as again pointed out by Wagner), the following won't, as the listable attribute is 'stripped off' when fn is replaced by its ownvalue during evaluation:

fn = Function[x, (x[Exponent[#, Variables[expr]]] &)];
SetAttributes[fn, Listable]
fn[{f1, f2}]

(* {f1, f2}[Exponent[#1, Variables[expr]]] & *)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.