Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

May I write {x,a,b}//Do[...,#]& instead of Do[...,{x,a,b}]?

I'm in love with Ruby. In this language all core functions are actually methods. That's why I prefer postfix notation – when the data, which I want to process is placed left from the body of anonymous processing function, for example: array.map{...}. I believe, that it has advantages in how easy is this code to read.

But Mathetica, being functional (yeah, it can be procedural if you want) dictates a style, where Function name is placed left from the data. As we can see in its manuals, // is used only when it's some simple Function, without arguments, like list // MatrixForm. When Function needs a lot of arguments, people who wrote manuals, use syntax F[data].
It would be okay, but my problem is the case F[f,data], for example Do[function, {x, a, b}]. Most of Mathematica functions (if not all) have arguments in exactly this order – [function, data], not [data, function]. As I prefer to use pure functions to keep namespace clean instead of creating a lot of named functions in my notebook, the argument function can be too big – so big, that argument data would be placed on the 5-20th line of code after the line with Function call.

This is why sometimes, when evil Ruby nature takes me under control, I rewrite such functions in postfix way:

Do[f (x), {x, a, b}]\n{x, a, b} // Do[f (x), #] &

Because it's important for me, that pure function (potentially big code) is placed right from processing data. Yeah I do it and I'm happy. But there are two things:

  1. this causes Mathematica's highlighting parser problem: the x in postfix notation is highlighted with blue color, not turquoise;
  2. everytime when I look into Mathematica manuals, I see examples like this one: Do[x[[i]] = (v[[i]] - U[[i, i + 1 ;; n]].x[[i + 1 ;; n]])/ U[[i, i]], {i, n, 1, -1}];, which means... hell, they think it's easy to read/support/etc.?!

So these two things made me ask this question here: am I so bad boy, that use my Ruby-style, and should I write code like these guys do, or is it OK, and I don't have to worry, and should write as I like to?

like image 356
Nakilon Avatar asked Aug 17 '11 15:08

Nakilon


People also ask

What does a * b do in MATLAB?

C = A*B is the linear algebraic product of the matrices A and B . The number of columns of A must equal the number of rows of B .

What does X a B mean in MATLAB?

x = A \ B solves the system of linear equations A*x = B . The matrices A and B must have the same number of rows. MATLAB® displays a warning message if A is badly scaled or nearly singular, but performs the calculation regardless. If A is a scalar, then A\B is equivalent to A.


2 Answers

The style you propose is frequently possible, but is inadvisable in the case of Do. The problem is that Do has the attribute HoldAll. This is important because the loop variable (x in the example) must remain unevaluated and be treated as a local variable. To see this, try evaluating these expressions:

x = 123;

Do[Print[x], {x, 1, 2}]
(* prints 1 and 2 *)

{x, 1, 2} // Do[Print[x], #]&
(* error: Do::itraw: Raw object 123 cannot be used as an iterator.
   Do[Print[x], {123, 1, 2}]
*)

The error occurs because the pure function Do[Print[x], #]& lacks the HoldAll attribute, causing {x, 1, 2} to be evaluated. You could solve the problem by explicitly defining a pure function with the HoldAll attribute, thus:

{x, 1, 2} // Function[Null, Do[Print[x], #], HoldAll]

... but I suspect that the cure is worse than the disease :)

Thus, when one is using "binding" expressions like Do, Table, Module and so on, it is safest to conform with the herd.

like image 169
WReach Avatar answered Sep 16 '22 18:09

WReach


I think you need to learn to use the styles that Mathematica most naturally supports. Certainly there is more than one way, and my code does not look like everyone else's. Nevertheless, if you continue to try to beat Mathematica syntax into your own preconceived style, based on a different language, I foresee nothing but continued frustration for you.

Whitespace is not evil, and you can easily add line breaks to separate long arguments:

Do[
  x[[i]] = (v[[i]] - U[[i, i + 1 ;; n]].x[[i + 1 ;; n]]) / U[[i, i]]
  , {i, n, 1, -1}
];

This said, I like to write using more prefix (f @ x) and infix (x ~ f ~ y) notation that I usually see, and I find this valuable because it is easy to determine that such functions are receiving one and two arguments respectively. This is somewhat nonstandard, but I do not think it is kicking over the traces of Mathematica syntax. Rather, I see it as using the syntax to advantage. Sometimes this causes syntax highlighting to fail, but I can live with that:

f[x] ~Do~ {x, 2, 5} 

When using anything besides the standard form of f[x, y, z] (with line breaks as needed), you must be more careful of evaluation order, and IMHO, readability can suffer. Consider this contrived example:

{x, y} // # + 1 & @@ # &

I do not find this intuitive. Yes, for someone intimate with Mathematica's order of operations, it is readable, but I believe it does not improve clarity. I tend to reserve // postfix for named functions where reading is natural:

Do[f[x], {x, 10000}] //Timing //First
like image 39
Mr.Wizard Avatar answered Sep 17 '22 18:09

Mr.Wizard