Re: Tips for writing correct, non trivial Mathematica Libraries
- To: mathgroup at smc.vnet.net
- Subject: [mg124506] Re: Tips for writing correct, non trivial Mathematica Libraries
- From: David Bailey <dave at removedbailey.co.uk>
- Date: Sun, 22 Jan 2012 07:21:11 -0500 (EST)
- Delivered-to: l-mathgroup@mail-archive0.wolfram.com
- References: <jf68se$g99$1@smc.vnet.net>
On 18/01/2012 11:02, l.i.b. wrote:
>
> ** Take for example the following: (Taken from the mathematica 8
> virtual book section "Applying Functions to Lists and Other
> Expressions")
>
> geom[list_] := Apply[Times, list]^(1/Length[list])
>
> So, this does a bad thing for geom[ x+ y] (returns (Sqrt[x y])
>
A lot of Mathematica functions that usually operate on lists, are
defined more generally so as to apply to any compound object. While this
can be very useful, it can produce weird results such as this. Simply
restricting your function to operate only on lists is very easy:
geom[list_List] := Apply[Times, list]^(1/Length[list])
This has the useful feature that geom[Sqrt[x y]] will return without
change. This is generally valuable, because in general the argument
might resolve to a list later on, for example
geom[x] /. x->{1,2,3}
Numerical calculations often do weird things is they are applied to
non-numerical data, so it is often useful to require arguments of a
function to be numeric:
f[x_?NumericQ]:=Module[{x1=N[x]},
doSomething[x1]
];
The reason for applying N (where appropriate) to the input x, is that a
numerical algorithm may fail, or operate extremely slowly if forced to
operate on integer data. To see why that is true, try comparing:
Nest[#^2/(1 + #) &, 22, 4]
with
Nest[#^2/(1 + #) &, 22.0, 4]
Again, the function f will return unchanged if applied to other types of
arguments, which is exactly what is normally required.
In more complicated cases, it is possible to validate the arguments in
an arbitrary way using a function definition of the form:
f[args]:=Calculation/;test
Where test can perform any calculation on the arguments, and unless it
returns True, no evaluation will take place.
Another thing that is almost vital, is to place your library of
functions in its own package, so that only selected symbols are shared
with 'the outside world', and to define complicated functions using
Module or Block, to ensure that they don't use global variables.
You don't want to create a function that works in almost all cases,
except when someone already has a definition for the variable x! The
automatic colouring is very useful in this regard.
David Bailey
http://www.dbaileyconsultancy.co.uk