KDP_book
.pdf
Mathematica: Functional and procedural programming
In[2230]:= ListableS[ToString, L]
Out[2230]= {"a", "b", {"c", "d"}, {{"m", "p", "n"}}}
The ListableS procedure can be represented by equivalent function ListableS1 of the list format as follows:
In[2231]:= ListableS1[F_Symbol, x_] := {Save["#", {g, s, t}],
g = Attributes[F], If[MemberQ[g, Listable], s = F[x]; t = 1, SetAttributes[F, Listable]; s = F[x]]; If[t === 1, s, ClearAttributes[F, Listable]; s], Get["#"], DeleteFile["#"]}[[3]]
In[2232]:= {g, s, t} = {42, 47, 67}; ListableS1[F, L]
Out[2232]= {F[a], F[b], {F[c], F[d]}, {{F[m], F[p], F[n]}}} In[2233]:= {g, s, t}
Out[2233]= {42, 47, 67}
The Temporary attribute determines that a symbol has local character, removed when no longer used. For instance, the local procedure variables have the Temporary attribute.
In[90]:= A[x__] := Module[{a = 77}, {a*x, Attributes[a]}]
In[91]:= A[5]
Out[91]= {385, {Temporary}}
In[92]:= A1[x_] := Module[{a = 7}, a = {a*x, Attributes[a], a};
ClearAttributes[a, Temporary]; a]
In[93]:= A1[5]
Out[93]= {35, {Temporary}, 7}
By managing the Temporary attribute, it is possible make the values of the local variables of the procedures available in the current session outside of these procedures, as the previous example illustrates. At that, you can both save the Temporary attribute for them or selectively cancel it.
The ReadProtected attribute prevents expression associated with a W symbol from being seen. In addition, this expression cannot be obtained not only by the function call Definition[W], but also be written to a file, for example, by the function Save, for example:
In[2129]:= G[x_, y_, z_] := x^2 + y^2 + z^2;
In[2130]:= SetAttributes[G, ReadProtected]
In[2131]:= Definition[G]
Out[2131]= Attributes[G] = {ReadProtected}
In[2132]:= Save["###", G]
251
V.Z. Aladjev, M.L. Shishakov, V.A. Vaganov
In[2133]:= Read["###"]
Out[2133]= {ReadProtected}
This attribute is typically used to hide the values of certain program objects, especially procedure and function definitions. While this attribute is cancelled by means of the ClearAttributes function, for example:
In[2141]:= ClearAttributes[G, ReadProtected]
In[2142]:= Definition[G]
Out[2142]= G[x_, y_, z_] := x^2 + y^2 + z^2
The Constant attribute defines all derivatives of a g symbol to be zero, for example:
In[2555]:= SetAttributes[g, Constant] In[2556]:= g[x_] := a*x^9 + b*x^10 + c In[2557]:= Definition[g]
Out[2557]= Attributes[g] = {Constant} + c g[x_] := a*x^9 + b*x^10
In[2558]:= Map[D[g, {x, #}] &, Range[10]]
Out[2558]= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
The Locked attribute prohibits attributes change of a symbol:
In[2654]:= ClearAttributes[Vs, {Locked}]
…Attributes: Symbol Vs is locked. In[2655]:= Attributes[Vs]
Out[2655]= {Listable, Locked} In[2656]:= Clear[Vs]; Attributes[Vs]
Out[2656]= {Listable, Locked} In[2657]:= ClearAll[Vs]; Attributes[Vs]
…ClearAll: Symbol Vs is locked. Out[2657]= {Listable, Locked}
In[2658]:= ClearAll[Gs]
…ClearAll: Symbol Gs is Protected. In[2659]:= Attributes[Gs]
Out[2659]= {Protected}
Note, that unlike the declaration by the Mathematica the function ClearAll to override a symbol attributes, this method does not work if the symbol has {Protected, Locked} attributes, as illustrated by the fragment above. The Mathematica claims, the call ClearAll[g1, g2,…] clears all values, definitions, defaults,
252
Mathematica: Functional and procedural programming
attributes, messages, associated with {g1,g2,…} symbols whereas in reality it is not quite so. In addition, the Remove function also does not affect symbols with the {Protected, Locked} attributes. On the other hand, a symbol x with attributes {Protected, Locked} is saved in a w file by means of the functions call Save[w, x] and Write[w, Definition[x]] with saving of all attributes ascribed to the x symbol. At the same time, attributes assigned to a symbol x are relevant only within the current session, being lost in the new session. Calling Unlocked[f] deletes the current document nb by returning the updated nb document (by replacing the Locked attribute with the Stub attribute) and saving it to a nb–file f.
In[2759]:= Unlocked[fn_] := Module[{a = NotebookGet[]},
a = ReplaceAll[a, "Locked" –> "Stub"]; NotebookClose[]; NotebookSave[a, fn]]
In[2760]:= Unlocked["C:\\Temp\\Exp.nb"]
The NumericFunction attribute of a procedure or function F indicates that F[x1, x2, x3, …] should be considered a numerical quantity whenever all its arguments are numerical quantities:
In[2858]:= Attributes[Sin]
Out[2858]= {Listable, NumericFunction, Protected}
The Orderless attribute of a procedure or function indicates that its arguments are automatically sorted in canonical order. This property is accounted for in pattern matching.
In[2953]:= SetAttributes[F, Orderless] In[2954]:= F[n, m, p, 3, t, 7, a]
Out[2954]= F[3, 7, a, m, n, p, t] In[2955]:= F[z_, y_, x_] := x + y + z In[2956]:= Definition[F]
Out[2956]= Attributes[F] = {Orderless} F[x_, y_, z_] := x + y + z
In[2957]:= SetAttributes[g, Orderless]
In[2958]:= L = {n, m, u, 3, t, 7, a, c, u, d, s, j, a, p}; v := g @@ L;
Map[Part[v, #] &, Range[Length[L]]]
Out[2958]= {3, 7, a, a, c, d, j, m, n, p, s, t, u, u}
The last example of the previous fragment illustrates using of the Orderless attribute to sort lists in lexicographical order.
253
V.Z. Aladjev, M.L. Shishakov, V.A. Vaganov
3.8. Additional tools expanding the built–in Mathematica functions, or its software as a whole
The string and list structures are of the most important in the Mathematica, they both are considered in the previous two chapters in the context of means, additional to the built-in tools, without regard to a large number of the standard functions of processing of structures of this type. Quite naturally, here it isn't possible to consider all range of standard functions of this type, sending the interested reader to the reference information on the Mathematica or to the appropriate numerous publications. It is possible to find many of these publications on the website http://www.wolfram.com/books. Having presented the means expanding the built–in Mathematica software in the context of processing of string and list structures in the present item we will represent the means expanding the Mathematica that are oriented on processing of other types of objects. Above all, we will present some tools of bit–by–bit processing of symbols.
The Bits procedure significantly uses function BinaryListQ, providing a number of useful operations during of operating with symbols. On the tuple of factual arguments <x, p>, where x – a 1–symbol string (character) and p – an integer in the range 0 .. 8, the call Bits[x, p] returns binary representation of the x in the form of the list, if p = 0, and p–th bit of such representation of a symbol x otherwise. While on a tuple of actual arguments <x, p>, where x – a nonempty binary list of length no more than 8 and p = 0, the procedure call returns a symbol corresponding to the set binary x list; in other cases the call Bits[x,p] is returned as unevaluated. The fragment below represents source code of the procedure Bits along with an example of its application.
In[7]:= Bits[x_, P_ /; IntegerQ[P]] := Module[{a, k},
If[StringQ[x] && StringLength[x] == 1, If[1 <= P <= 8, PadLeft[IntegerDigits[ToCharacterCode[x][[1]], 2], 8][[P]], If[P == 0, PadLeft[IntegerDigits[ToCharacterCode[x][[1]], 2], 8], Defer[Bits[x, P]]]],
If[BinaryListQ[x] && 1 <= Length[Flatten[x]] <= 8, a = Length[x]; FromCharacterCode[Sum[x[[k]]*2^(a – k), {k, a}]], Defer[Bits[x, P]]]]]
254
Mathematica: Functional and procedural programming
In[8]:= Map9[Bits, {"A", "A", {1, 0, 0, 0, 0, 0, 1}, "A", {1, 1, 1, 1, 0, 1}}, {0, 2, 0, 9, 0}]
Out[8]= {{0, 1, 0, 0, 0, 0, 0, 1}, 1, "A", Bits["A", 9], "="}
If the previous Bits procedure provides a simple enough processing of symbols, the two procedures BitSet1 and BitGet1 provide the expanded bit–by–bit information processing like our Maple procedures [16]. In the Maple we created a number of procedures (Bit, Bit1, xNB, xbyte1, xbyte) that provide bit– by–bit information processing [22-28,42]; the Mathematica has similar means too, in particular, the call BitSet[n, k] returns the result of setting of 1 to the k-th position of binary representation of an integer n. The procedure call BitSet1[n,p] returns result of setting to positions of the binary representation of an integer n that are determined by the first elements of sub-lists of a nested p list, {0|1} – values; in addition, in a case of non-nested p list a value replacement only in a single position of n integer is made. Procedures BitSet1 and BitGet1 are included in our package [16].
It should be noted that the BitSet1 procedure functionally expands both the standard function BitSet, and BitClear of the Mathematica while the procedure BitGet1 functionally extands the standard functions BitGet and BitLength of the system. The call BitGet1[n, p] returns the list of bits in the positions of binary representation of an integer n that are defined by a p list; at the same time, in a case of an integer p the bit in position p of binary representation of n integer is returned. While the procedure call BitGet1[x, n, p] through a symbol x in addition returns number of bits in the binary representation of an integer n. The above means rather wide are used at bit–by–bit processing.
In the Mathematica the transformation rules are generally determined by the Rule function, whose call Rule[a, b] returns the transformation rule in the form a –> b. These rules are used in transformations of expressions by the functions ReplaceAll,
Replace, ReplaceRepeated, StringReplace, StringReplaceList, ReplacePart, StringCases, that use either one rule, or their list as simple list, and a list of ListList type. For dynamic generation of such rules the GenRules procedure can be useful, whose call
255
V.Z. Aladjev, M.L. Shishakov, V.A. Vaganov
GenRules[x, y] depending on a type of its arguments returns a single rule or list of rules; the procedure call GenRules[x, y, z] with the third optional z argument – any expression – returns the list with single transformation rule or the nested list of ListList type. Depending on the coding format, the call returns result in the following formats, namely:
(1) GenRules[{x, y, z,…}, a] {x –> a, y –> a, z –> a,…}
(2) GenRules[{x, y, z,…}, a, h] {{x –> a}, {y –> a}, {z –> a},…} (3) GenRules[{x, y, z,…}, {a, b, c,…}] {x –> a, y –> b, z –> c,…}
(4) GenRules[{x, y, z,…}, {a, b, c,…}, h] {{x –> a}, {y –> b}, {z –> c},…} (5) GenRules[x, {a, b, c,…}] {x –> a}
(6) GenRules[x, {a, b, c,…}, h] {x –> a}
(7) GenRules[x, a] {x –> a}
(8) GenRules[x, a, h] {x –> a}
The GenRules procedure is useful, in particular, when in a procedure or function it is necessary to dynamically generate the transformation rules depending on conditions. The following fragment represents source code of the GenRules procedure and the most typical examples of its application onto all above cases of coding of the procedure call.
In[7]:= GenRules[x_, y_, z___] := Module[{a, b = Flatten[{x}],
c = Flatten[If[ListQ /@ {x, y} == {True, False}, PadLeft[{}, Length[x], y], {y}]]}, a = Min[Length /@ {b, c}]; b = Map9[Rule, b[[1 ;; a]], c[[1 ;; a]]];
If[{z} == {}, b, b = List /@ b; If[Length[b] == 1, Flatten[b], b]]]
In[8]:= {GenRules[{x, y, z}, {a, b, c}], GenRules[x, {a, b, c}], GenRules[{x, y}, {a, b, c}], GenRules[x, a], GenRules[{x, y}, a]}
Out[8]= {{x → a, y → b, z → c}, {x → a}, {x → a, y → b}, {x → a}, {x → a, y → a}}
In[9]:= {GenRules[{x, y, z}, {a, b, c}, 7], GenRules[x, {a, b, c}, 42], GenRules[x, a, 6], GenRules[{x, y}, {a,b,c}, 7], GenRules[{x, y}, a, 72]}
Out[9]= {{{x → a}, {y → b}, {z → c}}, {x → a}, {x → a}, {{x → a}, {y → b}}, {{x → a}, {y → a}}}
Modifications GenRules1÷GenRules3 of the above procedure are quite useful in many applications [1-15]. A number of tools of the MathToolBox package essentially use means of so–called
GenRules–group [16].
256
Mathematica: Functional and procedural programming
Considering the importance of the map function, starting with Maple 10, the option `inplace`, admissible only at use of the map function with rectangular rtable–objects at renewing these objects in situ was defined. While for objects of other type this mechanism isn't supported as certain examples from [18,21–42] illustrate. For the purpose of disposal of this shortcoming was offered a quite simple MapInSitu procedure [42]. Along with it the similar tools for Mathematica in the form of two functions
MapInSitu, MapInSitu1 and the MapInSitu2 procedure have been offered. With mechanisms used by the Maple procedure
MapInSitu and Math–tools MapInSitu÷MapInSitu2 the reader can familiarize in [6-16,27,42]. Tools of the MapInSitu-group for both systems are characterized by the prerequisite, the second argument at their call points out on an identifier in the string format to which a certain value has been ascribed earlier and that is updated "in situ" after its processing by the {map|Map} tool. Anyway, the calls of the tools return Map[x, y] as a result.
The following procedure makes grouping of expressions that are set by x argument according to their types defined by the Head2 procedure; in addition, a separate expression or their list is coded as a x argument. The procedure call GroupNames[x] returns simple list or nested list whose elements are lists whose first element – an object type according to the Head2 procedure, whereas the others – expressions of this type. The next fragment represents source code of the GroupNames procedure with an example of its typical application.
In[7]:= GroupNames[x_] := Module[{a = If[ListQ[x], x, {x}], c, d, p, t, b = {{"Null", "Null"}}, k = 1},
For[k, k <= Length[a], k++, c = a[[k]]; d = Head2[c]; t = Flatten[Select[b, #[[1]] === d &]]; If[t == {} && (d === Symbol && Attributes[c] === {Temporary}), AppendTo[b, {Temporary, c}],
If[t == {}, AppendTo[b, {d, c}], p = Flatten[Position[b, t]][[1]];
AppendTo[b[[p]], c]]]]; b = b[[2 ;; -1]]; b = Gather[b, #1[[1]] == #2[[1]] &]; b = Map[DeleteDuplicates[Flatten[#]] &, b]; If[Length[b] == 1, Flatten[b], b]]
257
V.Z. Aladjev, M.L. Shishakov, V.A. Vaganov
In[8]:= GroupNames[{Sin, Cos, ProcQ, Locals2, 90, Map1, StrStr, 72/77, Avz, Nvalue1, a + b, Avz, 77, Agn, If, Vsv}]
Out[8]= {{"System", Sin, Cos, If}, {"Module", ProcQ, Locals2, Nvalue1, Agn}, {Integer, 90, 77}, {"Function", Map1, StrStr},
{Rational, 72/77}, {Temporary, Avz, Vsv}, {Plus, a + b}}
The procedure call RemoveNames[] without any arguments provides removal from the current Mathematica session of the names, whose types are other than procedures and functions, and whose definitions have been evaluated in the current session; moreover, the names are removed so that aren't recognized by the Mathematica any more. The procedure call RemoveNames[] along with removal of the above names from the current session returns the nested 2-element list whose first element defines the list of names of procedures, while the second element – the list of names of functions whose definitions have been evaluated in the current session. The following fragment represents source code of the RemoveNames procedure and an example of its use.
In[7]:= RemoveNames[x___] := Module[{a = Select[Names["`*"], ToString[Definition[#]] != "Null" &], b},
ToExpression["Remove[" <> StringTake[ToString[MinusList[a, Select[a, ProcQ[#] || ! SameQ[ToString[Quiet[DefFunc[#]]], "Null"]||Quiet[Check[QFunction[#], False]] &]]], {2, -2}] <> "]"]; b = Select[a, ProcQ[#] &]; {b, MinusList[a, b]}]
In[8]:= RemoveNames[]
Out[8]= {{"Art", "Kr", "Rans"}, {"Ian"}}
The above procedure is an useful tool in some appendices connected with cleaning of the working Mathematica field from definitions of the non–used symbols. The procedure confirmed a certain efficiency in management of random access memory.
In the context of use of the built-in functions Nest and Map for definition of new pure functions on a basis of the available ones, we can offer the procedure as an useful generalization of the built-in Map function, whose call Mapp[F, E, x] returns the result of application of a function/procedure F to an expression E with transfer to it of the factual arguments defined by a tuple of x expressions which can be empty. In a case of the empty x
258
Mathematica: Functional and procedural programming
tuple the identity Map[F, E] ≡ Mapp[F, E] takes place. As formal arguments of the built-in function Map[w, g] act the f name of a procedure/function while as the second argument – an arbitrary g expression, to whose operands of the 1st level the w is applied. The following fragment represents the source code of the Mapp procedure and a typical example of its application.
In[308]:= Mapp[f_ /; ProcQ[f] || SysFuncQ[f] ||
SymbolQ[f], Ex_, x___] := Module[{a = Level[Ex, 1], b = {x}, c = {}, h, g = Head[Ex], k = 1}, If[b == {}, Map[f, Ex], h = Length[a]; For[k, k <= h, k++,
AppendTo[c, ToString[f] <> "[" <> ToString1[a[[k]]] <> ", " <> ListStrToStr[Map[ToString1, {x}]] <> "]"]]; g @@ Map[ToExpression, c]]]
In[309]:= Mapp[F, {a, b, c}, x, y, z]
Out[309]= {F[a, "F", y, z], F[b, "F", y, z], F[c, "F", y, z]}
In[310]:= Mapp[ProcQ, {Sin, ProcQ, Mapp, Definition2, StrStr}]
Out[310]= {False, True, True, True, False}
Note that algorithm of the Mapp procedure is based on the following relation, namely:
Map[F, Exp] ≡ Head[Exp][Sequences[Map[F, Level[Exp, 1]]]]
whose rightness follows from definition of the standard Level, Map, Head functions and our Sequences procedure considered in [6,8-16]. The relation can be used and at realization of cyclic structures for the solution of problems of other directionality, including programming on a basis of use of mechanism of the pure functions. While the Mapp procedure in the definite cases rather significantly simplifies programming of various tasks. The Listable attribute for a function f determines that it will be automatically applied to elements of the list which acts as its argument. Such approach can be used rather successfully in a number of cases of programming of blocks, functions, modules. In this context a rather simple Mapp1 procedure is of interest, whose call Mapp1[x,y] unlike the call Map[x,y] returns the result of applying of a block, function or module x to all elements of y list, regardless of their location on list levels. Meanwhile, for a number of functions and expressions the Listable attribute does
259
V.Z. Aladjev, M.L. Shishakov, V.A. Vaganov
not work, and in this case the system provides special functions Map and Thread that in a certain relation can quite be referred to the structural means that provide application of functions to parts of expressions. In this regard we programmed a group of a rather simple and at the same time useful enough procedures and functions, so-called Map–group which rather significantly expand the built–in Map function. The Map–group consists of 25 tools Map1÷Map25 different complexity levels. These tools are considered in detail in [5-14], they included in our package MathToolBox [16]. The above means from Map–group rather significantly expand functionality of the built–in Map function. In a number of cases the means allow to simplify programming of procedures and functions.
An useful enough modification of standard Map function is the MapEx function whose call returns the list of application of symbol f to those elements of a list that satisfy a testing function w (block, function, pure function, or module from one argument) or whose positions are defined by the list of positive integers w. The built-in function call MapAll[f, exp] applies f symbol to all subexpressions of an exp expression which are on all its levels. Whereas the procedure call MapToExpr[f, y] returns the result of application of a symbol f or their list only to all symbols of y expression. Furthermore, from the list f are excluded symbols entering into the y expression. For example, in a case if f = {G, S} then applying of f to a symbol w gives G[S[w]]. At absence of acceptable f symbols the call returns the initial y expression. The call MapToExpr[f,y,z] with the 3rd optional z argument – a symbol or their list – allows to exclude the z symbols from applying to them f symbols. In certain cases the procedure is a rather useful means at expressions processing.
The procedure MapListAll substantially adjoins the above Map–group. The call MapAt[F, expr, n] of the standard MapAt function provides applying F to the elements of an expression expr at its positions n. While the procedure call MapListAll[F, j] returns the result of applying F to all elements of a list j. At that, a simple analogue of the above procedure, basing on mechanism
260
