Re: Re: Re: debugging
- To: mathgroup at smc.vnet.net
- Subject: [mg56788] Re: [mg56729] Re: [mg56716] Re: [mg56676] debugging
- From: "E. Martin-Serrano" <EmilioMartin-Serrano at wanadoo.es>
- Date: Fri, 6 May 2005 02:59:56 -0400 (EDT)
- Sender: owner-wri-mathgroup at wolfram.com
(Sorry again, I corrected some spelling mistakes in my previous post. I hope this is a bit clearer. I am always in a hurry) Sorry, I failed to send an example of how CallingFunction[] works. Here it is. First I define the function MinBiPartition[], which accepts several arguments of different types and includes a "branch" to deal with errors of the kind treated by CallingFunction[]. MinBiPartition definition includes calls to other here no defined functions (since they are part of a larger system) (* this load the package with Function Call *) Needs["GeneralServices`CallingFunctionControl`"]; Off[General::"spell1",General::"spell"] (* this defines MinBiPartition[] *) ClearAll[MinBiPartition]; MinBiPartition::"argument" = "Function call within the context [* `1` *] has failed because it submitted the improper argument [`2`]. The name of the function whose body wrapped the faulty call is among those in the list `3`. Valids arguments for this call must belong to one the following types: `4`."; MinBiPartition[side_?SingletonListQ]:= DoNothing MinBiPartition[side_?VoydQ]:= DoNothing MinBiPartition[side_?SingletonQ]:= DoNothing MinBiPartition[side_?CompleteGraphQ]:= DoNothing MinBiPartition[side_?FakeCliqueQ]:= DoNothing MinBiPartition[side_?SinglePairListQ]:= DoNothing MinBiPartition[side_?ProperFlatListQ]:= DoNothing MinBiPartition[wrong___]:=With[{stack = Stack[_][[1]]},Message[MinBiPartition::"argument",stack,wrong,CallingFunctio n[ToString[Hold[stack]]],FunctionDomain[MinBiPartition]];AbortProtect[Abort[ ];Print["Computation will be aborted due to improper function call."]]] (*This is an instrumental function used to test CallingFunction[], by issuing a wrong call to MinBiPartition[] with " Fake Invalid Argument" as the wrong argument; "fake invalid argument" could take any variable form in a dynamic environment *) fff[]:= Module[{},one;two;MinBiPartition["Fake Invalid Argument"];three; four] (* This is another instrumental function used to test CallingFunction[], by issuing a wrong call to MinBiPartition[] with " Invalid Argument" as the wrong argument; "invalid argument" could take any variable form in a dynamic environment *) Otherfff[]:= Module[{},one;two;MinBiPartition["Invalid Argument"];three; four] (* This makes a wrong call to MinBiPartition[] through the call to fff[]. Actually it is *) fff[] (* and the rest is the result rendered by the wrong call to fff[] *) MinBiPartition::argument: Function call within the context [* Module[{},one;two;MinBiPartition[Fake Invalid Argument];three;four] *] has failed because it submitted the improper argument [Fake Invalid Argument]. The name of the function whose body wrapped the faulty call is among those in the list {fff[]}. Valid arguments for this call must belong to one the following types: {MinBiPartition[side_?SingletonListQ],MinBiPartition[side_?VoydQ],MinBiParti tion[side_?SingletonQ],MinBiPartition[side_?CompleteGraphQ],\[LeftSkeleton]1 4\[RightSkeleton]\[LeftSkeleton]1\[RightSkeleton]\[LeftSkeleton]1\[RightSkel eton]],MinBiPartition[side_?SinglePairListQ],MinBiPartition[side_?ProperFlat ListQ],MinBiPartition[wrong___]}. Computation will be aborted due to improper function call. $Aborted -----Original Message----- From: E. Martin-Serrano [mailto:EmilioMartin-Serrano at wanadoo.es] To: mathgroup at smc.vnet.net Subject: [mg56788] [mg56729] Re: [mg56716] Re: [mg56676] debugging The lack of debugging tools is, no doubt, an issue in Mathematica. I wrote the following utility package to deal with semantic/dynamic debugging; mainly to control calling functions flow. (* :Context: DFramework`DFrameworkMessage`*) (* :Title: Design Framework Environment *) (* :Author: E.Martin-Serrano - In Houston - Texas (USA) *) (* :Package Version:1.0,0 , July 3rd, 2004 *) (* :Mathematica Version:5.0.1 *) (* :Copyright: Copyright 2004 *) (* :History:Original version: July 3rd, 2004 *) (* :Summary: CallingFunction[stack] yields a list of functions. The meaning of this list of functions is that described ahead. Let us have a function 'f', whose body contains a call to another function 'f1'. Let us suppose that the call to 'f1', inside the body of 'f', fails due to an improper parameter passing. This failure may typically happen in situations of uncertainty: either the system is under construction (debugging) or in production when the parameters are produced dynamically from inputs inherited from other functions. To identify and locate the source of the problem, and the point of the failure, it is necessary to know three things: 1) the piece of code wrapping the point from where 'f1' was called when the failure came up, 2) The name of the parent function 'f' owning the piece of code wrapping the calling point to 'f1' where the failure came up, and 3) the domain of valid parameters for the function 'f1'. The necessity of this utility comes from the fact that any function may, in principle, be invoked from many different points or functions in a network-like manner, so there is not a way to know in advance which function is the culprit of a particular failure."*) (* :Keywords: Testing, debugging, messages *) (* :Contents:*) (* :Discussion: The present implementation is the first version and is mainly meant to describe the purpose of the utility itself, yet it seems to be working properly as far as it is currently used. The implementation should probably be improved in a more efficient and elegant manner*) (* :Sources: The function 'Domain' was taken from Ted Ersek's Tricks and slighted modify to accept arguments of the form ' arg___' *) (* :Credits: The function 'Domain[]' in its original form is due to Ted Ersek as mentioned above. David Park has been helping me a lot with his suggestions about systematic package developing *) (* :Warning: I have not performed a systematic thoroughly test *) BeginPackage["GeneralServices`CallingFunctionControl`"] Unprotect[Evaluate[$Context<>"*"]] FunctionDomain::usage= "FunctionDomain[function] computes the valid domain of the arguments accepted by 'function[]'." CallingFunction::usage= "CallingFunction[stack] yields a list of functions. The meaning of this list of functions is that described ahead. Let us have a function 'f', whose body contains a call to another function 'f1'. Let us suppose that the call to 'f1', inside the body of 'f', fails due to an improper parameter passing. This failure may typically happen in situations of uncertainty: either the system is under construction (debugging) or in production when the parameters are produced dynamically from inputs inherited from other functions. To identify and locate the source of the problem, and the point of the failure, it is necessary to know three things: 1) the piece of code wrapping the point from where 'f1' was called when the failure came up; 2) The name of the parent function, 'f', owning the piece of code that wraps the calling point to 'f1' where the failure came up; and 3) the domain of valid parameters for the function 'f1'. The necessity of this utility comes from the fact that any function may, in principle, be invoked from many different points or functions in a network-like manner, so that there is not an easy way to know in advance which function is the culprit of a particular failure." Begin["`Private`"] FunctionDomain[f_]:=Module[{result}, result=HoldForm@@{First/@DownValues[f]}; result=result/.Verbatim[HoldPattern][e_]\[RuleDelayed]e ] CallingFunction[stack_]:= Module[{downvalues,callingcontext,stp,index,functions}, downvalues= DownValues[#]&/@Cases[Map[ToExpression,Names[Context[]<>"*"]],_Symbol]// Flatten; callingcontext = StringDrop[stack,5]; callingcontext = StringDrop[callingcontext,-1]; stp =StringPosition[#,callingcontext]&/@(ToString[#]&/@downvalues); index = Table[If[stp[[i]]\[NotEqual]{},{i},{}],{i,Length[stp]}]//Flatten; functions =StringDrop[ ToString[First[downvalues[[#]]]],12]&/@index; StringDrop[#,-1]&/@functions ] End[] Protect[Evaluate[$Context<>"*"]] EndPackage[] -----Original Message----- From: Chris Chiasson [mailto:chris.chiasson at gmail.com] To: mathgroup at smc.vnet.net Subject: [mg56788] [mg56729] [mg56716] Re: [mg56676] debugging Do you mean it wasn't an error that referenced a line number? Some errors in Mathematica do come with line numbers; I thought you had one of those kind and were just looking for a way to display line numbers. You could add your own type checking/debugging code that will produce its own warning messages. That would help you locate the problem. I usually start from the name of the function that produces an error and tear my function apart, call by call, until I find the step between which the output went from good to bad. You may find ctrl+shift+b useful for this. You may also wish to make use of the Interrupt[] , Abort[] and Throw/Catch calls. On 5/3/05, Daniel Roy <droy at mit.edu> wrote: > There are no line numbers in the reported bugs, of course. > > On Tue, 2005-05-03 at 13:10 -0400, Chris Chiasson wrote: > > You could load the code into the vi editor (or your favorite text > > editor) and turn on the line numbers. > > > > On 5/3/05, Daniel Roy <droy at mit.edu> wrote: > > > > > > My question concerns debugging. I've done googling to find a quick > > > answer but have failed. I'm developming large functions and without > > > line numbers telling me where the errors occurred, its becoming very > > > difficult to develop code quickly. Can anyone point me in the right > > > direction in terms of debugging multi line (at least 50+ lines) > > > functions? > > > > > > thanks, > > > dan > > > > > > > > > > > > -- Chris Chiasson http://chrischiasson.com/ 1 (810) 265-3161