# How can I rewrite my code to make it simpler?

Two months ago,I written a function IRobot to caculate the $I_{xx},I_{yy},I_{zz}$ and $I_{xy},I_{xz},I_{yz}$,shown as below:

  IRobot[IStyle_String, ρ_, VaribleRange_List] := Module[
{IRobotResult},
IRobotResult =
Which[
IStyle == "xx", Integrate[ρ (y^2 + z^2),
{z, VaribleRange[[1, 1]], VaribleRange[[1, 2]]},
{y, VaribleRange[[2, 1]], VaribleRange[[2, 2]]},
{x, VaribleRange[[3, 1]], VaribleRange[[3, 2]]}],
IStyle == "yy", Integrate[ρ (x^2 + z^2),
{z, VaribleRange[[1, 1]], VaribleRange[[1, 2]]},
{y, VaribleRange[[2, 1]], VaribleRange[[2, 2]]},
{x, VaribleRange[[3, 1]], VaribleRange[[3, 2]]}],
IStyle == "zz", Integrate[ρ (x^2 + y^2),
{z, VaribleRange[[1, 1]], VaribleRange[[1, 2]]},
{y, VaribleRange[[2, 1]], VaribleRange[[2, 2]]},
{x, VaribleRange[[3, 1]], VaribleRange[[3, 2]]}],
IStyle == "xy", Integrate[ρ x y,
{z, VaribleRange[[1, 1]], VaribleRange[[1, 2]]},
{y, VaribleRange[[2, 1]], VaribleRange[[2, 2]]},
{x, VaribleRange[[3, 1]], VaribleRange[[3, 2]]}],
IStyle == "xz", Integrate[ρ x z,
{z, VaribleRange[[1, 1]], VaribleRange[[1, 2]]},
{y, VaribleRange[[2, 1]], VaribleRange[[2, 2]]},
{x, VaribleRange[[3, 1]], VaribleRange[[3, 2]]}],
IStyle == "yz", Integrate[ρ y z,
{z, VaribleRange[[1, 1]], VaribleRange[[1, 2]]},
{y,VaribleRange[[2, 1]], VaribleRange[[2, 2]]},
{x,VaribleRange[[3, 1]], VaribleRange[[3, 2]]}]
]
]


And I can use it correctly.

 IRobot["xx", ρ, {{-h1, 0}, {-r1, r1}, {-L1 - Sqrt[r1^2 - y^2], Sqrt[r1^2 - y^2]}}]
(*===>*)
1/12 h1 r1 (4 h1^2 (2 L1 + \[Pi] r1) + r1^2 (8 L1 + 3 \[Pi] r1)) ρ


