Mathematica is a symbolic language. I think that this makes it unavoidable that is very easy to write an expression which is perfectly valid, yet not what you mean.
Some would say that it is a to edged sword: it is powerful and it is easy to get a lot done in only a few lines of code. But it is also easy to shoot yourself in the foot.
Part of learning to work with Mathematica is learning to program in a way that makes such errors jump out as fast as possible.
In this case, I'll repeat what I said many many times: unless you are experienced with Mathematica, never ever use For
! For
is evil. Really. To make myself clear, I am not speaking against procedural programming. I am speaking specifically against For
.
In the vast majority of cases, For
can be directly replaced with Do
, which is easier to read, easier to write without mistakes (!), and localizes its iterator. If Do
is not general enough, use While
. I only use For
when translating code from other languages, and even them rarely. First I borrow the for
-based code literally, then I gradually rewrite it to be faster and more Mathematica-like, checking at each step that the result doesn't change.
About f[x,y] := x+y
This is not only valid syntax, but useful and necessary too. It is indeed a mistake which is easy to make. But the front end helps us with it: the syntax colouring is clearly different between f[x_, y_] := x+y
, f[x_, y_] = x+y
and f[x, y] = x+y
. Pay attention to the syntax colouring: black, blue or greenish-blue. It can save you from many mistakes. This sort of syntax highlighting is also done by the IDEA plugin, which can also warn you about common mistakes the front end won't show quite as clearly (e.g. newline as multiplication).
Some criticize Mathematica for being cryptic and hard to understand. It is true that it is easy to write such code with all the different yet equivalent notations and powerful operators. But you can use this notational flexibility to your advantage, to make code more readable, although it takes practice and discipline. Try to develop a consistent style that you are comfortable with and stick to it. For example, I think that f@g@h[x, y]
is objectively easier to read than f[g[h[x,y]]]
because it eliminates the need to match up brackets. There is also the postfix approach, e.g. h[x,y] // doThis // doThat // Map[f] // Riffle[#, x]& // StringJoin
. This can be very readable because the operations are listed in the order they will be performed.
We could also mix all these syntaxes and use all of @
, //
and maybe even ~f~
within the same line. But we don't have to as it would likely hurt readability. It's the same with doing a lot in one line: Mathematica is famous for compact one liners, but you don't have to overdo it. Feel free to break down the code to manageable sized parts.
I am talking about readability because I think that this is the key to the problems you mentioned. If you stick to a consistent style which you are well practiced in and which is designed to enhance readability, such mistakes will jump out visually.
All this said, I do agree that a lint tool could be quite useful, but probably not very easy to write.