Manipulating Tables in Mathematica - wolfram-mathematica

The indexing scheme I'm trying seems so simple (but wrong)...
data is the name of the table of data imported from an Oracle database.
I tried moving pointer outside of List[....] and successfully tested (In[100]).
I'm new to Mathematica... been going in little circles using Wolfram help tool.
Can someone get me out of rut and point me to a better method?
In[100]:= dat[n_, m_] := data[[n, m]];
dat[1, 3]
Out[102]= 0.70388
In[104]:= List[dat[n, 3], {n, 1, Length[data]}]
During evaluation of In[104]:= Part::pkspec1: The expression n cannot be used as a part specification.
Out[104]= {{{0.00499, 0.00037, 0.70388, 0.00526, 0.00008,
0.00006}, {0.00176, 0.00006, 0.31315, 0.00129, 0.01142,
0.00016}, {0.00201, 0.00013, 0.32143, 0.00158, 0.01544,
0.00041}, {0.00507, 0.00015, 0.7228, 0.00263, 0.00002,
0.00001}, {0.00516, 0.00011, 0.72381, 0.0028, 0.00001,
0.00001}, {0.00203, 0.00019, 0.31207, 0.00297, 0.01143,
0.00044}, {0.00138, 0.00024, 0.26769, 0.00349, 0.00098,
0.00018}, {0.00182, 0.00007, 0.31365, 0.00129, 0.01383,
0.0002}, {0.00531, 0.00009, 0.72048, 0.00212, 0.,
0.00001}, {0.00395, 0.00019, 0.60555, 0.00307, 0.00047,
0.00007}, {0.0055, 0.00017, 0.72021, 0.00332, 0.00001,
0.00001}, {0.00175, 0.00016, 0.30605, 0.00313, 0.00933,
0.00035}, {0.00198, 0.00009, 0.29497, 0.00135, 0.01019,
0.00023}, {0.00545, 0.00016, 0.72135, 0.00249, 0.00001,
0.00001}, {0.00179, 0.00038, 0.33179, 0.00791, 0.01627,
0.00097}, {0.00211, 0.00013, 0.31377, 0.00171, 0.01289,
0.00031}, {0.00515, 0.00057, 0.7213, 0.00766, 0.00006,
0.00018}, {0.00543, 0.00012, 0.72163, 0.0025, 0.,
0.00001}, {0.00395, 0.00011, 0.72095, 0.00267, 0.00001,
0.00001}, {0.00548, 0.00014, 0.72343, 0.00278, 0., 0.00001}}[[n,
3]], {n, 1, 20}}

The List function is not meant to extract data in the way you're attempting to do here. List is basically just a wrapper that indicates that whatever is inside is a list of things. If you construct a list in Mathematica using the curly brackets ({...}), you're automatically calling the List function:
FullForm[{1, 2, 3}]
which gives:
List[1, 2, 3]
Always remember that in Mathematica you're invoking named functions, even if it's not immediately obvious. For example, if you type dat[[1]], you're actually invoking the Part function. You can see the functions you're using by wrapping your code in Hold (which tells Mathematica to just keep your code in its current form) and then in FullForm (which tells Mathematica to show you how Mathematica interprets your input internally):
FullForm[Hold[ dat[[1]] ]]
This results in:
Part[dat, 1]
So if you want to understand what's happening, read up on the Part function and any linked documentation pages in the Part documentation.
As for the rest of your question: if you want to have an index run over a range, you can use the Table function. This way your code should work:
Table[dat[n, 3], {n, 1, Length[data]}]
However, I wouldn't even bother with the definition you put on the top. You can access the elements of your data using Spans (look up that function in the documentation. Spans are abbreviated with the symbols ;;) and All like this:
data[[All, 3]]
or:
data[[1 ;; Length[data], 3]]
I would suggest reading these parts of the documentation (you can find them under the Mathematica documentation under F1 as well as using the following online links):
https://reference.wolfram.com/language/tutorial/ManipulatingElementsOfLists.html
https://reference.wolfram.com/language/ref/Part.html
https://reference.wolfram.com/language/ref/Span.html
https://reference.wolfram.com/language/ref/Take.html
https://reference.wolfram.com/language/ref/Table.html

