• Aucun résultat trouvé

Definition of procedures in theMathematicasoftware

Dans le document Extension of Mathematica systemfunctionality (Page 92-103)

Chapter 6. Problems of procedural programming in the Mathematicasoftware

6.1. Definition of procedures in theMathematicasoftware

Procedures in theMathematica system formally represent functional objects of following two simple formats, namely:

M[x_/;Testx,y_/;Testy, …] {:= | =}Module[{locals},Procedure Body]

B[x_/;Testx,y_/;Testy, …] {:= | =}Block[{locals},Procedure Body]

i.e., the procedures of both types represent functions from two arguments – body of a procedure(Body) andlocal variables (locals). Local variables– the list of names, perhaps, with the initial values which are attributed to them. These variables have local character concerning procedure, i.e. their values aren’t crossed with values of the symbols of the same name outside of the procedure. All other variables in procedure have global character, dividing area of variables of theMathematica current session.

Thus, in definition of procedures it is possible to distinguish five following component, namely:

– procedure name (Min the first procedure definition);

– procedure heading(M[x_/;Testx,y_/;Testy, …]in the both procedures definitions);

–procedural brackets (Module[…]orBlock[…]);

–local variables(list of local variables {locals};can be empty);

– procedure body;can be empty.

Above all, it should be noted the following very important circumstance. If in the

traditional programming languages the identification of an arbitrary procedure/function is made according to itsname, in case ofMathlanguage identification is made according to itsheading. The circumstance is caused by that the definition of a procedure/function inMathlanguage is made by the manner different from traditional [28-33]. Simultaneous existence of the procedures/functions of the same name with various headings in the given

situation is admissible as it illustrates the following fragment, namely:

In[2434] := M[x_, y_] := Module[{}, x + y]; M[x_] := Module[{}, x^2]; M[y_] :=

Module[{}, y^3]; M[x___] := Module[{}, {x}]

In[2435]:= Definition[M]

Out[2435]= M[x_, y_]:= Module[{}, x+ y]

M[y_]:= Module[{}, y^3]

M[x___]:= Module[{}, {x}]

In[2436]:= {M[480, 80], M[80], M[42, 47, 67, 25, 18]}

Out[2436]= {560, 512000, {42, 47, 67, 25, 18}}

In[2437]:= G[x_Integer] := Module[{}, x]; G[x_] := Module[{}, x^2]; G[480]

Out[2437]= 480

At the call of a procedure/function of the same name from the list is chosen the one, whose formal arguments of the heading correspond to the factual arguments of the call, otherwise the call is returned byunevaluated, except forsimplifications of the actual arguments according to the standard system agreements. Moreover, at compliance of

formal arguments of heading with the actual ones a procedurex is caused, whose definition is above in the list returned at theDefinition[x] call; in particular, whose definition has been calculated in theMathematica current session by the first.

Further is being quite often mentioned about return of result of the call of a

function/procedure by unevaluated, it concerns both the standard system means, and the user means. In any case, the call of a procedure/function on aninadmissible tuple of actual arguments is returned by unevaluated, except for standard simplifications of the actual arguments. In this connection the UnevaluatedQ procedure providing testing of a certain procedure/function regarding of return of its call unevaluated on a concrete tuple of the factual arguments has been programmed. The callUnevaluatedQ[F,x] returnsTrue if the callF[x] is returned unevaluated, andFalse otherwise; in addition, on an erroneous

callF[x]”ErrorInNumArgs” is returned. The fragment below represents source code of the UnevaluatedQ procedure with examples of its usage. Procedure represents a certain interest for program processing of results of calls of procedures and functions.

In[3246] := UnevaluatedQ[F_ /; SymbolQ[F], x___] :=

Module[{a = Quiet[Check[F[x], “e”, F::argx]]}, If[a === “e”, “ErrorInNumArgs”, If[ToString1[a]===ToString[F]<>”[” <> If[{x}== {}, ””,

ListStrToStr[Map[ToString1, {x}]] <> “]”], True, False]]]

In[3247] := {UnevaluatedQ[F, x, y, z], UnevaluatedQ[Sin, x, y, z]} Out[3247]= {True,

“ErrorInArgs”}

In[3248]:= {UnevaluatedQ[Sin, 48080], UnevaluatedQ[Sin, 480.80], UnevaluatedQ[Sin]}

