9
$\begingroup$

I'm experimenting with the Through function. I suspect there is a way to use that function to obtain both the mean and difference of two values. But this doesn't work:

 Through[{Mean, Subtract}[1175., 247.]]

It reports the error:

Mean::argx: Mean called with 2 arguments; 1 argument is expected.

The corollary raises a similar error:

 Through[{Mean, Subtract}[{1175., 247.}]]

Subtract::argr: Subtract called with 1 argument; 2 arguments are expected.

I think the problem is caused by the Mean function taking only one argument as a list of values, whereas Subtract takes its arguments as two separate values. It reminds me of destructuring as found in other languages, hence the title. Feel free to edit that for something more descriptive.

Is there a way to do what I try? Since I'm learning the Wolfram Language, I would prefer a solution working in the general case rather that a solution specific to the Mean and Subtract functions.

$\endgroup$

4 Answers 4

9
$\begingroup$

Here is one way to do what you ask

Through[{Mean@*List, Subtract}[1175., 247.]]
(* {711., 928.}*)

This works by using Composition (in its operator form) to apply List and then Mean to the inputs.

You could also "Lift" (is that the correct functional programming term?) Subtract to operate on lists (as suggested by @LukasLang)

Through[{Mean, Apply[Subtract]}[{1175., 247.}]]
(* {711., 928.}*)
$\endgroup$
3
  • 1
    $\begingroup$ I knew there was some @... notation that would be involved. Thank @mikado. Could you ellaborate a little on the way it works? $\endgroup$ Dec 8, 2019 at 16:38
  • 2
    $\begingroup$ It might be worth to add Through[{Mean, Apply@Subtract}[1175., 247.]] as the "inverse" approach (where a list is supplied and converted to a sequence of arguments) $\endgroup$
    – Lukas Lang
    Dec 9, 2019 at 10:46
  • 1
    $\begingroup$ @Lukas, Thank you! I took the liberty of editing the Mikado's answer to quote your comment (I also fixed a small typo in the code where you wrote [1175., 247.] for [{1175., 247.}]. Feel free to revert that edit if you desagree. $\endgroup$ Dec 9, 2019 at 15:16
6
$\begingroup$

One way is to force Mean to aggregate the two arguments into a list,

Through[{Mean[{##}] &, Subtract}[1175., 247.]]

Please notice the double ##. With only one # the mean will be applied only on the first argument.

Or you can modify the call to Subtract to force it to break the list into separate arguments:

Through[{Mean, Subtract[#[[1]], #[[2]]] &}[{1175., 247.}]]
$\endgroup$
5
  • $\begingroup$ I saw something like that already. It wraps Mean in a lambda function. Am I right? $\endgroup$ Dec 8, 2019 at 16:39
  • $\begingroup$ I'm not 100% sure I know what a lambda function is... the first one operates by placing the argument 1175., 247 where the # is, so that the two numbers are placed into a list (as required by Mean). The second works the opposite, by separating the list argument into its two components (as required by Subtract). $\endgroup$
    – bill s
    Dec 8, 2019 at 16:43
  • 1
    $\begingroup$ @SylvainLeroux Mathematica's equivalent of a lambda function is referred to as a "Pure" function. See the help on Function for an explanation. $\endgroup$
    – mikado
    Dec 8, 2019 at 16:47
  • 2
    $\begingroup$ I think the first one should be Mean[{##}]& - otherwise, you will keep only the first argument $\endgroup$
    – Lukas Lang
    Dec 9, 2019 at 10:45
  • $\begingroup$ You're right @Lukas. I' editing Bill's answer with that. I add en extra explntion of the problem, since one-character edits are not allowed. Feel free to edit that if I was wrong. $\endgroup$ Dec 9, 2019 at 15:22
1
$\begingroup$

Using Comap (new in 14.0}

Comap[{Mean, Apply @ Subtract}] @ {1175., 247.}

{711., 928.}

Using ComapApply (also new in 14.0}

ComapApply[{Mean @* List, Subtract}] @ {1175., 247.}

{711., 928.}

$\endgroup$
1
$\begingroup$

Another way using Thread:

#1@{##2} & @@@ Thread[{{Mean, Apply@Subtract}, Splice@{1175., 247.}}]

(*{711., 928.}*)
$\endgroup$

Your Answer

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

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