Related

In Mathematica, is there any elegant way to map over a list of variable names?

For example, the following rule to create a slider that edits a given variable:
EditorLine[stat_] := {
Labeled[Slider[Dynamic[stat], {1, 20, 1}],
{SymbolName[Unevaluated[stat]]}, {Left}], Dynamic[stat]}
SetAttributes[EditorLine, HoldFirst]
This works fine for EditorLine[x], but using a map - e.g., EditorLine /# {x,y,z}, gives an error because the map function evaluates the variable names and thus they are not held.
This can be done by writing EditorLine /# {Unevaluated[x],Unevaluated[y],Unevaluated[z]} but if I wanted to write repeated function calls like that I would not be using a map!
Is there any better way of doing this?
This will work too:
EditorLine /# Unevaluated[{x, y, z}]
and if you add Listable attribute, even shorter:
EditorLine[{x, y, z}]

How to disable case sensitivity in Mathematica functions?

I want to make mathematica insensitive to the functions first capital letter. For example, it accepts both "Plot" and "plot" as plotting function.
I agree with george's sentiment: "You don't want to do that." It is common practice to start user Symbols with lowercase letters which both identifies them and prevents collisions with built-ins. Nevertheless you can do this in several ways. One is just to create aliases as george also suggested, e.g.
plot = Plot;
sin = Sin;
plot[sin[x], {x, 0, 6}]
This has the advantage of working even in packages because it does not rely on the Front End. However, because these are not true aliases it will fail in some cases, e.g.:
evaluate = Evaluate;
Hold[evaluate[2 + 2]]
Hold[evaluate[2 + 2]]
Whereas the "real" function behaves like this:
Hold[Evaluate[2 + 2]]
Hold[4]
To get complete equivalence, though only in the Front End, you can use $PreRead. (Example.) You will need to build a list of rules that replace the string form of each lowercase Symbol with the uppercase string. I shall do that only for all Symbols in the System` context.
With[{rules = Thread[ToLowerCase[#] -> #] & # Names["System`*"]},
$PreRead = # /. rules &
];
Now both of these examples work:
plot[sin[x], {x, 0, 6}]
hold[evaluate[2 + 2], 3 + 4]
The latter producing:
Hold[4, 3 + 4]
This is not a direct answer to your question and I strongly advise you against redefining Mathematica functions just for the sake of the letter-case.
Nevertheless, have you seen that there is an option Match case in command completion when you go to Edit -> Preferences -> Interface?
If you turn this off, then you can type plot in the notebook and you get the correct Plot as suggestion from the autocompletion. You only have to hit enter and the correct command is inserted.

Why is Cases[] so slow here? Are there any tricks to speed it up?