Out[3248]= {True, False, “ErrorInNumArgs”}

Meanwhile, the standard Definition function in the case of the procedures/ functions of the same name in a number of cases is of little use for solution of tasks which are

connected with processing of definitions of such objects. Above all, it concerns the procedures whose definitions are located in the user packages loaded into the current session ofMathematica as illustrates a simple example of receiving definition of

theSystemQ procedure [48]:

In[3247]:= Definition[“SystemQ”]

Out[3247]= SystemQ[AladjevProcedures`SystemQ`S_]:=

If[Off[ “Definition“::”ssle”]; !

ToString[”Definition”[AladjevProcedures`SystemQ`S]]=== Null&&

SysFuncQ1[AladjevProcedures`SystemQ`S], On[”Definition“::”ssle”]; True,

On[”Definition“::”ssle”]; False] The callDefinition[x] of the standard function in a

number of cases returns the definition of some objectx with the context corresponding to it what at quite large definitions becomes bad foreseeable and less acceptable for the

subsequent program processing as enough visually illustrates the previous example.

Moreover, the name of object or its string format also can act as an actual argument. For elimination of this shortcoming we defined a number of means allowing to obtain

definitions of procedures/functions in a certain optimized format. As such tools it is possible to note such asDefOptimum, Definition1, Definition2, Definition3,

Definition4, DefFunc, DefFunc1, DefFunc2, DefFunc3 andDefOpt. These means along with some others are presented in books [28-33] and included in theAVZ_Package

package [48]. The following fragment represents source codes of the most used of them.