However,I would like to simplify my code by Similarity,my trail as below:

 Flatten /@Thread@List[{z, y, x},
Apply[Part[VaribleRange, ##] &, Table[{i, j}, {i, 1, 3}, {j, 1, 2}], {2}]]
(*==>*)
{{z, VaribleRange[[1, 1]], VaribleRange[[1, 2]]},
{y, VaribleRange[[2, 1]], VaribleRange[[2, 2]]},
{x, VaribleRange[[3, 1]], VaribleRange[[3, 2]]}}


## Trial 1

IRobot[IStyle_String, ρ_, VaribleRange_List] := Module[
{IRobotResult,intlist},
intlist=
Apply[Part[VaribleRange, ##] &, Table[{i, j}, {i, 1, 3}, {j, 1, 2}], {2}]];
IRobotResult =
Which[
IStyle == "xx", Integrate[ρ (y^2 + z^2),intlist],
IStyle == "yy", Integrate[ρ (x^2 + z^2),intlist],
IStyle == "zz", Integrate[ρ (x^2 + y^2),intlist],
IStyle == "xy", Integrate[ρ x y,intlist],
IStyle == "xz", Integrate[ρ x z,intlist],
IStyle == "yz", Integrate[ρ y z,intlist]
]
]


Unfortunately,it failed.

## Trail2

 IRobot[IStyle_String, ρ_, VaribleRange_List] := Module[
{IRobotResult,intlist},
intlist[z_,y_,x_,range_]:=
Apply[Part[range, ##] &, Table[{i, j}, {i, 1, 3}, {j, 1, 2}], {2}]];
IRobotResult =
Which[
IStyle == "xx", Integrate[ρ (y^2 + z^2),intlist[z,y,x,VaribleRange]],
IStyle == "yy", Integrate[ρ (x^2 + z^2),intlist[z,y,x,VaribleRange]],
IStyle == "zz", Integrate[ρ (x^2 + y^2),intlist[z,y,x,VaribleRange]],
IStyle == "xy", Integrate[ρ x y,intlist[z,y,x,VaribleRange]],
IStyle == "xz", Integrate[ρ x z,intlist[z,y,x,VaribleRange]],
IStyle == "yz", Integrate[ρ y z,intlist[z,y,x,VaribleRange]]
]
]


Also it ends in failure!

## Or

I want to by

 Which@@(
Flatten@{IStyle == #1, Integrate[ρ #2, intlist[z,y,x,VaribleRange]]} & @@@
{{"xx", (y^2 + z^2)}, {"yy", (x^2 + z^2)}, {"zz", (x^2 + y^2)},
{"xy", x y}, {"xz", x z}, {"yz", y z}})
(*==>*)


to achieve

  Which[
IStyle == "xx", Integrate[ρ (y^2 + z^2),intlist[z,y,x,VaribleRange]],
IStyle == "yy", Integrate[ρ (x^2 + z^2),intlist[z,y,x,VaribleRange]],
IStyle == "zz", Integrate[ρ (x^2 + y^2),intlist[z,y,x,VaribleRange]],
IStyle == "xy", Integrate[ρ x y,intlist[z,y,x,VaribleRange]],
IStyle == "xz", Integrate[ρ x z,intlist[z,y,x,VaribleRange]],
IStyle == "yz", Integrate[ρ y z,intlist[z,y,x,VaribleRange]]
]


So my question is why and how to revise it.

## Proposal

I recommend something like this:

IRobot2[IStyle_String, ρ_, VaribleRange_List] :=
Block[{x, y, z},
With[{expr =
Switch[IStyle,
"xx", (y^2 + z^2),
"yy", (x^2 + z^2),
"zz", (x^2 + y^2),
"xy", x y,
"xz", x z,
"yz", y z
]},
Integrate[ρ expr, ##] & @@ Join[{{z}, {y}, {x}}, VaribleRange, 2]
]
]


The Block is there to localize x, y, z to prevent these Symbols from incorrectly evaluating while they are manipulated, before passing them to Integrate using SlotSequence and Apply.

## Code review

I first posted my recommendation above because it is faster for me to do so than to analyze and debug your attempts that did not work but as requested I will do the latter now.

The Trial 1 code throws this error when used:

Integrate::ilim: Invalid integration variable or limit(s) in {{z,-h1,0},{y,-r1,r1},{x,-L1-Sqrt[r1^2-Power[<<2>>]],Sqrt[r1^2-y^2]}}. >>

That should draw your attention to that part of the code, meaning intlist and how it is used in Integrate. The problem arises because intlist is (indeed) a list, whereas the parameters of Integrate need to be a sequence, i.e. 1, 2, 3 rather than {1, 2, 3}. In my own code above I used SlotSequence for this because it is more universal and I could not remember off-hand the way in which Integrate evaluated its arguments. However your Trial 1 code can be corrected by wrapping the existing right-hand-side definition of intlist in Sequence @@ ( . . . ), or a bit more concisely:

intlist = Sequence @@ (
Flatten /@ Thread@{ {z, y, x}, Array[VaribleRange[[##]] &, {3, 2}] }
)


I stated that using SlotSequence is more robust. Here is an example where it is needed:

iterSeq = Sequence[{x, 5}, {i, x}];
Table[x + i^2, iterSeq]              (*failure*)

iterList = {{x, 5}, {i, x}} ;
Table[x + i^2, ##] & @@ iterList     (*success*)


(Attributes[Table] includes HoldAll and iterSeq is not evaluated.)

Trial 2 can be corrected in the same manner.

The second attempt at Trial 2 was clever but you didn't quite get it right. Which needs input in the form of:

Which[
test1, value1,
test2, value2,
. . .
]


Which[
{test1, value1},
{test2, value2},
. . .
]


Also you are not doing anything to Hold the "value" expressions, therefore Integrate will evaluate prematurely.

To correct these problems we need to Flatten the entire expression, not the sub-lists, and we need to add expression holding:

Which @@ Flatten[
{IStyle == #1, Unevaluated @ Integrate[ρ #2, intlist[z, y, x, VaribleRange]]} & @@@
{{"xx", (y^2 + z^2)},
{"yy", (x^2 + z^2)},
{"zz", (x^2 + y^2)},
{"xy", x y},
{"xz", x z},
{"yz", y z}}
]


Unevaluated should suffice here (I did not actually test this section of code) but if not you could use Hold in its place, then add a ReleaseHold outside of Which.

• ♦,+1,Perfect!This solution make the function IRobot become more refine and elegant.By the way,I would like to why my trail cannot work normally or can you give me some suggestion about writing program.Thanks sincerely!
– user8336
Jul 10, 2014 at 8:11
• @tangshutao Comment again on this answer some time tomorrow to remind me, and I'll try to explain where your attempt went wrong. I need to sleep now. Jul 10, 2014 at 8:18
• ♦,Ok,thanks ror your warm help.May you have a good dream!
– user8336
Jul 10, 2014 at 8:26
• @tangshutao Update complete. Jul 10, 2014 at 19:18
• ♦.Wow,Thanks very much.From your reputation rank,I know you are a Mathematica expert!!
– user8336
Jul 11, 2014 at 0:04