Description
When a long parenthesized expression containing addition or subtraction is followed by multiplication or division, the formatted result can be confusing. These are some examples:
fn main() {
let dv = (2. * m * l * dtheta * dtheta * theta.sin()
+ 3. * m * g * theta.sin() * theta.cos()
+ 4. * u
- 4. * b * v)
/ (4. * (M + m) - 3. * m * theta.cos().powi(2));
let ddtheta = (-3. * m * l * dtheta * dtheta * theta.sin() * theta.cos()
- 6. * (M + m) * g * theta.sin()
- 6. * (u - b * v) * theta.cos())
/ (4. * l * (m + M) - 3. * m * l * theta.cos().powi(2));
}
fn main() {
let V: Array2<_> = (((&lq + &vi).mapv(f64::exp) - &q) * (mi_minus_mi_t).mapv(f64::cos)
- ((&lq - &vi).mapv(f64::exp) - &q) * (mi_plus_mi_t).mapv(f64::cos))
* e.as_row()
* e.as_column()
* 0.5;
}
fn main() {
dVdm.slice_mut(s![.., .., j]).assign(
&(((Array2::zeros((d, d)) + u.as_column() - u.as_row()) * &U1
+ (Array2::<f64>::zeros((d, d)) + u.as_column() + u.as_row()) * &U2)
* e.as_column()
* e.as_row()),
);
}
fn main() {
{
{
{
{
{
let LdXi: Array2<_> = (dmahai
+ kdX.slice(s![.., i, d]).into_column()
+ kdX.slice(s![.., j, d]))
* &L;
}
}
}
}
}
}
In all these examples, there is a multiplication or division of a parenthesized expression containing +
or -
. The *
or /
is indented by the same amount as the +
or -
, suggesting that it's at the same level, which by order of operations would mean that only the last expression would be multiplied/divided. It's not obvious that the +
or -
are in fact inside a parenthesized expression.
A relatively small change that would help would be to increase the indentation of the expressions inside the parentheses, like this:
fn main() {
let dv = (2. * m * l * dtheta * dtheta * theta.sin()
+ 3. * m * g * theta.sin() * theta.cos()
+ 4. * u
- 4. * b * v)
/ (4. * (M + m) - 3. * m * theta.cos().powi(2));
let ddtheta = (-3. * m * l * dtheta * dtheta * theta.sin() * theta.cos()
- 6. * (M + m) * g * theta.sin()
- 6. * (u - b * v) * theta.cos())
/ (4. * l * (m + M) - 3. * m * l * theta.cos().powi(2));
}
fn main() {
let V: Array2<_> = (((&lq + &vi).mapv(f64::exp) - &q) * (mi_minus_mi_t).mapv(f64::cos)
- ((&lq - &vi).mapv(f64::exp) - &q) * (mi_plus_mi_t).mapv(f64::cos))
* e.as_row()
* e.as_column()
* 0.5;
}
fn main() {
dVdm.slice_mut(s![.., .., j]).assign(
&(((Array2::zeros((d, d)) + u.as_column() - u.as_row()) * &U1
+ (Array2::<f64>::zeros((d, d)) + u.as_column() + u.as_row()) * &U2)
* e.as_column()
* e.as_row()),
);
}
fn main() {
{
{
{
{
{
let LdXi: Array2<_> = (dmahai
+ kdX.slice(s![.., i, d]).into_column()
+ kdX.slice(s![.., j, d]))
* &L;
}
}
}
}
}
}
I think a better solution would be to make the parentheses more obvious by adding new lines after the opening parenthesis and before the closing parenthesis, with something like this:
fn main() {
let dv = (
2. * m * l * dtheta * dtheta * theta.sin()
+ 3. * m * g * theta.sin() * theta.cos()
+ 4. * u
- 4. * b * v
) / (4. * (M + m) - 3. * m * theta.cos().powi(2));
let ddtheta = (
-3. * m * l * dtheta * dtheta * theta.sin() * theta.cos()
- 6. * (M + m) * g * theta.sin()
- 6. * (u - b * v) * theta.cos()
) / (4. * l * (m + M) - 3. * m * l * theta.cos().powi(2));
}
fn main() {
let V: Array2<_> = (
((&lq + &vi).mapv(f64::exp) - &q) * (mi_minus_mi_t).mapv(f64::cos)
- ((&lq - &vi).mapv(f64::exp) - &q) * (mi_plus_mi_t).mapv(f64::cos)
)
* e.as_row()
* e.as_column()
* 0.5;
}
fn main() {
dVdm.slice_mut(s![.., .., j]).assign(&(
(
(Array2::zeros((d, d)) + u.as_column() - u.as_row()) * &U1
+ (Array2::<f64>::zeros((d, d)) + u.as_column() + u.as_row()) * &U2
)
* e.as_column()
* e.as_row()
));
}
fn main() {
{
{
{
{
{
let LdXi: Array2<_> = (
dmahai
+ kdX.slice(s![.., i, d]).into_column()
+ kdX.slice(s![.., j, d])
) * &L;
}
}
}
}
}
}
Although doing so is not necessary for clarity, if the closing parenthesis is moved to a new line, we could eliminate some of the extra new lines, so the middle examples would become this:
fn main() {
let V: Array2<_> = (
((&lq + &vi).mapv(f64::exp) - &q) * (mi_minus_mi_t).mapv(f64::cos)
- ((&lq - &vi).mapv(f64::exp) - &q) * (mi_plus_mi_t).mapv(f64::cos)
)
* e.as_row() * e.as_column() * 0.5;
}
fn main() {
dVdm.slice_mut(s![.., .., j]).assign(&(
(
(Array2::zeros((d, d)) + u.as_column() - u.as_row()) * &U1
+ (Array2::<f64>::zeros((d, d)) + u.as_column() + u.as_row()) * &U2
)
* e.as_column() * e.as_row()
));
}
or this:
fn main() {
let V: Array2<_> = (
((&lq + &vi).mapv(f64::exp) - &q) * (mi_minus_mi_t).mapv(f64::cos)
- ((&lq - &vi).mapv(f64::exp) - &q) * (mi_plus_mi_t).mapv(f64::cos)
) * e.as_row() * e.as_column() * 0.5;
}
fn main() {
dVdm.slice_mut(s![.., .., j]).assign(&(
(
(Array2::zeros((d, d)) + u.as_column() - u.as_row()) * &U1
+ (Array2::<f64>::zeros((d, d)) + u.as_column() + u.as_row()) * &U2
) * e.as_column() * e.as_row()
));
}