In[2470]:= Definition2[x_ /; SameQ[SymbolQ[x], HowAct[x]]] := Module[{a, b = Attributes[x], c},

If[SystemQ[x], Return[ {“System”, Attributes[x]}], Off[Part::partw]];

ClearAttributes[x, b]; Quiet[a = ToString[InputForm[Definition[x]]];

Mapp[SetAttributes, {Rule, StringJoin}, Listable]; c = StringReplace[a,

Flatten[{Rule[StringJoin[Contexts1[], ToString[x] <> “`”], ””]}]]; c = StringSplit[c,

“\n \n”]; Mapp[ClearAttributes, {Rule, StringJoin}, Listable]; SetAttributes[x, b]; a

= AppendTo[c, b]; If[SameQ[a[[1]], “Null”] && a[[2]] == {}, On[Part::partw];

{“Undefined”, Attributes[x]}, If[SameQ[a[[1]], “Null”] && a[[2]] != {}&& ! SystemQ[x], On[Part::partw]; {“Undefined”, Attributes[x]}, If[SameQ[a[[1]],

“Null”] && a[[2]] != {}&& a[[2]] != {}, On[Part::partw]; {“System”, Attributes[x]}, On[Part::partw]; a]]]]]

In[2471]:= Definition2[SystemQ]

Out[2471]= {”SystemQ[S_]:= If[Off[MessageName[Definition, "ssle"]];

! ToString[Definition[S]]=== Null&& SysFuncQ1[S], On[MessageName[Definition,

"ssle"]]; True, On[MessageName[Definition,"ssle"]]; False]”, {}} In[2472]:=

Definition2[Tan]

Out[2472]= {”System”, {Listable, NumericFunction, Protected}}

In[2473]:= Definition2[(a + b)/(c + d)]

Out[2473]= Definition2[(a+ b)/(c+ d)]

In[2502]:= Definition3[x_ /; SymbolQ[x], y_ /; ! HowAct[y]] := Module[{a = Attributes[x], b = Definition2[x]},

If[b[[1]] == “System”, y = x; {“System”, a}, b = Definition2[x][[1 ;;–2]];

ClearAttributes[x, a]; If[BlockFuncModQ [x, y], ToExpression[b]; SetAttributes[x, a]; Definition[x], SetAttributes[x, a]; Definition[x]]]]

In[2503]:= Definition3[SystemQ, y]

Out[2503]= SystemQ[S_]:= If[Off[”Definition“::”ssle”];

! ToString[”Definition”[S]]=== Null&& SysFuncQ1[S],

On[ “Definition“::”ssle”]; True, On[”Definition“::”ssle”]; False] In[2504]:= y Out[2504]= “Function”

In[2505]:= Definition3[Sin, z]

Out[2505]= Attributes[Sin]= {Listable, NumericFunction, Protected} In[2506]:= z Out[2506]= Sin

In[2598] := Definition4[x_ /; StringQ[x]] := Module[{a},

a = Quiet[Check[Select[StringSplit[ToString[InputForm[ Quiet[Definition[x]]]],

“\n”], # != ” ” && # != x &], $Failed]]; If[a === $Failed, $Failed, If[SuffPref[a[[1]],

“Attributes[“, 1], a = AppendTo[a[[2 ;;–1]], a[[1]]]]]; If[Length[a] != 1, a, a[[1]]]]

In[2599]:= W = 80; G := 480; Map[Definition4, {“W”, “G”, “72”, “a + b”, “If”}]

Out[2599]= {”W= 80“, “G:= 480“, $Failed, $Failed, “Attributes[If]= {HoldRest, Protected}”}

In[2600]:= A[x_] := Module[{a=90}, x+a]; A[x_, y_] := Module[{a=6}, x+y+a];

A[x_, y_List] := Block[ {}, {x, y}]; A[x_Integer] := Module[{a = 480}, x + a]; A := {a, b, c, d, h}; SetAttributes[A, {Flat, Listable, Protected}]; In[2601]:= Definition4[“A”]

Out[2601]= {”A:= {a, b, c, d, h}“, “A[x_Integer]:= Module[{a= 480}, x+ a]“,

“A[x_]:= Module[{a= 90}, x+ a]“, “A[x_, y_List]:= Block[{}, {x, y}]“, “A[x_, y_]:=

Module[{a= 6}, x+ y+ a]“, “Attributes[A]=

{Flat , Listable, Protected}”}

A number of functional means ofMath–language as the actual arguments assume only objects of the types {Symbol,String,HoldPattern[Symbol]} what in some cases is quite inconvenient at programming of problems of different purpose. In particular,

theDefinitionDefinition 33]. For the purpose of expansion of theDefinition function on the types, different from the mentioned ones, theDefinition1 procedure can be used, whose callDefinition1[x] returns definition of an objectx in string format, “Null” ifx isn’t defined, otherwise$Failed is returned. A fragment in [28,33] represents the procedure code with typical examples of its application from which certain advantages of theDefinition1 concerning theDefinition are quite visually visible. TheDefinition1 procedure has been realized with use of ourToString1 procedure [28] that unlike the standardToString function provides correct converting of expressions in string format. TheDefinition1

procedure processes the main special and erroneous situations. Meanwhile, theDefinition1 procedure doesn’t rid the returned definitions from contexts and is correct only for objects with unique names. Moreover, in case of the multiple contexts theDefinition1 procedure call returns definitions with a context that answers the last user package loaded into the current session. On system functions, theDefinition1 procedure call returns”Null“. As an expansion of theDefinition1 procedure theDefinition2 procedure represented by the previous fragment can serve. The given procedure uses our meansContexts1, HowAct, Mapp, SymbolQ andSystemQ considered in the present book and in [28-33]. These means are rather simple and are used in our means enough widely [48].

Unlike previous procedure Definition1, theDefinition2 procedure rids the returned

definitions from contexts, and is correct for program objects with unique names.

TheDefinition2 call on system functions returns the nested list, whose first element–

“System“, whereas the second element– the list of attributes ascribed to a factual

argument. On a function or procedure of the userx the callDefinition2[x] also returns the nested list, whose first element

– theoptimized definition ofx(in the sense of absence of contexts in it), whereas the second element– the list of attributes ascribed tox; in their absence the empty list acts as the

second element of the returned list. In the case ofFalse value on a test ascribed to formal argumentx, the callDefinition2[x] will be returnedunevaluated. Analogously to the previous procedure, the procedure Definition2 processes the mainspecial anderroneous situations. In addition, Definition1 andDefinition2 return definitions of objects in string format. The callDefinition3[x, y] returns the optimum definition of a procedure or a functionx, while through the second argumenty –an undefined variable– the type ofx in a context {”Procedure“, “Function“, “Procedure&Function”} is returned ifx is a procedure or function, on system functions the procedure call returns the list {”Function“,

{Attributes}} while thru the second argument y thefirst argument is returned; at

inadmissibility of thefirst argumentx the call is returned unevaluated, i.e.Definition[x].

The call Definition4[x] in a convenient format returns the definition of an objectx whose name is coded in the string format, namely:(1) on a system functionx its attributes are returned,(2) on the user block, function, module the call returns the definition of objectx in string format with the attributes, options and/or values by default for formal arguments ascribed to it(if such are available), (3) the call returns the definition of an objectx in string format for assignments by operators {“:=”, “=”}, and(4) in other cases the

procedure call returns$Failed. The procedure has a number of interesting appendices at programming of various system appendices.

The followingDefOpt procedure represents a quite certain interest that in a number of cases is more acceptable than theDefinition function along with our proceduresDefFunc, DefFunc1, DefFunc2 andDefFunc3 considered in [28-33,48] that are also intended for obtaining definitions of procedures and functions in the convenient form acceptable for processing. The following fragment represents source code of the procedure with

examples of its use.

In[2342] := DefOpt[x_ /; StringQ[x]] := Module[{a = If[SymbolQ[x], If[SystemQ[x], b

= “Null”, ToString1[Definition[x]], “Null”]], b, c}, If[! SameQ[a, “Null”], b = Quiet[Context[x]]]; If[! Quiet[ContextQ[b]], “Null”,

c = StringReplace[a, b <> x <> “`”–> ””]; ToExpression[c]; c]]

In[2343] := DefOpt[“SystemQ”]

Out[2343]= SystemQ[S_]:= If[Off[MessageName[Definition, “ssle”]]; !

ToString[Definition[S]]=== Null&& SysFuncQ1[S], On[MessageName[Definition,

“ssle”]]; True, On[MessageName[Definition,”ssle”]]; False]

In[2344] := DefFunc[$TypeProc]

Out[2344]= Attributes[$Failed]= {HoldAll, Protected}

In[2345]:= DefOpt[“$TypeProc”]

Out[2345]= “$TypeProc:= CheckAbort[If[$Art24$Kr17$ =

Select[{Stack[Module] , Stack[Block], Stack[DynamicModule]}, #1!= {}&];

If[$Art24$Kr17$ == {}, Clear[$Art24$Kr17$]; Abort[], $Art24$Kr17$ = ToString[$Art24$Kr17$[[1]][[1]]]]; SuffPref[$Art24$Kr17$, "Block[{", 1], Clear[$Art24$Kr17$]; "Block", If[SuffPref[$Art24$Kr17$,

"Module[{", 1]&& !StringFreeQ[$Art24$Kr17$, "DynamicModule"],

Clear[$Art24$Kr17$]; "DynamicModule", Clear[$Art24$Kr17$]; "Module"]], $Failed]”

In[2346]:= Map[DefOpt, {“If”, “Sin”, “Goto”, “a + b”, “80”, 480}] Out[2346]= {Null, Null, Null, Null, Null, DefOpt[480]}

On the other hand, our some procedures are unsuitable in case of necessity of receiving definitions of a number of procedural variables, in particular, $TypeProc as some

illustrate examples in [33]. And only the procedure call DefOpt[x] returns definition of an arbitrary objectx in an optimum format irrespective of type of the user objectx. At that, the callDefOpt[x] not only returns an optimum form of definition of an objectx in string

format, but also evaluates it in the current session what in a number of cases is useful enough; at the procedure call the name of the objectx is coded in the string format; while on the system functions and other string expressions the call DefOpt[x] returns”Null“. At the same time it must be kept in mind that the DefOpt is inapplicable to the procedures / functions of the same name, i.e. having several definitions with different headings. The previous fragment represents source code of theDefOpt procedure with examples of its usage.

The OptDefinition procedure is an interesting enough modification of the previous

procedure; its source code with examples of usage represents the following fragment. The call OptDefinition[x] returns the definition of a procedure or a functionx optimized in the above sense i.e. without context associated with the user package containing the procedure or functionx.

In[3298] := OptDefinition[x_ /; Quiet[ProcQ[x] || FunctionQ[x]]] := Module[{c =

$Packages, a, b, d, h = Definition2[x]}, {a, b}= {h[[1 ;;–2]], h[[–1]]};

ClearAllAttributes[x]; d = Map[StringJoin[#, ToString[x] <> “`”] &, c];

ToExpression[Map[StringReplace[#, GenRules[d, ””]] &, a]]; SetAttributes[x, b];

Definition[x]]

In[3299] := SetAttributes[ToString1, {Listable, Protected}];

Definition[ToString1]

Out[3299]= Attributes[ToString1]= {Listable, Protected}

ToString1[AladjevProcedures`ToString1`x_]:=

Module[{AladjevProcedures`ToString1`a= “$Art23Kr15$.txt“,

AladjevProcedures`ToString1`b= ””, AladjevProcedures`ToString1`c, AladjevProcedures`ToString1`k= 1},

Write[AladjevProcedures`ToString1`a, AladjevProcedures`ToString1`x];

Close[AladjevProcedures`ToString1`a];

For[AladjevProcedures`ToString1`k,

AladjevProcedures`ToString1`k< \[Infinity], AladjevProcedures`ToString1`k++, AladjevProcedures`ToString1`c=

Read[AladjevProcedures`ToString1`a, String]; If[AladjevProcedures`ToString1`c===

EndOfFile, Return[DeleteFile[

Close[AladjevProcedures`ToString1`a]]; AladjevProcedures`ToString1`b], AladjevProcedures`ToString1`b= AladjevProcedures`ToString1`b<>

StrDelEnds[AladjevProcedures`ToString1`c, ” “, 1]]]]

In[3300]:= OptDefinition[ToString1]

Out[3300]= Attributes[ToString1]= {Listable, Protected}

ToString1[x_]:= Module[{a= “$Art25Kr18$.txt“, b= ””, c, k= 1}, Write[a, x]; Close[a];

For[k, k< ∞, k++, c= Read[a, String]; If[c=== EndOfFile, Return[DeleteFile[Close[a]];

b], b= b<> StrDelEnds[c, ” “, 1]]]]

It is necessary to pay attention to use of the GenRules procedure providing generation of the list of transformation rules for providing of replacements in a string definition of an objectx. In a number of cases such approach is a rather effective at strings processing.

TheDefOptimum procedure realized in a different manner is full analog of the previous procedure, whose callDefOptimum[x] returns the definition of a function or procedurex optimized in the respect that it doesn’t contain acontext of the user package containing definition of the procedure/function x. The following fragment represents source code of this procedure with a typical example of its usage.

In[2245] := SetAttributes[OptDefinition, {Listable, Protected}];

Definition[OptDefinition]

Out[2245]= Attributes[OptDefinition]= {Listable, Protected}

OptDefinition[x_ /; ProcQ[x]|| FunctionQ[x]]:= Module[{a= Definition2[x][[1;;–2]], b=

Definition2[x][[–1]], AladjevProcedures`OptDefinition`c= $Packages, AladjevProcedures`OptDefinition`d,

AladjevProcedures`OptDefinition`h}, ClearAllAttributes[ToString1];

AladjevProcedures`OptDefinition`d=(#1<> (ToString[x]<> “`”)&)/@

AladjevProcedures`OptDefinition`c;

ToExpression[(StringReplace[#1,

GenRules[AladjevProcedures`OptDefinition`d, ””]]&)/@ a]; SetAttributes[x, b];

“Definition”[x]]

In[2246]:= DefOptimum[x_ /; Quiet[ProcQ[x] || FunctionQ[x]]] := Module[{a, c, k = 1, b = “Art$Kr.txt”, d = Context[x], f = Attributes[x]}, ClearAttributes[x, f]; Save[a = ToString[x], x]; For[k, k < Infinity, k++, c = Read[a, String]; If[SameQ[c,

EndOfFile], Break[], Write[b, StringReplace[c, d <> ToString[x] <> “`”–> ””]]]];

Map[Close, {a, b}]; Get[b]; Map[DeleteFile, {a, b}]; SetAttributes[x, f];

Definition[x]]

In[2247]:= DefOptimum[OptDefinition]

Out[2247]= Attributes[OptDefinition]= {Listable, Protected}

OptDefinition[x_ /; Quiet[ProcQ[x]|| FunctionQ[x]]]:= Module[{c= $Packages, a, b, d, h=

Definition2[x]}, {a, b}= {h[[1;;–2]], h[[–1]]}; ClearAllAttributes[x]; d= (#1<>

(ToString[x]<> “`”)&)/@ c; ToExpression[(StringReplace[#1, GenRules[d, ””]]&)/@ a];

SetAttributes[x, b]; “Definition”[x]]

In[2500]:= DefOpt1[x_] := Module[{a = ToString[x], b, c}, If[! SymbolQ[a], $Failed, If[SystemQ[x], x,

If[ProcQ[a]||FunctionQ[a], b = Attributes[x]; ClearAttributes[x, b]; c = StringReplace[ToString1[Definition[x]], Context[a] <> a <> “`”–> ””];

SetAttributes[x, b]; c, $Failed]]]]

In[2501] := DefOpt1[StrStr]

Out[2501]= “StrStr[x_]:= If[StringQ[x], "<>x<>", ToString[x]]” In[2502]:=

Map[DefOpt1, {a + b, 72, Sin}]

Out[2502]= {$Failed, $Failed, Sin}

The algorithm of the above DefOptimum procedure is based on saving of the current definition of a block/function/modulex in anASCII format file with the subsequent its converting into thetxt–datafile containing definition of the objectx without occurrences of a package context in which definition of this object is located. Whereupon the result

datafile is loaded by means of theGet function into the current session of theMathematica with return of the optimized definition of the objectx.

Meanwhile, the last DefOpt1 procedure of the previous fragment is seemed as effective enough for receiving of definition of the user procedure/function in optimized format in the above sense, i.e. without context. The procedure callDefOpt1[x] on a system

functionx returns its name, on an user function or procedure returns its optimized code in string format whereas on other values of argumentx$Failed is returned. The previous fragment represents source code of the procedureDefOpt1 along with examples of its usage. For a number of appendices, including appendices of system character, the

standardDefinition function seems as important enough means whose call Definition[x]

returns the definition of an objectx with attributes ascribed to it; in the absence of definition theNull, i.e. nothing, or the ascribed attributes to an undefined symbolx is returned, namely:

Attributes[ x] =The list of attributes ascribed to a symbol x As very visually illustrate the following simple examples, namely:

In[2839]:= SetAttributes[h, Listable]; Definition[h]

Out[2839]= Attributes[h]= {Listable}

In[2840] := Definition[Sin]

Out[2840]= Attributes[Sin]= {Listable, NumericFunction, Protected} Meanwhile, on the other hand, many problems of processing of objects are based strictly speaking on their definitions in their pure form. Therefore the allotment of definition of an arbitrary objectx in pure form can be provided, in particular, by means of2 mechanisms whose essence is explained by the examples in [28-33] by means of the proceduresDef andDef1; definition of the procedureDef1 gives the following example, namely:

In[2526]:= Def1[x_ /; StringQ[x]] := Module[{a}, If[! SymbolQ[x] || SystemQ[x],

$Failed, a = Definition2[x][[1 ;;–2]]; If[Length[a] == 1, a[[1]], a]]]

In[2527] := B[x_] := x; B[x_, y_] := Module[{a, b, c}, x + y];

B[x_ /; IntegerQ[x]] := Block[{a, b, c, d}, x]

In[2528]:= SetAttributes[B, {Protected}]; Attributes[B]

Out[2528]= {Protected}

In[2529]:= Def1[“B”]

Out[2529]= {”B[x_ /; IntegerQ[x]]:= Block[{a, b, c}, x]“,

“B[x_]:= x“, “B[x_, y_]:= Module[{a, b, c, d}, x+ y]”}

In[2530]:= Definition[B]

Out[2530]= Attributes[B]= {Protected}

B[x_ /; IntegerQ[x]]:= Block[{}, x]}

B[x_]:= x

B[x_, y_]:= Module[{}, x+ y]

In event of an object x of the same name the procedure callDef1[x] returns the list of the optimized definitions of the objectx in string format without the attributes ascribed to it.

Ifx defines an unique name, the call returns the optimized definition of the objectx in string format without the attributes ascribed to it. The name of an objectx is given in string format; in addition, on unacceptable values of argumentx$Failed is returned.

An extension of the standardAttributes function is represented by simple procedure, whose callAttributes1[x, y, z, t, …] unlike standard function on objectsx, y, z, t, …, that differ from admissible ones, returns the empty list, i.e. {}, without output of any error messages what in a number of cases more preferably from standpoint of processing of erroneous situations. While on admissible objectsx, y, z, … the callAttributes1[x, y, z, …]

returns the list of the attributes ascribed to objectsx, y, z, … The following fragment represents source code of the procedure along with typical examples of its usage.

In[2796]:= Attributes1[x__] := Module[{a=

Map[Quiet[Check[Attributes[#], {}]] &, {x}]}, If[Length[a] == 1, a[[1]], a]]

In[2797] := L := {42, 47, 67, 25, 18}; SetAttributes[L, {Flat, Protected, Listable}]

In[2798]:= Attributes1[L[[5]], Sin, ProcQ]

Out[2798]= {{}, {Listable, NumericFunction, Protected}, {}}

In[2799]:= Attributes1[72, a + b, Attributes1, While, If]

Out[2799]= {{}, {}, {}, {HoldAll, Protected}, {HoldRest, Protected}}

The Attributes1 procedure is a rather useful tool in a number of appendices. Means of processing of the attributes specific to procedures/functions in the form of

proceduresAttributesH andDefAttributesH are presented below.

As it was noted above, the strict differentiation of the blocks, functions and modules in theMathematica is carried out not by means of their names as it is accepted in the

majority of known programming languages and systems, but by means of theirheadings.

For this reason in a number of cases of the advanced procedural programming, the important enough problem of the organization of mechanisms of the differentiated

processing of such objects on the basis of their headings arises. A number of such means is presented in the present book, here we will determine two means ensuring work with

attributes of objects on the basis of their headings. The following fragment represents source codes of2 meansDefAttributesH andAttributesH along with typical examples of their usage.

The callDefAttributesH[x, y, z, p, h, …] returnsNull, i.e. nothing, assigning {y= “Set”} or deleting {y = “Clear”} the attributes determined by arguments {z,p, h, …} for an object with headingx. Whereas in attempt of assigning or deleting of an attribute, nonexistent in the current version of the system, the procedure call returns the list whose1st element is$Failed, whereas the2nd element– the list of the expressions different from the current attributes. At that, the callAttributesH[x] returns the list of attributes ascribed to an object

with headingx. An useful function whose callClearAllAttributes[x, y, z, …] returnsNull, i.e. nothing, canceling all attributes ascribed to the symbolsx, y, z, … completes the given fragment.

In[2880]:= DefAttributesH[x_ /; HeadingQ[x], y_ /; MemberQ[{“Set”, “Clear”}, y], z___] :=

Module[ {a}, If[AttributesQ[{z}, a = Unique[g]], ToExpression[y <> “Attributes[” <>

HeadName[x] <> “, ” <> ToString[{z}] <> “]”], {$Failed, a}]]

In[2881] := M[x__] := Module[{}, {x}]; M[x__, y_] := Module[{}, {x}]; M[x___, y_, z_] := x + y + z

In[2882]:= DefAttributesH[“M[x___, y_, z_]”, “Set”, Flat, Protected, Listable]

In[2883]:= Attributes[M]

Out[2883]= {Flat, Listable, Protected}

In[2884]:= DefAttributesH[“M[x___, y_, z_]”, “Set”, AvzAgn]

Out[2884]= {$Failed, {AvzAgn}}

In[2930]:=AttributesH[x_ /; HeadingQ[x]] :=

Attributes1[Symbol[HeadName[x]]] In[2972]:= AttributesH[“M[x___, y_, z_]”]

Out[2972]= {Flat, Listable, Protected}

In[2973]:= ClearAllAttributes[x__] :=

Map[Quiet[ClearAttributes[#, Attributes[#]];] &, {x}][[1]]

In[2974] := SetAttributes[G, {Flat, Protected}]; SetAttributes[V, {Protected}]

In[2975]:= Map[Attributes, {G, V}]

Out[2975]= {{Flat, Protected}, {Protected}}

In[2976]:= ClearAllAttributes[G, V]; Attributes[G]

Out[2976]= {}

The represented means equally with Attributes1 andSetAttributes1 [33,48] of work with attributes that are most actual for objects of the type {Function, Block,Module}, in some cases are rather useful. At that, these means can be used quite effectively at programming and other means ofdifferent purpose, first of all, of means of the system character.

The mechanism of the Mathematica attributes is quite effective tool both for protection of objects against modifications, and for management of a mode of processing of arguments at calls of blocks, functions and modules. So, by means of assignment to a procedure or function of theListable attribute can be specified that this procedure or function has to be applied automatically to all actual arguments as for a list elements. In the following fragment the simple procedure is presented, whose callCallListable[x, y] returns the list of valuesMap[x,Flatten [{y}]], wherex – a block, function or module from one formal argument, andy – the list or sequence of the actual arguments that can be and empty. The fragment represents source code and the most typical examples of usage of

theCallListable procedure.

In[2977]:= ToString[{a, b, c + d, 72, x*y, (m + n)*Sin[p–t]}]

Out[2977]= “{a, b, c+ d, 72, x y, (m+ n) Sin[p– t]}”

In[2978]:= CallListable[x_ /; SystemQ[x] || BlockFuncModQ[x], y___] := Module[{a

= Attributes[x]}, If[MemberQ[a, Listable], x[Flatten[{y}]], SetAttributes[x, Listable]; {x[Flatten[{y}]], ClearAttributes[x, Listable]}[[1]]]]

In[2979] := CallListable[ToString, {a, b, c + d, 80, x*y, (m + n)*Sin[p–t]}] Out[2979]=

{”a“, “b“, “c+ d“, “80“, “x y“, “(m+ n) Sin[p– t]”}

In[2980]:= CallListable[ToString, a, b, c + d, 480, x*y, (m + n)*Sin[p–t]] Out[2980]=

{”a“, “b“, “c+ d“, “480“, “x y“, “(m+ n) Sin[p– t]”}

In[2981]:= CallListable[ToString]

Out[2981]= {}

The approach used by theCallListable procedure is quite effective and can be used in a number of the appendices programmed in theMathematica.

In conclusion of this section some useful means for receiving the optimized definitions of procedures/functions are in addition represented. So, the call DefFunc[x] provides return of theoptimized definition of anx–object whose definition is located in the user package ornb-document and which has been loaded into the current session. At that, the namex should define an object without any attributes and options; otherwise the erroneous situation arises. The fragment below represents source code of theDefFunc procedure with typical examples of its usage.

In[2461]:= DefFunc[x_ /; SymbolQ[x] || StringQ[x]] :=

Module[{a = GenRules[Mapp[StringJoin, {“Global`”, Context[x]},

ToString[x] <> “`”], ””], b = StringSplit[ToString[InputForm[Definition[x]]], “\n

\n”]}, ToExpression[Map[StringReplace[#, a] &, b]]; Definition[x]] In[2462]:=

Definition[ListListQ]

Out[2462]= ListListQ[AladjevProcedures`ListListQ`L_]:=

If[AladjevProcedures`ListListQ`L!= {}&&

ListQ[AladjevProcedures`ListListQ`L]&&

Length[Select[AladjevProcedures`ListListQ`L, ListQ[#1]&& Length[#1]==

Length[AladjevProcedures`ListListQ`L[[1]]]&]]==

Length[AladjevProcedures `ListListQ`L], True, False] In[2463]:= DefFunc[ListListQ]

Out[2463]= ListListQ[L_]:= If[L!= {}&& ListQ[L]&&

Length[Select[L, ListQ[#1]&& Length[#1]== Length[L[[1]]]&]]== Length[L], True, False]

Naturally, the standard Definition function also is suitable for receiving of definition of an object activated in the current session, but in case of amfile or anb–document exists an essential distinction as is well illustrated by the return of definition of theListListQ function fromAVZ_Package package [48] by means of both theDefinition function, and ourDefFunc procedure. In the second case the obtained definition is essentially more readably, first of all, for large source codes of procedures and functions. With procedures DefFunc1, DefFunc2 andDefFunc3 which are quite useful versions of the aboveDefFunc procedure, the interested reader can familiarize oneself in [28-33]; the means are

presented and in our package [48]. These means also are functionally adjoined by the ToDefOptPF procedure and the OptRes function [28,48]. Meanwhile, theToDefOptPF procedure is inefficient for a case when the user packages with identical contexts have been loaded into the current session [33]. We for the similar purposes widely use the above Definition2 procedure.

Withal, having provided loading of the user package for instance UPackage by the

Withal, having provided loading of the user package for instance UPackage by the

Dans le document Extension of Mathematica systemfunctionality (Page 92-103)