# Automatic Handling of bracket vs double-bracket errors

In the thick of programming, I often make bracket/double-bracket errors, such as

or

Unfortunately, in the former the error message

Part::pspec: Part specification A is neither an integer nor a list of integers.

doesn't uniquely specify and localize the problem in a long program, and in the latter no error message is generated at all. (If any Wolfram employees are reading this, please consider generating a more informative error message for Print[["hello"]] that flags that Print was bracketed as a list instead of a function.)

I couldn't think of a reason why Mathematica necessarily needs different kinds of brackets for functions and lists. The bracket/double-bracket convention lets you distinguish functions from lists by context, but it decreases readability of complicated expressions and makes me prone to coding mistakes. Note added: Albert Retey commented that if f is defined as a pure function via f=Function[x,x^2] (rather than as f[x_]=x^2) then f[1] and f[[1]] are simultaneously defined and nonequal unless x=1. This gave the example I hadn't thought possible and (to make matters worse) provided a bracket/double bracket hazard which won't generate even a cryptic error message.

In the case of functions, I partially solved the problem by manually applying the following function declaration to all native functions (except Function[ ] itself) and to user-defined non-pure functions:

Attributes[DeclareFunction] = {HoldAll};
DeclareFunction::HeadInvalid = "The Argument 1 of DeclareFunction
must have a head other than Function.";
DeclareFunction[f_] :=
Block[{prot},
prot = MemberQ[Attributes[f], Protected];
Unprotect[f];
f::FunctionAsList = "Changed 1[[ ]] to 1[ ]";
f[[x__]] ^:= (Message[f::FunctionAsList, f]; f[x]);
If[prot, Protect[f]]]]

After DeclareFunction is applied to a function f, the offending double-brackets are automatically interpreted as single-brackets and a warning message is given, pointing out the function with the offending double-bracket: After

DeclareFunction[Print]

the command

Print[["Hello"]]

yields

Print::FunctionAsList: Changed Print[[ ]] to Print[ ] >>
Hello

However,

1. Is there a way to write an analogous DeclareList command? Once DeclareList[list] is invoked, list[ ] should be automatically converted to list[[ ]] with a warning message given.
2. It would also be nice to find an unobtrusive way to invoke DeclareFunction automatically any time a new function is defined using the usual f[x_]:= method. A complication is that if I modify the function SetDelayed[ ] then I run into issues of the modification recursing on itself instantly as it is made.

Any ideas?

• Not an answer to your question, but you may find this useful: type ESC [[ ESC to get a special double-bracket character which is (in my opinion) much more readable. I always use this character. Since I find ESC [[ ESC too time consuming to type, I set up Ctrl-[ as a keyboard shortcut to type it more easily. Commented Dec 26, 2016 at 9:30
• "I couldn't think of a reason why Mathematica necessarily needs different kinds of brackets for functions and lists." Have you never used indexed variables; i.e., a[1], a[2], ....? Both a[1] = 42 and a[[1]] = 42 are valid and useful assignment expressions that mean very different things, and are an example of the why Mathematica has single and double bracket notation. Commented Dec 26, 2016 at 9:46
• Note that someList[[i]] is just syntactic sugar for Part[someList, i] Commented Dec 26, 2016 at 9:49
• "I infer that Mathematica won't let me simultaneously use the variable a as a list and a function" - you infer right. If a is an indexed variable or a function, you use []. Also, it is entirely possible to use Part[] on "non-atomic heads" (see e.g. this), and it is possible to have a list as a head, e.g. Through[{Sin, Cos}[30 °]]. Commented Dec 26, 2016 at 10:19
• here is an example where [] vs. [[]] makes a difference: f = Function[x, x^2]. Try f[1] vs. f[[1]], both are valid operations but in this case return different results Commented Dec 26, 2016 at 10:29