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