While trying to paste images, I noticed that Cases[] is very slow.
To reproduce, first copy a large image to the clipboard (just press Print Screen), then evaluate the following:
In[33]:= SetSystemOptions["PackedArrayOptions" -> "UnpackMessage" -> True];
In[34]:= AbsoluteTiming[nb = NotebookGet#ClipboardNotebook[];]
Out[34]= {0.4687500, Null}
In[35]:= AbsoluteTiming[d1 = nb[[1, 1, 1, 1, 1, 1, 1]];]
Out[35]= {0., Null}
In[36]:= AbsoluteTiming[d2 = First#Cases[nb, r_RasterBox :> First[r], Infinity, 1];]
During evaluation of In[36]:= Developer`FromPackedArray::unpack: Unpacking array in call to Notebook. >>
Out[36]= {0.9375000, Null}
(I did this on Windows, not sure if the paste code is the same on other systems.)
Note that extracting the data using Cases is extremely slow compared to using Part directly, even though I explicitly tell Cases that I need only one match.
I did find out (as shown above) that Cases triggers unpacking for some reason, even though the search should stop before it reaches the packed array inside. Using a shallower level specification than Infinity might avoid unpacking.
Question: Using Cases here is both easier and more reliable than Part (what if the subexpression can appear in different positions?) Is there a way to make Cases fast here, perhaps by using a different pattern or different options?
Possibly related question: Mathematica's pattern matching poorly optimized?
(This is why I changed the Cases rule from RasterBox[data_, ___] -> data to r_RasterBox :> First[r].)
I don't have access to Mathematica right now, so what follows is untested. My guess is that Cases unpacks here because it searches depth-first, and so sees the packed array first. If this is correct, then you could use rules instead (ReplaceAll, not Replace), and throw an exception upon first match:
Module[{tag},
Catch[
nb /. r_RasterBox :> Block[{}, Throw[First[r], tag] /; True];
$Failed,
tag]
]
As I said, this is just an untested guess.
Edit 2: an approach based on shielding parts of expression from the pattern-matcher
Preamble
In the first edit (below) a rather heavy approach is presented. In many cases, one can take an alternative route. In this particular problem (and many others like it), the main problem is to somehow shield certain sub-expressions from the pattern-matcher. This can be achieved also by using rules, to temporarily replace the parts of interest by some dummy symbols.
Code
Here is a modification of Cases which does just that:
Clear[casesShielded];
casesShielded[expr_,pt_,shieldPattern_,levspec_,n_,opts:OptionsPattern[]]:=
Module[{dummy,inverseShieldingRules, shielded, i=0},
inverseShieldingRules =
If[#==={},#,Dispatch#First##]&#
Reap[shielded= expr/.(p:shieldPattern):>
With[{eval = With[{ind = ++i},Sow[dummy[ind]:>p];dummy[ind]]},
eval/;True];
][[2]];
Cases[shielded,pt,levspec,n,opts]/.inverseShieldingRules];
This version of Cases has one additional parameter shieldPattern (third one), which indicates which sub-expressions must be shielded from the pattern-matcher.
Advantages and applicability
The code above is pretty light-weight (compared to the suggestion of edit1 below), and it allows one to fully reuse and leverage the existing Cases functionality. This will work for cases when the main pattern (or rule) is insensitive to shielding of the relevant parts, which is a rather common situation (and in particular, covers patterns of the type _h, including the case at hand). This may also be faster than the application of myCases (described below).
The case at hand
Here, we need this call:
In[55]:=
(d4=First#casesShielded[nb,x_RasterBox:>First#x,
p_List/;Developer`PackedArrayQ[p],Infinity,1]);//Timing
Out[55]= {0.,Null}
and the result is of course the same as before:
In[61]:= d2===d4
Out[61]= True
Edit: an alternative Cases-like function
Motivation and code
It took me a while to produce this function, and I am not 100 percent sure it always works correctly, but here is a version of Cases which, while still working depth-first, analyzes expression as a whole before sub-expressions:
ClearAll[myCases];
myCases[expr_, lhs_ :> rhs_, upToLevel_: 1, max : (_Integer | All) : All,
opts : OptionsPattern[]] :=
Module[{tag, result, f, found = 0, aux},
With[{
mopts = FilterRules[{opts}, {Heads -> False}],
frule =
Apply[
RuleDelayed,
Hold[lhs, With[{eval = aux}, Null /; True]] /.
{aux :> Sow[rhs, tag] /; max === All,
aux :> (found++; Sow[rhs, tag])}
]
},
SetAttributes[f, HoldAllComplete];
If[max =!= All,
_f /; found >= max := Throw[Null, tag]
];
f[x_, n_] /; n > upToLevel := Null;
f[x_, n_] :=
Replace[
HoldComplete[x],
{
frule,
ex : _[___] :>
With[{ev =
Replace[
HoldComplete[ex],
y_ :> With[{eval = f[y, n + 1]}, Null /; True],
{2},
Sequence ## mopts
]},
Null /; True
]
},
{1}
]
]; (* external With *)
result =
If[# === {}, #, First##] &#
Reap[Catch[f[expr, 0], tag], tag, #2 &][[2]];
(* For proper garbage-collection of f *)
ClearAll[f];
result
]
How it works
This is not the most trivial piece of code, so here are some remarks. This version of Cases is based on the same idea I suggested first - namely, use rule-substitution semantics to first attempt the pattern-match on an entire expression and only if that fails, go to sub-expressions. I stress that this is still the depth-first traversal, but different from the standard one (which is used in most expression-traversing functions like Map, Scan, Cases, etc). I use Reap and Sow to collect the intermediate results (matches). The trickiest part here is to prevent sub-expressions from evaluation, and I had to wrap sub-expressions into HoldComplete. Consequently, I had to use (a nested version of the) Trott-Strzebonski technique (perhaps, there are simpler ways, but I wasn't able to see them), to enable evauation of rules' r.h.sides inside held (sub)expressions, and used Replace with proper level spec, accounting for extra added HoldComplete wrappers. I return Null in rules, since the main action is to Sow the parts, so it does not matter what is injected into the original expression at the end. Some extra complexity was added by the code to support the level specification (I only support the single integer level indicating the maximal level up to which to search, not the full range of possible lev.specs), the maximal number of found results, and the Heads option. The code for frule serves to not introduce the overhead of counting found elements in cases when we want to find all of them. I am using the same Module-generated tag both as a tag for Sow, and as a tag for exceptions (which I use to stop the process when enough matches have been found, just like in my original suggestion).
Tests and benchmarks
To have a non-trivial test of this functionality, we can for example find all symbols in the DownValues of myCases, and compare to Cases:
In[185]:=
And##Flatten[
Outer[
myCases[DownValues[myCases],s_Symbol:>Hold[s],#1,Heads->#2] ===
Cases[DownValues[myCases],s_Symbol:>Hold[s],#1,Heads->#2]&,
Range[0,20],
{True,False}
]]
Out[185]= True
The myCases function is about 20-30 times slower than Cases though:
In[186]:=
Do[myCases[DownValues[myCases],s_Symbol:>Hold[s],20,Heads->True],{500}];//Timing
Out[186]= {3.188,Null}
In[187]:= Do[Cases[DownValues[myCases],s_Symbol:>Hold[s],20,Heads->True],{500}];//Timing
Out[187]= {0.125,Null}
The case at hand
It is easy to check that myCases solves the original problem of unpacking:
In[188]:= AbsoluteTiming[d3=First#myCases[nb,r_RasterBox:>First[r],Infinity,1];]
Out[188]= {0.0009766,Null}
In[189]:= d3===d2
Out[189]= True
It is hoped that myCases can be generally useful for situations like this, although the performance penalty of using it in place of Cases is substantial and has to be taken into account.

Force scientific notation in tick labels of ListLogLogPlot

I am trying to custom-format tick labels on a ListLogLogPlot. By searching Mathgroup archives, it looks like the usual way to mess with tick labels is to extract them using AbsoluteOptions, run a replacement rule with the custom format, and then explicitly feed them to the plotting function with the Ticks->{...} option. However, the following doesn't work for ListLogLogPlot:
foo = ListLogLogPlot[Range[20]^3, Frame -> True];
ticks=(FrameTicks /. AbsoluteOptions[foo, FrameTicks])
Any ideas on how to deal with this?..
Edit: lots of good answers here! Accepting Mr. Wizard's since it proved to be the most concise way to solve the immediate problem at hand, but I see myself using the other methods suggested in the future.
One can use replacements to mess with the labels directly, bypassing Option/AbsoluteOptions:
ListLogLogPlot[Range[20]^3, Frame -> True] /.
(FrameTicks -> x_) :>
(FrameTicks -> (x /. {a_?NumericQ, b_Integer, s___} :>
{a, Superscript[10, Log10#b], s} ))
Thanks to Alexey Popkov this is now improved and less fragile.
Like Sjoerd, I generally prefer to write a function that computes the ticks on the fly:
PowerTicks[label_][min_, max_] := Block[{min10, max10},
min10 = Floor[Log10[min]];
max10 = Ceiling[Log10[max]];
Join[Table[{10^i,
If[label, Superscript[10, i], Spacer[{0, 0}]]}, {i, min10,
max10}],
Flatten[
Table[{k 10^i,
Spacer[{0, 0}], {0.005, 0.`}, {Thickness[0.001`]}}, {i, min10,
max10}, {k, 9}], 1]]
]
ListLogLogPlot[Range[20]^3, Frame -> True,
FrameTicks -> {{PowerTicks[True],
PowerTicks[False]}, {PowerTicks[True], PowerTicks[False]}}]
To complement Brett's answer, look at the CustomTicks package in LevelScheme. It provides two functions for generating tick marks 'LinTicksandLogTicks`, and each has a host of formatting options. Currently, it requires you to perform the logarithm yourself, i.e.
Plot[ {Log[10,Cosh[x]], Log[10, Sinh[x]]}, {x, 0, 4}, Frame -> True,
FrameTicks -> { LinTicks, LogTicks, None, None }]
gives
For a list of data, obviously you'd have to use Log[Base, data] with ListPlot, but it is workable. I have submitted a patch to Mark Caprio so that the following would do the exact same thing as above
LogPlot[ {Cosh[x], Sinh[x]}, {x, 0, 4}, Frame -> True,
FrameTicks -> { LinTicks, LogTicks, None, None }]
If the patch is accepted the old form of LogTicks would be accessible by setting the option PlotType to Linear, Logarithmic is default. The advantage of using CustomTicks is that other bases are easy
and it automatically formats it like you want.
Edit: I'd also like to point out, that CustomTicks is loadable by itself, separate from the rest of LevelScheme. And, as it is a small package, there isn't all that much additional overhead.
Looks like a bug to me. Simple calling AbsoluteOptions[foo] yields error messages. Plain old Options[foo] works fine, though.
Send an email with this code in it to support#Wolfram.com. They will be able to tell you if there's a known better workaround.

Preventing avalanche of runtime errors in Mathematica

A typical situation I run into when notebook grows beyond a couple of functions -- I evaluate an expression, but instead of correct answer I get Beep followed by dozens of useless warnings followed by "further Output of ... will be suppressed"
One thing I found useful -- use Python-like "assert" inside functions to enforce internal consistency. Any other tips?
Assert[expr_, msg_] := If[Not[expr], Print[msg]; Abort[], None]
edit 11/14
A general cause of a warning avalanche is when a subexpression evaluates to "bad" value. This causes the parent expression to evaluate to a "bad" value and this "badness" propagates all the way to the root. Built-ins evaluated along the way notice the badness and produce warnings. "Bad" could mean an expression with wrong Head, list with wrong number of elements, negative definite matrix instead of positive definite, etc. Generally it's something that doesn't fit in with the semantics of the parent expression.
One way do deal with this is to redefine all your functions to return unevaluated on "bad input." This will take care of most messages produced by built-ins. Built-ins that do structural operations like "Part" will still attempt to evaluate your value and may produce warnings.
Having the debugger set to "break on Messages" prevents an avalanche of errors, although it seems like an overkill to have it turned on all the time
As others have pointed out, there are three ways to deal with errors in a consistent manner:
correctly typing parameters and setting up conditions under which your functions will run,
dealing correctly and consistently with errors generated, and
simplifying your methodology to apply these steps.
As Samsdram pointed out, correctly typing your functions will help a great deal. Don't forget about the : form of Pattern as it is sometimes easier to express some patterns in this form, e.g. x:{{_, _} ..}. Obviously, when that isn't sufficient PatternTests (?) and Conditions (/;) are the way to go. Samdram covers that pretty well, but I'd like to add that you can create your own pattern test via pure functions, e.g. f[x_?(Head[#]===List&)] is equivalent to f[x_List]. Note, the parentheses are necessary when using the ampersand form of pure functions.
The simplest way to deal with errors generated is obviously Off, or more locally Quiet. For the most part, we can all agree that it is a bad idea to completely shut off the messages we don't want, but Quiet can be extremely useful when you know you are doing something that will generate complaints, but is otherwise correct.
Throw and Catch have their place, but I feel they should only be used internally, and your code should communicate errors via the Message facilities. Messages can be created in the same manner as setting up a usage message. I believe the key to a coherent error strategy can be built using the functions Check, CheckAbort, AbortProtect.
Example
An example from my code is OpenAndRead which protects against leaving open streams when aborting a read operation, as follows:
OpenAndRead[file_String, fcn_]:=
Module[{strm, res},
strm = OpenRead[file];
res = CheckAbort[ fcn[strm], $Aborted ];
Close[strm];
If[res === $Aborted, Abort[], res] (* Edited to allow Abort to propagate *)
]
which, Until recently, has the usage
fcn[ file_String, <otherparams> ] := OpenAndRead[file, fcn[#, <otherparams>]&]
fcn[ file_InputStream, <otherparams> ] := <fcn body>
However, this is annoying to do every time.
This is where belisarius solution comes into play, by creating a method that you can use consistently. Unfortunately, his solution has a fatal flaw: you lose support of the syntax highlighting facilities. So, here's an alternative that I came up with for hooking into OpenAndRead from above
MakeCheckedReader /:
SetDelayed[MakeCheckedReader[fcn_Symbol, symbols___], a_] :=
Quiet[(fcn[file_String, symbols] := OpenAndRead[file, fcn[#, symbols] &];
fcn[file_Symbol, symbols] := a), {RuleDelayed::"rhs"}]
which has usage
MakeCheckedReader[ myReader, a_, b_ ] := {file$, a, b} (*as an example*)
Now, checking the definition of myReader gives two definitions, like we want. In the function body, though, file must be referred to as file$. (I have not yet figured out how to name the file var as I'd wish.)
Edit: MakeCheckedReader works by not actually doing anything itself. Instead, the TagSet (/:) specification tells Mathematica that when MakeCheckedReader is found on the LHS of a SetDelayed then replace it with the desired function definitions. Also, note the use of Quiet; otherwise, it would complain about the patterns a_ and b_ appearing on the right side of the equation.
Edit 2: Leonid pointed out how to be able to use file not file$ when defining a checked reader. The updated solution is as follows:
MakeCheckedReader /:
SetDelayed[MakeCheckedReader[fcn_Symbol, symbols___], a_] :=
Quiet[(fcn[file_String, symbols] := OpenAndRead[file, fcn[#, symbols] &];
SetDelayed ## Hold[fcn[file_Symbol, symbols], a]),
{RuleDelayed::"rhs"}]
The reasoning for the change is explained in this answer of his. Defining myReader, as above, and checking its definition, we get
myReader[file$_String,a_,b_]:=OpenAndRead[file$,myReader[#1,a_,b_]&]
myReader[file_Symbol,a_,b_]:={file,a,b}
I'm coming late to the party, with an accepted answer and all, but I want to point out that definitions of the form:
f[...] := Module[... /; ...]
are very useful in this context. Definitions of this kind can perform complex calculations before finally bailing out and deciding that the definition was not applicable after all.
I will illustrate how this can be used to implement various error-handling strategies in the context of a specific case from another SO question. The problem is to search a fixed list of pairs:
data = {{0, 1}, {1, 2}, {2, 4}, {3, 8}, {4, 15}, {5, 29}, {6, 50}, {7,
88}, {8, 130}, {9, 157}, {10, 180}, {11, 191}, {12, 196}, {13,
199}, {14, 200}};
to find the first pair whose second component is greater than or equal to a specified value. Once that pair is found, its first component is to be returned. There are lots of ways to write this in Mathematica, but here is one:
f0[x_] := First # Cases[data, {t_, p_} /; p >= x :> t, {1}, 1]
f0[100] (* returns 8 *)
The question, now, is what happens if the function is called with a value that cannot be found?
f0[1000]
error: First::first: {} has a length of zero and no first element.
The error message is cryptic, at best, offering no clues as to what the problem is. If this function was called deep in a call chain, then a cascade of similarly opaque errors is likely to occur.
There are various strategies to deal with such exceptional cases. One is to change the return value so that a success case can be distinguished from a failure case:
f1[x_] := Cases[data, {t_, p_} /; p >= x :> t, {1}, 1]
f1[100] (* returns {8} *)
f1[1000] (* returns {} *)
However, there is a strong Mathematica tradition to leave the original expression unmodified whenever a function is evaluated with arguments outside of its domain. This is where the Module[... /; ...] pattern can help out:
f2[x_] :=
Module[{m},
m = Cases[data, {t_, p_} /; p >= x :> t, {1}, 1];
First[m] /; m =!= {}
]
f2[100] (* returns 8 *)
f2[1000] (* returns f2[1000] *)
Note that the f2 bails out completely if the final result is the empty list and the original expression is returned unevaluated -- achieved by the simple expedient of adding a /; condition to the final expression.
One might decide to issue a meaningful warning if the "not found" case occurs:
f2[x_] := Null /; Message[f2::err, x]
f2::err = "Could not find a value for ``.";
With this change the same values will be returned, but a warning message will be issued in the "not found" case. The Null return value in the new definition can be anything -- it is not used.
One might further decide that the "not found" case just cannot occur at all except in the case of buggy client code. In that case, one should cause the computation to abort:
f2[x_] := (Message[f2::err, x]; Abort[])
In conclusion, these patterns are easy enough to apply so that one can deal with function arguments that are outside the defined domain. When defining functions, it pays to take a few moments to decide how to handle domain errors. It pays in reduced debugging time. After all, virtually all functions are partial functions in Mathematica. Consider: a function might be called with a string, an image, a song or roving swarms of nanobots (in Mathematica 9, maybe).
A final cautionary note... I should point out that when defining and redefining functions using multiple definitions, it is very easy to get unexpected results due to "left over" definitions. As a general principle, I highly recommend preceding multiply-defined functions with Clear:
Clear[f]
f[x_] := ...
f[x_] := Module[... /; ...]
f[x_] := ... /; ...
The problem here is essentially one of types. One function produces a bad output (incorrect type) which is then fed into many subsequent functions producing lots of errors. While Mathematica doesn't have user defined types like in other languages, you can do pattern matching on function arguments without too much work. If the match fails the function doesn't evaluate and thus doesn't beep with errors. The key piece of syntax is "/;" which goes at the end of some code and is followed by the test. Some example code (and output is below).
Input:
Average[x_] := Mean[x] /; VectorQ[x, NumericQ]
Average[{1, 2, 3}]
Average[$Failed]
Output:
2
Average[$Failed]
If the test is simpler, there is another symbol that does similar pattern testing "?" and goes right after an argument in a pattern/function declaration. Another example is below.
Input:
square[x_?NumericQ] := x*x
square[{1, 2, 3}]
square[3]
Output:
square[{1, 2, 3}]
9
It can help to define a catchall definition to pick up error conditions and report it in a meaningful way:
f[x_?NumericQ] := x^2;
f[args___] := Throw[{"Bad Arguments: ", Hold[f[args]]}]
So your top level calls can use Catch[], or you can just let it bubble up:
In[5]:= f[$Failed]
During evaluation of In[5]:= Throw::nocatch: Uncaught Throw[{Bad Args: ,Hold[f[$Failed]]}] returned to top level. >>
Out[5]= Hold[Throw[{"Bad Args: ", Hold[f[$Failed]]}]]
What I'd love to get is a way to define a general procedure to catch error propagation without the need to change radically the way I write functions right now, preferentially without adding substantial typing.
Here is a try:
funcDef = t_[args___] :c-: a_ :> ReleaseHold[Hold[t[args] :=
Check[a, Print#Hold[a]; Abort[]]]];
Clear#v;
v[x_, y_] :c-: Sin[x/y] /. funcDef;
?v
v[2, 3]
v[2, 0]
The :c-: is of course Esc c- Esc, an unused symbol (\[CircleMinus]), but anyone would do.
Output:
Global`v
v[x_,y_]:=Check[Sin[x/y],Print[Hold[Sin[x/y]]];Abort[]]
Out[683]= Sin[2/3]
During evaluation of In[679]:= Power::infy: Infinite expression 1/0 encountered. >>
During evaluation of In[679]:= Hold[Sin[2/0]]
Out[684]= $Aborted
What we changed is
v[x_, y_] := Sin[x/y]
by
v[x_, y_] :c-: Sin[x/y] /. funcDef;
This almost satisfies my premises.
Edit
Perhaps it's also convenient to add a "nude" definition for the function, that does not undergo the error checking. We may change the funcDef rule to:
funcDef =
t_[args___] \[CircleMinus] a_ :>
{t["nude", args] := a,
ReleaseHold[Hold[t[args] := Check[a, Print#Hold[a]; Abort[]]]]
};
to get for
v[x_, y_] :c-: Sin[x/y] /. funcDef;
this output
v[nude,x_,y_]:=Sin[x/y]
v[x_,y_]:=Check[Sin[x/y],Print[Hold[Sin[x/y]]];Abort[]]

Resources