## Mathematica: Functional and procedural programming

_{ }**International Academy of Noosphere**

**the Baltic branch**

**V. Aladjev, M. Shishakov,**

**V. Vaganov**

**Functional and procedural programming in Mathematica**

**Second edition**

**Lulu Press – 2020**

**Functional and procedural programming in Mathematica.V. Aladjev, M. Shishakov, V. Vaganov.**

**–**

**Lulu Press**

**, 396 p., 2020.**Software presented in the book contains a number of useful and effective receptions of the procedural and functional programming in * Mathematica* that extend the system software and allow sometimes much more efficiently and easily to program the software for various purposes. Among them there are means that are of interest from the point of view of including of their or their analogs in

*at the same time they use approaches, rather useful in programming of various applications. In addition, it must be kept in mind that the classification of the presented tools by their appointment in a certain measure has a rather conditional character because these tools can be crossed substantially among themselves by the functionality.*

**Mathematica,**The freeware package * MathToolBox* containing more

*tools is attached to the present book. The*

**1420***not only contains a number of useful procedures and functions, but can serve as a rather useful collection of programming examples using both standard and non*

**MathToolBox***standard techniques of functional*

**–***procedural programming*

**–**

**.**The book is oriented on a wide enough circle of the users from computer mathematics systems, researchers, teachers and students of universities for courses of computer science, physics, mathematics, and a lot of other natural disciplines. The book will be of interest also to the specialists of industry and technology which use the computer mathematics systems in own professional activity. At last, the book is a rather useful handbook with fruitful methods on the procedural and functional programming in the * Mathematica* system.

**Mathematica 2,**** ****5**** ****÷**** ****12.1.1.0 – trademarks of Wolfram Research Inc.**

**Printed by Lulu Press**

**December, 2020**

**©**** **<* 2020*>

*by*

**V. Aladjev, M. Shishakov, V. Vaganov**

**Contents**

**Introduction****5**

**Chapter 1:****The user functions in****Mathematica **** **** 7**

1.1.* *The user functions, defined intuitively 8

1.2.* *The user pure functions 12

1.3. Some useful tools for work with the user functions 20

**Chapter 2:****The user procedures in****Mathematica **** ****28**

2.1. Definition of procedures in * Mathematica* software 29

2.2. Headings of procedures 38

2.3. Optional arguments of procedures and functions 57

2.4. Local variables in * Mathematica* procedures 71

2.5. Exit mechanisms of the user procedures 86

2.6. Tools for testing of procedures and functions 94

2.7. The nested blocks and modules 102

**Chapter 3:****Programming tools of the user procedure body ****107**

3.1. Branching control structures in the * Mathematica *111

***** Conditional branching structures 111

***** Unconditional transitions 115

3.2. Cyclic control structures in the **Mathematica **** *** *120

3.3. Some special types of cyclic control structures in

the* Mathematica *system

*125*

3.4. * Mathematica* tools for string expressions 130

***** Replacements and extractions in strings 141

***** Sub-strings processing in strings 143

***** Expressions containing in strings 155

3.5. * Mathematica* tools for lists processing 160

3.6. Additional tools for the **Mathematica **** *** *197

3.7. Attributes of procedures and functions 248

3.8. Additional tools expanding the built* -*in

* Mathematica* functions, or its software as a whole 254

3.9. Certain additional tools of expressions processing

in the * Mathematica* software 272

***** Tools of testing of correctness of expressions 273

***** Expressions processing at level of their components 277

***** Replacement sub-expressions in expressions 285

***** Expressions in strings 297

**Chapter**** ****4:**** ****Software**** ****for**** ****input****-****output**** ****in**** ****Mathematica 300**

4.1. Tools of * Mathematica* for work with internal files 300

4.2. Tools of * Mathematica* for work with external files 305

4.3. Tools of * Mathematica* for attributes processing of

directories and data files 316

4.4. Additional tools for files and directories processing

of file system of the computer 323

4.5. Special tools for files and directories processing 333

**Chapter 5:****Organization of the user software****341**

5.1. * MathToolBox* package for

*system 345*

**Mathematica**5.2. Operating with the user packages in **Mathematica *** *354

***** The concept of context in **Mathematica **** *** *355

***** Interconnection of contexts and packages 363

5.3. Additional tools of operating with user packages 377

**References****391**

**About the authors **** **** 395**

Book completes our multi* –*year cycle of book publications on general theory of statistics, computer science, cellular automata

**,***and*

**Mathematica***with creation of software for the latest two computer mathematics systems*

**Maple,***and*

**Maple***[42] and [16] accordingly.*

**Mathematica**

All rights reserved. This book or any portion thereof may not be reproduced or

used in any manner whatsoever without the express written permission of the

publisher except for the use of brief quotations in a book review or a scholarly

journal. This book completes a multi-year cycle of our publications in five areas**: ** General theory of statistics

**,**Information science

**,**Cellular automata

**,**

*and*

**Maple***along with creation of software for*

**Mathematica***and*

**Maple**

**Mathematica.**

The authors express deep gratitude and appreciation to Misters * Uwe Teubel *and

*the representatives of the firms*

**Dmitry Vassiliev –***REAG Renewable Energy AG*

**&**

*Purwatt AG*

*(Switzerland)*

*for essential assistance rendered by preparation of the present book.*

**–**

*For contacts***:***aladjev***@***europe.com***,*** **aladjev***@***yandex.ru***,*** **aladjev***@***mail.ru*

**Introduction**

*Systems of computer mathematics* *(***SCM***)* find wide enough application in a whole number of natural, economic and social sciences such as**:*** technologies***,*** chemistry***,*** informatics, mathematics***,*** physics***,*** education***,*** economics***,*** sociology***,*** etc** .* Systems

*and*

**Mathematica***and some others are more and more demanded for learning of mathematically oriented disciplines, in scientifical researches and technologies.*

**Maple,***are main tools for scientists, teachers, researchers, and engineers. The investigations on the basis of*

**SCM***as a rule, well combine algebraical methods with advanced computing methods. In this sense,*

**SCM,***are a certain interdisciplinary area between informatics and mathematics in which researches will be concentrated on the development of algorithms for algebraic*

**SCM***(symbolical)*and numerical calculations, data processing, and development of programming languages along with software for realization of algorithms of this kind and problems of different purpose basing on them.

It is possible to note that among modern * SCM* the leading positions are undoubtedly taken by the

*and*

**Maple***systems, alternately being ahead of each other on this or that indicator. The given statement is based on our long*

**Matematica***term use in different purposes of both systems*

**–***and*

**– Maple***and also work on preparation and edition of the book series and some papers in*

**Mathematica***Russian*and

*English*in this direction [1-42]. At the same time, as a result of expanded use of the above systems were created the package

*for*

**MathToolBox***and library*

**Mathematica***for*

**UserLib6789***[16,42]. All tools from the above library and package are supplied with*

**Maple***freeware*license and have open program code. Programming of many projects in

*and*

**Maple***substantially promoted emergence of a lot of system tools from the above library and package. So, openness of*

**Mathematica***package code allows both to modify the tools containing in it, and to program on their basis own tools, or to use their components in various appendices. Experience of use of library and package showed efficiency of such approach.*

**MathToolBox**In particular, * MathToolBox* package contains more than

*tools of different purpose which eliminate restrictions of a number of standard tools of*

**1420***system, and expand its software with new tools. In this context, this package can serve as a certain additional tool of procedural and functional programming, especially useful in the numerous appendices where certain nonstandard evaluations have to accompany programming. At that, tools represented in this package have a direct relationship to certain principal questions of procedural and functional programming in*

**Mathematica***system, not only for the decision of applied problems, but, above all, for creation of software extending frequently used facilities of the system, eliminating their defects or extending*

**Mathematica***with new facilities. The software presented in the package contains a lot of rather useful and effective receptions of programming in the*

**Mathematica***and extends its software that allows to program the tasks of various purpose more simply and more effectively. A number of tools of the given package is used in the examples illustrating these or those provisions of the book.*

**Mathematica,**In the book basic objects of programming in **Mathematica*** –* functions and procedures are considered that consist the base of functional

*procedural programming. The given book considers some principal questions of*

**–***procedural*

**–**

*functional*programming in

*not only for decision of various applied tasks, but, as well, for creation of software expanding frequently used facilities of the system and/or eliminating their limitations, or expanding the system with new facilities. The important role of functions and procedures take place at creation of effective and intelligible user software in various fields. This also applies to software reliability.*

**Mathematica,** The book is oriented on a wide enough circle of the users of the * CMS,* researchers, mathematicians, physicists, teachers and students of universities for courses of mathematics, computer science, physics, chemistry, etc. The book will be of interest to the specialists of industry and technology, economics, medicine and others too, that use the

*in own professional activity.*

**CMS****Chapter 1: The user functions in Mathematica**

* Function* is one of basic concepts of mathematics, being not less important object in programming systems, not excluding

*system*

**Mathematica***with that difference that function*

**,***as a subject to programming*

**–***very*

**–***significantly differs from strictly mathematical concept of function, considering specific features of programming in the*

*system.*

**Mathematica*** Mathematica* has a large number of functions of different purpose and operations over them. Each function is rather well documented and supplied with the most typical examples of its application. Unfortunately, unlike

*the program code of the*

**Maple,***functions is closed that significantly narrows a possibility of deeper mastering the system and acquaintance with the receptions used by it and a technique of programming.*

**Mathematica**Truth, with rare exception, * Mathematica* allows to make assignments that override the standard built

*in functions and meaning of*

**–***objects. However, program codes of the built*

**Mathematica***in functions of the system remain closed for the user. Names of built*

**–***in functions submit to some general properties, namely*

**–****:**names consist of complete

*English*words, or standard mathematical abbreviations. In addition, the first letter of each name is capitalized. Functions whose names end with

*letter as a rule usually*

**Q**

**"***ask a question*

*and return either*

**",***True*or

*False*.

Many important functions of the * Mathematica* system can be found in our books [1-15], that provide detailed discussions of the built-in functions, the features of their implementation along with our tools [16] which expand or supplement them. A full arsenal of functionality can be found in the system manual. Here we will cover the basic issues of organizing user functions in

*along with some tools that provide a number of important operations over user*

**Mathematica****-**defined functions. Moreover, it is possible to get acquainted with many of them in package

*[16] and in certain our books [1-15]. We pass to definition of the main functional user objects.*

**MathToolBox****1.1.**** ****The classical functions, defined intuitively****.*** *Functions of this type are determines by expressions as follows

**:**

**(a) ****F[****x_,**** ****y_,**** ****z_,**** ****…****] := [****x,**** ****y,**** ****z,**** ****…****]**

**(b)**** F[****x_ ****/;**** ****TestQ****[****x****],**** ****y_,**** ****z_ ****/;**** ****TestQ****[****z****],**** ****…****]**** ****:=**** ****[****x,**** ****y,**** ****z,**** ****…****]**

Definition allows two formats * (a)* and

*from which the first format is similar to the format of a classical mathematical function*

**(b)**

**f(x,**

**y,**

**z,**

**...)**

**=**

****

**(x,**

**y,**

**z,**

*from*

**...)***variables with that difference that for formal arguments*

**n***the object template are used*

**x,y,z,...**

**“****_**

*which can designate any admissible expression of the system while*

**”******

*designate an arbitrary expression from variables*

**(x,y,z,…)**

**x,y,z**

*including constants and function calls, for example*

**...,****:**

In[1425]**:= F[x_, y_, z_] := a*x*b*y + N[Sin[2020]]**

In[1426]**:= F[42, 78, 2020]**

Out[1426]**=** 0**.**044062 **+** 3276*****a*****b

Whereas the second format unlike the first allows to hold testing of actual arguments obtained at function call **F****[****x,**** ****y,**** ****z****] **for validity. It does a testing expression **TestQ****[****x****]** attributed to formal argument e.g. * x –* if at least one testing expression on a relevant argument returns

*False*

*then function call is returned unevaluated, otherwise the function call returns the required value, if at evaluation of expression*

**,******was no an erroneous or especial situation, for example

**:**

In[8]**:= F[x_ /; IntegerQ[x], y_, z_Symbol] := a*x*b*y + c*z**

In[9]**:= F[77, 90, G]**

Out[9]**=** 6930*****a*****b **+** c*****G

In[10]**:= F[77, 90, 78]**

Out[10]**=** F[77, 90, 78]

At the same time, for an actual argument its * Head,* e.g.

*List*

**,***Integer*

**,***String*

**,***Symbol*

*etc, as that illustrates the above example, can act as a test. At standard approach the concept of a function does not allow the use of*

**,***local*variables. As a rule

*system assumes that all variables are global. This means that every time you use a name e.g.*

**Mathematica***the*

**w,***normally assumes that you are referring to the same object. However, at program writing, you may not want all variables to be global. In this case, you need the*

**Mathematica***in different points of a program to be treated as a*

**w***local*variable. At the same time, local variables in function definition can be set using

*modules*. Within

*module*you can give a list of variables which are to be treated as local. This goal can be achieved with help of

*blocks*too. A simple example illustrates the told

**:**

In[47]**:= F[x_, y_] := x*y + Module[**{**a = 5, b = 6**}**, a*x + b*y]**

In[48]**:= F[42, 78]**

Out[48]**=** 3954

In[49]**:=** {**a, b**} **=** {**0, 0**}

Out[49]**=** {0**,** 0}

In[50]**:= F[42, 78]**

Out[50]**=** 3954

In[51]**:= S[x_, y_] := x*Block[**{**a = 5, b = 6**}**, a**/**b*y^2]**

In[52]**:= S[42, 48]**

Out[52]**=** 80640

In[53]**:=** {**a, b**} **=** {0**,** 0}**;** **S[42, 48]**

Out[53]**=** 80640

In addition, pattern object * "___"* or

*is used for formal arguments in a function definition can stand for any sequence of zero or more expressions or for any nonempty sequence of expressions accordingly, for example*

**"__"****:**

In[2257]**:= G[x__] := Plus[x]**

In[2258]**:= G[500, 90, 46]**

Out[2258]**=** 636

In[2259]**:= G1[x___] := Plus[x]**

In[2260]**:=** {**G1[], G1[42, 47, 67]**}

Out[2260]**=** {0**,** 156}

Lack of such definition of function is that the user cannot use local variables, for example, the coefficients of polynomials and other symbols other than calls of *standard* functions or local symbols determined by the artificial reception described above *(otherwise function will depend on their current values in the current session with ***Mathematica*** system)*. So, at such function definition expression **** should depend only on formal arguments. But in a number of cases it is quite enough. This function definition is used to give a more complete view of this object and in certain practical cases it is indeed used [9-12,16].

Meanwhile, using our procedure [16] with program code**:**

In[2274]**:= Sequences[x__] := Module[**{**a = Flatten[**{**x**}**], b**}**,**

**b = "Sequence[" <> ToString1[a] <> "]";**

**a = Flatten[StringPosition[b, **{**"**{**", "**}**"**}**]];**

**ToExpression[StringReplace[b, **{**StringTake[b, **{**a[[1]],**

**a[[1]]**}**] ****–****> "", StringTake[b, **{**a[[****–****1]], a[[****–****1]]**}**] ****–****> ""**}**]]]**

that extends the standard built* -*in

*function and useful in many applications, it is possible to represent another way to define the user functions, modules, and blocks, more precisely their headers based on constructions of the format*

**Sequence****:**

**<****Function name****>@Sequences[****formal args****]** **:=** ****

The following a rather simple example illustrates the told**:**

In[75]**:= [email protected][a_Integer, b_Symbol, c_] := a+b+c**

In[76]**:= Definition[G]**

Out[76]**=** G[a**_**Integer**,** b**_**Symbol**,** c**_**] **:=** a **+** b **+** c

In[77]**:= G[6.7, 5, 7]**

Out[77]**=** G[6* .*7

**,**5

**,**7]

In[78]**:= G[67, m, 7]**

Out[78]**=** 74 **+** m

Naturally, in real programming, this definition of functions is not practical, serving only the purposes of possible methods of defining said objects. In the meantime, such extension of the built* -*in tool allows comparing the capabilities of both tools in determining the underlying objects of the system.

Along with the above types of functions, the * Mathematica* uses also the

*function intended for compilation of the functions which calculate numeric expressions at quite certain assumptions. The*

**Compile***function has the*

**Compile***formats of coding, each of which is oriented on a certain compilation type*

**4****:**

**Compile****[**{* x1, x2,…*}

**,**

**G****]**

**–***compiles a function for calculation of an expression*

**G***in the assumption that all values of arguments*

**x**

**j***{*

**j**

**=****1,**** ****2,**** *** …*}

*have numerical character*

**;****Compile****[**{{**x****1****,**** ****t*** 1*}

**,****{**

**x**

**2**

**,**

**t***}*

**2**

**,****{**

**x**

**3**

**,**

**t***}*

**3**

**,**

*}*

**…****,**

**G****]**

**–***compiles a function for calculation of an expression*

**G***in the assumption that all values of*

**x**

**j***arguments*

*have type*

**t**

**j***{*

**j**

**=**

**1,**

**2,**

*}*

**3,…***accordingly*

**;****Compile****[**{{**x****1****, ****p****1****, ****w*** 1*}

**,****{**

**x**

**2****,**

**p**

**2****,**

**w***}*

**2***}*

**,…**

**,**

**J****]**

**–***compiles a function for calculation of an expression*

**J***in the assumption that values of*

**xj***arguments*

*are*

**w**

**j***ranks of array of objects*

**,***each of that corresponds to a type*

**p***{*

**j**

**j**

**=**

**1,**

**2,**

*}*

**3,…****;**

**Compile****[****s,**** ****W,**** **{{**p****1****,**** ****pw*** 1*}

**,****{{**

**p**

**2**

**,**

**pw***}*

**2**

**,**

*}*

**…****]**

**–**

*compiles a function for calculation of a certain expression*

**W***in the assumption that*

*its*

**s***sub*

**-**

*expressions that correspond*

*to the*

**p**

**k***templates have the*

**p**

**wj***types*

*accordingly*{

**k**

**=**

**1,**

**2,**

**3,**

*}*

**…**

**.** The * Compile* function processes procedural and functional objects, matrix operations, numeric functions, functions for lists processing, etc. Each

*function generates a special object*

**Compile**

**CompiledFunction.****The function call**

**Compile****[**

**…, Evaluate****[**

**w****]]**is used to specify the fact that

*expression should be evaluated symbolically before compilation. For testing of functions of this type a rather simple*

**w***function is used [8]*

**CompileFuncQ****,**whose call

**CompileFuncQ****[**

**x****]**returns

*True*if a

*represents the*

**x***function, and*

**Compile***False*otherwise. The fragment represents source code of the

*function with examples of its use.*

**CompileFuncQ** In[7]**:= V := Compile[**{{**x, _Real**}**, **{**y, _Real**}}**, x*y]; K**** ****:=**** ****(#1*#2)**** ****&;**

**A := Function[**{**x, y**}**, x/y]; H[x_] := Block[**{}**, x]; H[x_, y_]**** ****:=**** ****x**** ****+**** ****y;**

**SetAttributes["H", Protected]; P[x__] := Plus[Sequences[**{**x**}**]];**

**GS[x_ /; IntegerQ[x], y_ /; IntegerQ[y]] := Sin[78] + Cos[42];**

**Sv[x_ /; IntegerQ[x], y_ /; IntegerQ[y]] := x^2 + y^2;**

**Sv = Compile[**{{**x, _Integer**}**, **{**y, _Real**}}**, (x + y)^6];**

**S := Compile[**{{**x, _Integer**}**, **{**y, _Real**}}**, (x + y)^3];**

**G**** ****=**** ****Compile[**{{**x,**** ****_****Integer**}**,**** **{**y,**** ****_****Real**}}**,**** ****(x**/**y)];**

In[8]**:= ****CompileFuncQ[x_] :=**** ****If[SuffPref[ToString1[Definition3[x]]****,**

**"Definition3[CompiledFunction[**{**", 1], True, False]**

In[9]**:= Map[CompileFuncQ, **{**Sv, S, G, V, P, A, K, H, GS, Sv**}**]**

Out[9]**=** {True, True, True, True, False, False, False, False, False, True}

The * CompileFuncQ* function expands testing possibilities of the functional objects in

*by representing a certain interest first of all for the system programming.*

**Mathematica,** Thus, as a reasonably useful version of the built-in * Compile* function, one can represent the

*procedure whose call*

**Compile1**

**Compile1****[**

**f,**

**x,**

**y****]**returns a function of the classical type whose body is defined by an algebraic

*expression, whereas*

**y***defines a name of the generated function and*

**f***defines the list of types attributed to the parameters of an expression*

**x***The factual*

**y.***argument is specified in the format {{*

**x**

**a,**

**T***}*

**a**

**,**

*{*

**b,**

**c,**

**T***}*

**c***}*

**,…****,**where {

**a,**

**b,**

*} defines parameters of the*

**c,…***expression, whereas {*

**y**

**T**

**a**

**,**

**T**

**c***} defines the testing*

**,…***functions while single elements of*

**Q-***defines validity of any expression for corresponding parameter.*

**x** In[10]**:= Compile1[f_ /; SymbolQ[f], x_ /; ListQ[x], y_] :=**

**Module[**{**a = ToString1[y],**** ****b,**** ****c,**** ****d,**** ****g,**** ****h,**** ****t**}**, b = FactualVarsStr1[a];**

**b = Select[b, !**** ****SameQ[#[[1]], "System`"] &][[1]][[2 ;–1]];**

**SetAttributes[g, Listable]; g[t_] := ToString[t];**

**t = Map[ToString, Map[If[ListQ[#], #[[1]], #] &, x]];**

**c = ToString[f] <> "["; d = Map[g, x];**

**Do[h = d[[j]]; If[ListQ[h] && MemberQ[b, h[[1]]],**

**c = c <> h[[1]] <> "_ /;" <> h[[2]] <> "[" <> h[[1]] <> "],",**

**If[MemberQ[b, h], c = c <> h <> "_ ,", 77]], **{**j, Length[d]**}**];**

**t = Complement[b, t];**

**If[t != **{}**, Do[c = c <> t[[j]] <> "_ ,", **{**j, Length[t]**}**], 78];**

**c = StringTake[c, **{**1, –2**}**] <> "] := " <> a; ToExpression[c];**

**Definition[f]]**

In[11]**:= Compile1[f,**** **{**x,**** **{**n,**** ****IntegerQ**}**,**** **{**M,**** ****RationalQ**}**,**** **{**h,**** ****RealQ**}}**,**

**(Sin[h] + a*x^b)**/**(c*M – Log[n])]**

Out[11]**=** f[x**_,** n**_**/**;** IntegerQ[n]**,** M**_**/**;** RationalQ[M]**,** h**_**/**;** RealQ[h]**,**

a**_,** b**_,** c**_**] **:=** (a*****x**^**b **+** Sin[h])/(c*****M * –* Log[n])

In[12]**:= N[f[t****,**** 77****,**** 7**/**8****,**** 7.8****,**** m****,**** n****,**** p]****,**** 3]**

Out[12]**=** (0**.**998543 **+** m*****t**^**n)/(* –*4.34

**+**0

**.**875

*****p)

Fragment above represents source code of the procedure.

**1.2. ****The user pure functions*** .* First of all, we will notice that so–called

*isn*

**functional programming***t any discovery of the*

**'***system, and goes back to a number of software that appeared long before the above system. In this regard, it is pertinently focused slightly more in details the attention on the concept of functional programming in historical aspect. While here we only will note certain moments characterizing specifics of the paradigm of functional programming. We will note only that the foundation of functional programming has been laid approximately at the same time, as*

**Mathematica***imperative*

*programming*that is the most widespread now, i.e. in the thirties years of the last century.

*A. Church*

*(USA)*

*the author of*

**–****λ–**calculus and one of founders of the concept of

*Cellular Automata*in connection with his works in field of infinite automata and mathematical logic along with

*H.*

*Curry*

*(England)*and

*M.*

*Schönfinkel*

*(Germany)*that have developed the mathematical theory of combinators, with good reason can be considered as the founders of mathematical foundation of functional programming. In addition, functional programming languages, especially the purely functional ones such as the

*Hope*and

*Rex*

*have largely been used in academical circles rather than in commercial software. Whereas prominent*

**,***functional*programming languages such as

*Lisp*have been used in the industrial and commercial applications. Today

**,***functional*

*programming paradigm*is also supported in a number of domain-specific programming languages, for example, by the

*language of the*

**Mathem–***From a rather large number of languages of functional programming it is possible to note the following languages that exerted a great influence on progress in this field, namely*

**Mathematica.****:**

*Lisp*

**,***Scheme*

**,***ISWIM*

*family*

**,***ML*

**,***Miranda*

**,***Haskell*

*etc. By and large, if the*

**,***imperative*languages are based on operations of assignment and cycle, the

*functional*languages on recursions. The most important advantages of the functional languages are considered in our books in detail [8-14], namely

**:**

– *programs on functional languages as a rule are much shorter and simpler than their analogues on the imperative languages***;**

– *almost all modern functional languages are strictly typified and ensure the safety of programs***;*** at that, the strict typification allows to generate more effective code***;**

– *in a functional language the functions can be transferred as an argument to other functions or are returned as result of their calls***;**

– *in pure functional languages (which aren***'***t allowing by–effects for the functions) there is no an operator of assigning, the objects of such language can***'***t be modified or deleted, it is only possible to create new objects by decomposition and synthesis of the existing objects. In the pure functional languages all functions are free from by***–***effects*.

Meanwhile, *functional* languages can imitate certain useful *imperative* properties. Not every functional language are a pure forasmuch in a lot of cases the admissibility of *by*–*effects* allows to essentially simplify programming. However, today the most developed functional languages are as a rule pure. With many interesting enough questions concerning a subject of functional programming, the reader can familiarize oneself, for example, in [15]. Whereas with an quite interesting critical remarks on functional languages and possible ways of their elimination it is possible to familiarize oneself in [8-15,22].

A number of concepts and paradigms are quite specific for *functional* programming and absent in *imperative* programming. Meanwhile, many programming languages, as a rule, are based on several paradigms of programming, in particular imperative programming languages can successfully use also concepts of functional programming. In particular, as an important enough concept are so–called the **pure*** functions,* whose results of run depends only on their

*actual*arguments. Such functions possess certain useful properties a part of which it is possible to use for

*optimization*of program code and parallelization of calculations. In principle, there are no special difficulties for programming in the functional style in languages that aren

*t the functional. The*

**'***language supports the mixed paradigm of functional and procedural programming. We will consider the elements of*

**Mathematica***functional*

*programming*in

*in whose basis the concept of the*

**Mathematica***pure*function lays. The

**pure***functions*

*one of the basic concepts of functional programming which is a component of programming system in*

**–***in general.*

**Mathematica**Typically, when a function is called, its name is specified, whereas pure functions allow specifying functions that can be applied to arguments without having to define their explicit names. If a certain function * G* is used repeatedly, then can define the function using definition, considered above, and refer to the function by its name

*On the other hand, if some function is intend to use only once, then will probably find it better to give the function in format of*

**G.***pure*

*function*without ever naming it. The reader that is familiar with formal logic or the

*LISP*programming language, will recognize

**Mathematica***pure*functions as being like

*expressions or*

**λ***not named*

*functions*. Note, that

*pure*

*functions*are also close to the pure mathematical notion of operators.

*uses the following formats for definition of pure functions, namely*

**Mathematica****:**

* (a) Function*[

*]*

**x, body*** (b) Function*[{

**x**

**1**

**, x**

**2**

**, …, x***}*

**n****,**

*]*

**body****(c) body ****&**

Format *(***a***)* determines pure function in which * x* in function

*body*is replaced by any given argument. An arbitrary admissible expression from variable

*including also constants and calls of functions acts as a body. Format*

**x,***(*

**b***)*determines a pure function in which variables

**x**

**1**

**,**

**x**

**2**

**,**

**…,**

**x***in function body is replaced by the corresponding arguments. Whereas format*

**n***(*

**с***)*determines a function body containing formal arguments denoted as

**#**or

**#**

**1,****#**

**2,**

**#**

*etc. It is so*

**3,***called*

**-***format. Note, the pure functions of formats*

**short***(*

**a***)*

**,***(*

**b***)*do not allow to use the

*typification*mechanism for formal arguments similarly to the

*classical*functions, namely constructs of type

*are not allowed. This is a very serious difference between*

**"h_..."***pure*function and

*classical*function whereas otherwise, already when evaluating the definition of any pure function with typed formal arguments,

*identifies the erroneous situations.*

**Mathematica**The calls of pure functions of the above formats are defined according to simple examples below, namely**:**

In[2162]**:= Function[x, x^2 + 42][25]**

Out[2162]**=** 667

In[2163]**:= Function[**{**x, y, z**}**, x^2 + y^2 + z^2][42, 75, 78]**

Out[2163]**=** 13473

In[2164]**:= #1^2 + #2^2 &[900, 50]**

Out[2164]**=** 812500

In[2165]**:= Function[x_Integer, x^2 + 42]**

Function**::**flpar**:** Parameter specification x**_**Integer in **…**

When **Function****[****body****]** or **body**** ****&** is applied to a set of *formal* arguments, **#** *(or ***#1***)* is replaced by the first argument, * #2* by the second, and so on while

*is replaced by the function itself. If there are more arguments than*

**#0***in the function supplied, the remaining arguments are ignored. At that,*

**#j****##**defines sequence of all given arguments, whereas

*stands for arguments from number*

**##n***onward.*

**n***has attribute*

**Function***HoldAll*and function body is evaluated only after the formal arguments have been replaced by actual arguments. Function construct can be nested in any way. Each is treated as a scoping construct, with named inner variables being renamed if necessary. Furthermore, in the call

**Function****[**

**args,**

**body,**

**attrs****]**as optional argument

*can be a single attribute or a list of attributes, e.g.*

**attrs***HoldAll*

**,***Protected*and so on, while the call

**Function****[**

**Null,**

**body,**

**attrs****]**represents a function in which the arguments in function body are given using slot

**#**

*etc. Such format of a pure function is very useful when a one*

**,***time call of the function is required.*

**–**Note that unlike the format *(***c***)** ,* the formats

*(*

**a***)*and

*(*

**b***)*of a pure function allow use as the body rather complex program constructions, including local variables, cycles and definitions of blocks, modules and functions. A simple enough example quite visually illustrates what has been said

**:**

In[7]**:=** {**a, b**} **=** {**0****,**** 0**}

Out[7]**=** {0* ,* 0}

In[8]**:= Function[**{**x,**** ****y,**** ****z**}**,**** ****Save["t",**** **{**a,**** ****b**}**];**** **{**a,**** ****b**}** ****=**** **{**42,**** ****47**}**;**

**g[h_, g_] := h*g; If[x <= 6, Do[Print[**{**a, b, y^z**}**], z], x+y+z];**

{**(a+b)*(x+y+z) + g[42, 47], Get["t"], DeleteFile["t"]**}**[[1]]][1, 2, 3]**

{42, 47, 8}

{42, 47, 8}

{42, 47, 8}

Out[8]**=** 2508

In[9]**:=** {**a, b**}

Out[9]**=** {0**,** 0}

In[10]**:= g[42, 47]**

Out[10]**=** 1974

So, in the given example the locality of variables * a* and

*is provided with saving their initial*

**b***(up to a function call)*values at the time of function call by their saving in the temporary

**"***tmp*

*file, their redefinitions in the course of execution of a function body with the subsequent uploading of initial values of*

**"***and*

**a***from the*

**b**

**"***tmp*

*file to the current session of*

**"***with removal of the*

**Mathematica**

**"***tmp*

*file from the file system of the computer. Such mechanism completely answers the principle of locality of variables in a function body. This example also illustrates the ability to define a new function in the body of a pure function with its use, both within the body of the source function and outside of the function.*

**"**At using of the pure functions, unlike traditional functions, there is no need to designate their names, allowing to code their definitions directly in points of their call that is caused by that the results of the calls of pure functions depend only on values of the actual arguments received by them. Selection from a list * x* of elements that satisfy certain conditions and elementwise application of a function to elements of the list

*can be done by constructions of the view*

**x**

**Select****[**

**x,**

**test****[#]**

**&]**and

**Map****[**

**F****[#]**

**&**

**,**

**x****]**respectively as illustrate the following examples, namely

**:**

In[3336]**:= Select[**{**a, 72, 77, 42, 67, 2019, s, 47, 500**}**, OddQ[#] &]**

Out[3336]**=** {77, 67, 2019, 47}

In[3337]**:= Map[(#^2 + #) &, **{**1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12**}**]**

Out[3337]**=** {2, 6, 12, 20, 30, 42, 56, 72, 90, 110, 132, 156}

At use of the short form of a pure function it is necessary to be careful at its coding because the *ampersand* *(***&***)* has quite low priority. For example, expression **#****1**** ****+**** ****#****2**** ****–**** ****#****3**** ****+**** ****#****2*****#****4**** ****&** without parentheses is correct whereas, in general, they are obligatory, in particular, at use of a pure function as the right part of a rule as illustrate very simple examples [10-12]. The universal format of a call of pure * f* function is defined as

**f**

*{*

**@@***}, for instance*

**args****:**

In[4214]**:= OddQ[#]**** ****||**** ****PrimeQ[#]**** ****||**** ****IntegerQ[#] & @@ **{**78**}

Out[4214]**=** True

In combination with a number of functions, in particular, * Map, Select* and some others the use of pure functions is rather convenient, therefore the question of converting the traditional functions into the pure functions seems an quite topical

**;**for its decision various approaches, including creation of the program converters can be used. Thus, we used pure functions a rather widely at programming of a lot of problems of various types of the applied, and the system character [1-16,22].

Unlike a number of convertors of classical functions to pure function, procedure below allows to keep the testing functions of the general kind for arguments of the converted functions

**W****[****x****_ /; ****Test****[****x****], ****y****_****H****, ****z_, h__H1, t__,**** ****…****] := [****x, y, z, h, t,**** ****…****]**

by converting of a classical * W* function to pure function of short format, i.e. the procedure call

**FuncToPureFunction****[**

**W****]**returns the pure function in the following kind

**If[****Test****[****#1****] && ****HQ****[****#2****] && True && ****H1Q****[****#4****] && True &&**** ****…,**** [****#1, #2, #3, #4, #5,**** ****…****], ****IncorrectArgs****[****Sequential numbers of incorrect factual arguments****]]**** ****&**

where {*heads* * H* and

*} can absent. In addition, for arguments of type {*

**H1**

**h__H1,**

*} the resultant pure function considers only their first factual value. At the same time, only one of the {*

**t__***Real*

**,***List*

**,***Complex*

**,***Integer*

**,***Rational*

**,***String*

**,***Symbol*} list is allowed as a head

*for a*

**H***expression. In a case of inadmissibility of at least one argument and/or its testing*

**y***(for example*

**,***incorrect head*

**H***or*

**H1***)*the call of the pure function returns the formal call of the kind

**IncorrectArgs****[**

**n**

**1**

**,**

**n**

**2**

**,…,**

**n**

**p****],**where {

**n**

**1**

**,**

**n**

**2**

**,…,**

**n***} determine sequential numbers of incorrect arguments. With source code of the*

**p***procedure with typical examples of its application that a quite clearly illustrate the results returned by the procedure can be found below [8-12,16].*

**FuncToPureFunction**In[5]**:= FuncToPureFunction[x_ /; FunctionQ[x]] :=**

**Module[**{**a, b = ProcBody[x], c = 1, d, g, h, p, s = Map[ToString,**

{**Complex, Integer, List, Rational, Real, String, Symbol**}**]**}**,**

**a = ArgsBFM1[x]; g = Map[**{**Set[d, "#" <> ToString[c++]]; d,**

**StringReplaceVars[#[[2]], #[[1]] –> d]**}** &, a];**

**h = Map[If[! StringFreeQ[#[[2]], #[[1]]], #[[2]],**

**If[#[[2]] == "Arbitrary", "True", If[MemberQ[s, #[[2]]], #[[2]] <>**

**"Q[" <> #[[1]] <> "]", "False"]]] &, g];**

**p = Map["(" <> # <> ")" &, h]; p = Riffle[p, "&&"];**

**a = Map[#[[1]] &, a]; c = Map[#[[1]] &, g];**

**a = StringReplaceVars[b, GenRules[a, c]];**

**ToExpression["If[" <> p <> "," <> a <> "," <>**

**"[email protected]@Flatten[Position[" <>**

**ToString[h] <> ", False]]" <> "]&"]]**

In[6]**:= f[x_ /; IntegerQ[x], y_ /; y == 77, z_List, t_, p__, h___] :=**

**x*y*h + Length[z]*t**

In[7]**:= FuncToPureFunction[f]**

Out[7]**=** If[IntegerQ[**#**1] **&&** **#**2 **==** 77 **&&** ListQ[**#**3] **&&** True **&& **True **&&** True**, #**1***#**2***#**6 **+** Length[**#**3]***#**4**, **IncorrectArgs **@@** Flatten[Position[{IntegerQ[**#**1]**,** **#**2 **==** 77**, **ListQ[**#**3]**,** True**,** True**,** True}**,** False]]] **&**

It should be noted that pure functions allow for a kind of *parameterization* based on constructions of the following format**:**

<**Name****[****params****]> := <****Pure function, containing params****>**

where **Name*** –* a name of pure function and

*determines parameters entering the function body. Calls of pure functions parameterized in this way have the following format*

**params****:**

**Name****[****params****][****actual args****]**

The following simple example illustrates the told**:**

In[2215]**:= T[n_, m_] := Function[**{**x, y, z**}**, n*(x + m*y + z)]**

In[2216]**:= T[42, 47][1, 2, 3]**

Out[2216]**=** 4116

In[2217]**:= G[p_, n_] := p*(#1^2 + #2^2*#3^n)**** ****&**

In[2218]**:= G[5, 2][5, 6, 7]**

Out[2218]**=** 8945

In[2219]**:= With[**{**p=5, n=2**}**, p*(#1^2 + #2^2*#3^n) &][5,6,7]**

Out[2219]**=** 8945

In a number of applications such parameterization is quite useful, allowing customizing the tool for application based on parameter values. Some useful tools for working with the user functions are presented below, whereas a wider range of such tools are available for classical functions which are suitable also for many user procedure processing. This should be borne in mind when discussing issues related to the procedures.

**1.3. ****Some useful tools for work with the user functions*** .* For work with functions

*has a wide range of tools for working with functions, including user ones. Here we present a number of tools for working with user functions that do not go to the standard set. First of all, it is of particular interest to test a symbol or expression to be a function. Some of the tools in this direction are presented in our package*

**Mathematica***[16,9-12]. The most common tool of this type is the function*

**MathToolBox***whose definition in turn contains*

**FunctionQ,***and*

**QFunction***procedures and function*

**QFunction1***of the same type, whose call on a symbol or expression*

**PureFuncQ***returns*

**x***True*

*if*

**,***is a function and*

**x***False*otherwise. Program code of the

*function can be presented as follows*

**FunctionQ****:**

In[25]**:=** **FunctionQ[x_] := If[StringQ[x], QFunction1[x] ||**

**PureFuncQ[ToExpression[x]], PureFuncQ[x] || QFunction[x]]**

In[26]**:= y := #1^2 + #2^2 &; **{**FunctionQ[#1^2 + #2^2 &],**

**FunctionQ[y]**}

Out[26]**=** {True**,** True}

In[27]**:= z = Function[**{**x, y, z**}**, If[x <= 6, Do[Print[y^z], z],**

**x + y + z]];**

In[28]**:= FunctionQ[Function[**{**x, y, z**}**, If[x <= 6,**

**Do[Print[y^z], z], x + y + z]]]**

Out[28]**=** True

In[29]**:= FunctionQ[z]**

Out[29]**=** True

In[30]**:= PureFuncQ[Function[**{**x, y, z**}**, If[x <= 6,**

**Do[Print[y^z], z], x + y + z]]]**

Out[30]**=** True

In[31]**:= PureFuncQ[#1^2 + #2^2 &]**

Out[31]**=** True

In[32]**:= G[x_] := Plus[Sequences[x]]**

In[33]**:=** {**FunctionQ**[**G**]**,** **PureFuncQ**[**G**]}

Out[33]**=** {True**,** False}

At the same time, the function call **PureFuncQ****[****w****]** allows to identify object * w* to be a pure function, returning

*True*, if

*is a pure function and*

**w***False*otherwise. This tool along with others provides

*strict*differentiation of such basic element of functional and procedural programming, as a

**function***[8-16]*

**.**The question of determining the formal arguments of user function is of quite certain interest. Built* -*in tools of the system do not directly solve this issue and we have created a number of tools for the purpose of determining the formal arguments of the function, module and block. For a function, this problem is solved e.g. by the

*function with program code*

**ArgsF****:**

In[47]**:= ArgsF[x_] := If[PureFuncQ[x], ArgsPureFunc[x],**

**If[FunctionQ[x],**** ****Args[x],**** ****ToString1[x]**** ****<>**** ****"**** ****–**** ****not**** ****function"]]**

In[48]**:=** **[email protected][a_Integer, b_Symbol, c_] := a+b+c**

In[49]**:= ArgsF[GS]**

Out[49]**=** {a**_**Integer* ,* b

**_**Symbol

*c*

**,****_**}

In[50]**:= H := #1^2 + #2^2*#3^4 &**

In[51]**:= ArgsF[H]**

Out[51]**=** {* "#1", "#2", "#3"*}

In[52]**:= T := Function[**{**x****,**** y****,**** z**}**, x + y + z]; ArgsF[T]**

Out[52]**= **{**"**x**"****,**** "**y**"****,**** "**z**"**}

In[53]**:= ArgsF[Agn]**

Out[53]**=** **"**Agn * –* not function

**"**

The call **ArgsF****[****x****]** returns the list of formal arguments in the string format of function * x,* including pure function, if

*is not a function the call returns the corresponding message. The*

**x***function uses the testing tools*

**ArgsF***and*

**FunctionQ***along with tools*

**PureFuncQ***and*

**Args, ArgsPureFunc,***with which it is possible to get acquainted in [1-12], while the interested reader can get acquainted here with a number of tools*

**ToString1***(that complement the built*

**-***in system tools)*for work with the user functions.

For converting of a pure function of formats *(***a***)* and *(***b***)* to format *(***c***)* the * PureFuncToShort* procedure with the following program code serves

**:**

In[4220]**:= PureFuncToShort[x_ /; PureFuncQ[x]] :=**

**Module[**{**a, b, c, d**}**,**

**If[ShortPureFuncQ[x], x, a = ArgsPureFunc[x]; d = a;**

**b = Map[ToExpression, a]; Map[ClearAll, a];**

**a = Map[ToExpression, a];**

**c = Quiet[GenRules[a, Range2[#, Length[a]]]];**

{**ToExpression[ToString1[ReplaceAll[x[[2]], c]] <> "&"],**

**ToExpression[ToString[d] <> "=" <> ToString1[b]]**}**[[1]]]]**

In[4221]**:= G := Function[**{**x, y, z**}**, p*(x + y + z)];**

In[4222]**:= PureFuncToShort[G]**

Out[4222]**= **p*****(**#**1** + #**2** + #**3)** &**

The procedure call **PureFuncToShort****[****w****]** returns the result of converting of a pure function * w* to its short format. In turn, the

*procedure is intended for converting of a pure function to classical. The following example presents its program code with a simple example of its application*

**PureFuncToFunction****:**

In[7]**:= ****PureFuncToFunction****[x_/;**** ****PureFuncQ****[x], y_/;**** ****!****HowAct****[****y****]]:=**

**Module[**{**a = ArgsPureFunc[x], b, c**}**,**

**If[ShortPureFuncQ[x], b = (StringReplace[#1, "#" ****–****> "x"] &) /@ a;**

**c = StringReplace[ToString1[x], GenRules[a, b]];**

**b = ToExpression /@ Sort[(#1 <> "_" &) /@ b];**

**ToExpression[ToString1[y[Sequences[b]]] <> ":=" <>**

**StringTake[c, **{**1, ****–****3**}**]], a = (#1 <> "_" &) /@ a;**

**ToExpression[ToString1[y[Sequences[ToExpression /@ a]]] <> ":="**

**<> ToString1[x[[2]]]]]]**

In[8]**:= t := p*(#1^2 + #2^2*#3^n) &**

In[9]**:= PureFuncToFunction[t, H]**

In[10]**:= Definition[H]**

Out[10]**=** H[x1**_,** x2**_,** x3**_**] **:=** p*****(x1**^**2 **+** x2**^**2*****x3**^**n)

The procedure call with two arguments * x* and

*where*

**H,**

**x***a pure function and*

**–***an undefined symbol, converts the pure*

**H –***function to a classical function named*

**x**

**H.**We have programmed a number of procedures that ensure the mutual conversion of classical, pure and pure functions of the short format. In particular, the * CfToPure* procedure allows the classical functions to be converted into pure functions of the short format [12-16]. Calling the

**CfToPure****[**

**f****]**procedure returns the result of converting a classical function

*to its equivalent in the form of a pure function of short format. The procedure uses a number of techniques useful in practical programming, which are recommended to the reader. The fragment below represents source code of the*

**f***procedure and examples of its use.*

**CfToPure** In[4]**:= **{**x, y, z**}** = **{**42, 47, 67**}**;**

In[5]**:= F[x_Integer, y_, z_ /; IntegerQ[z]] := (x^2 + y^3) +**

**(y^2 ****–**** x*y*z)**/**Sqrt[x^2 + y^2 + z^2]**

In[6]**:= CfToPure[f_ /; FunctionQ[f]] := Module[**{**a, b, c, d**}**,**

**a = Map[ToString[#] <> "@" &, Args[f]];**

**a = Map[StringReplace[#, "_" ~~ ___ ~~ "@" ****–****> ""] &, a];**

**d = "###"; Save2[d, a];**

**b = Map["#" <> ToString[#] &, Range[Length[a]]];**

**Map[Clear, a]; c = GenRules[a, b];**

**c = Map[ToExpression[#[[1]]] ****–****> ToExpression[#[[2]]]**** ****&,**** ****c];**

**a = StringReplace[Definition2[f][[1]],**

**Headings[f][[2]] <> "**** ****:=**** ****" ****–****> ""]; a**** ****=**** ****ToExpression[a**** ****<>**** ****"**** ****&"];**

{**ReplaceAll[c][a],**** ****Get[d],**** ****DeleteFile[d]**}**[[1]]]**

In[7]**:= CfToPure[F]**

Out[7]**=** (x**^**2 **+** y**^**3) **+** (y**^**2 **–** x*****y*****z)/Sqrt[x**^**2 **+** y**^**2 **+** z**^**2] **&**

In[8]**:=** {x* ,* y

*z}*

**,**Out[8]**=** {42* ,* 47

*67}*

**,**In[9]**:= G[x_Integer****,**** y_List****,**** z_ /; IntegerQ[z]] := N[Sin[x]**/

**Log[Length[y]] + (y^2 – x*y*z)^(x+z)**/**Sqrt[x^2+y^2+z^2]]**

In[10]**:= CfToPure[G]**

Out[10]**=** N[Sin[**#**1]/Log[Length[**#**2]] **+** (**#**2**^**2 **–** **#**1***#**2***#**3)**^**

(**#**1 **+** **#**3)/Sqrt[**#**1**^**2 **+** **#**2**^**2 **+** **#**3**^**2]] **&**

As in a function body along with formal arguments global variables and calls of functions can enter, then the problem of determination them is of a certain interest to any function. In this regard the * GlobalsInFunc* function can be useful enough with the following program code

**:**

In[2223]**:= ****VarsInFunc[x_] := Complement[Select[VarsInExpr[**

**ToString2[Definition[x]]], ! SystemQ[#] &],**

{**ToString[x]**}**, ArgsBFM[x]];**

**GlobalsInFunc[x_] := If[PureFuncQ[x],**

**Complement[VarsInExpr[x], Flatten[**{**ArgsPureFunc[x],**

**"Function"**}**]], If[FunctionQ[x], VarsInFunc[x],**

**"Argument ****–**** not function"]]**

In[2224]**:= F[x_, y_, z_] := a*x*b*y + N[Sin[2020]]**

In[2225]**:= GlobalsInFunc[F]**

Out[2225]**= **{**"**a**"****,**** "**b**"**}

In[2226]**:= G := Function[**{**x, y, z**}**, p*(x + y + z)];**

In[2227]**:= GlobalsInFunc[G]**

Out[2227]**= **{**"**p**"**}

In[2228]**:= T := p*(#1^2 + #2^2*#3^n)**** ****&**

In[2229]**:= GlobalsInFunc[T]**

Out[2229]**= **{**"**n**"****,**** "**p**"**}

The call **GlobalsInFunc****[****x****]** returns the list of global symbols in string format entering a function * x* definition

*(pure or classical)*and other than the built

**-**in symbols of

*if*

**Mathematica,***is not a function, than the call returns the corresponding message. The function uses the tools of our*

**x***package [7,8,16], in particular the function whose call*

**MathToolBox**

**VarsInFunc****[**

**x****]**returns the list of global symbols in string format entering a

*classical*function

*definition and other than the built*

**x***in symbols of the system.*

**-**Generally, the user functions do not allow to use the local variables, however a simple artificial reception allows to do it. Sequential list structure of execution of operations when the list is evaluated element* –*wise from left to right is for this purpose used, i.e. function is represented in the following format

**:**

**Name****[****args****] := **{**Save****["#"****,**** **{* locals*}

**],**{

**locals****=**

*}*

**values****,**

**function body****,**

**Get****["#"],**

**DeleteFile****["#"]**}

**[[3]]**

The presented format is rather transparent and well illustrates essence of the method of use in user function of local variables. The following simple example illustrates told**:**

In[9]**:= ****GS****[****x****_, ****y****_, ****z****_] := **{**Save****["****#****", **{**a****,**** ****b****,**** ****c**}**], **{**a****=2,**** ****b****=7,**** ****c****=6**}**,**

**a*x + b + y + c*z, Get["#"], DeleteFile["#"]**}**[[3]]**

In[10]**:=** {**a, b, c**} **=** {**1, 2, 3**}

Out[10]**=** {1* ,* 2

*3}*

**,**In[11]**:= GS[42, 47, 67]**

Out[11]**=** 540

In[12]**:=** {a**,** b**,** c}

Out[12]**=** {1**,** 2**,** 3}

In some cases, the given approach may prove to be quite useful in practical programming. A number of our software tools have effectively used this approach.

Meanwhile, a rather significant remark needs to be made regarding the objects multiplicity of definitions with the same name. As noted repeatedly, * Mathematica* system differentiates objects, above all, by their headers, if any. It is therefore quite real that we may deal with different definitions under the same name. This applies to all objects that have headers. In view of this circumstance, we have programmed a number of tools for various cases of application [1-16]. First of all, we need a tool of testing the presence of such multiplicity for a particular object

*(function*

**,***module*

**,***block)*. This function is successfully performed by the

*procedure with program code*

**MultipleQ****:**

In[47]**:= ****MultipleQ[x_ /; SymbolQ[x], j___] := Module[**{**a**}**,**

**a = ToString[InputForm[Definition[x]]];**

**a = StringReplace[a, "\n \n" "\[CircleDot]"];**

**a = StringSplit[a, "\[CircleDot]"];**

**If[**{**j**}** ****!= **{}** ****&& !ValueQ[j],**** ****j=a];**** ****If[Length[a]**** ****>**** ****1,**** ****True****,**** ****False****]]**

In[48]**:= G[x_, y_] := p*(x^2 + y^2); G[x_Integer, y_] := x*y**

**G[x_, y_, z_] := x^2 + y^2 + z^2; G[x_, y_List] := x*y**

In[49]**:= MultipleQ[G, gs]**

Out[49]**=** True

In[50]**:= gs**

Out[50]**=** {**"**G[x**_**Integer**,** y**_**] **:=** x*****y**", "**G[x**_,** y**_**List] **:=** x*****y**",**

**"**G[x**_,** y**_**] **:=** p*****(x**^**2**+**y**^**2)**", "**G[x**_,** y**_,** z**_**] **:=** x**^**2**+**y**^**2**+**z**^**2**"**}

In[53]**:= MultipleQ1[x_ /; SymbolQ[x], j___] :=**

**Module[**{**a = Definition2[x]**}**,**

**If[**{**j**}** != **{}** && ! HowAct[j], j = a[[1 ;–2]], 77];**

**If[Length[a[[1 ;–2]]] == 1, False, True]]**

In[54]**:= MultipleQ2[x_Symbol] := If[Length[ToExpression[**

**Unique1[Definition2[x], j]][[1 ;–2]]] > 1, True, False]**

The call **MultipleQ****[****x****]** returns *True* if symbol * x* has multiple definitions, and

*False*otherwise. Through optional

*argument the list of*

**j***definitions in string format is returned.*

**x***and*

**MultipleQ1***tools*

**MultipleQ2***functional analogues of the*

**–**

**MultipleQ.**At last, quite natural interest represents the existence of the user procedures and functions activated in the current session**.** Solution of the question can be received by tool of a procedure whose call **ActBFMuserQ****[]** returns *True* if such objects exist in the current session, and *False* otherwise**; **the call **ActBFMuserQ****[****x****]** thru optional * x* argument

**–***an indefinite*

*variable*

*returns the*

**–***element nested list whose the first element contains name of the user object in the string format while the second defines list of its types in string format respectively. The fragment represents source code of the*

**2–***with an example of its use.*

**ActBFMuserQ** In[7]**:=**** ****ActBFMuserQ[x___ /;**** ****If[**{**x**}** ****==**** **{}**,**** ****True,**** ****If[Length[**{**x**}**]**** ****==**** ****1**

**&&**** ****!**** ****HowAct[x], True, False]]] := Module[**{**b**** ****=**** **{}**, c**** ****=**** ****1,**** ****d, h,**

**a = Select[Names["`*"], ! ****UnevaluatedQ****[Definition2, #] &]**}**,**

**For[c, c**** ****<=**** ****Length****[a], c++, h**** ****=**** ****Quiet[****ProcFuncTypeQ****[a[[c]]]];**

**If[h[[1]], AppendTo[b, **{**a[[c]], h[[****–****1]]**}**], Null]];**

**If[b == **{}**, False, If[**{**x**}** != **{}**, x = ReduceLists[b]]; True]]**

In[8]**:= V := Compile[**{{**x, _Real**}**, **{**y, _Real**}}**, (x^3 + y)^2];**

**Art := Function[**{**x, y**}**, x*Sin[y]]; K := (#1^2 + #2^4) &;**

**GS[x_ /; IntegerQ[x], y_ /; IntegerQ[y]] := Sin[90] + Cos[42];**

**G = Compile[**{{**x, _Integer**}**, **{**y, _Real**}}**, x*y];**

**H[x_] := Block[**{}**, x]; H[x_, y_] := x + y;**

**SetAttributes["H", Protected]; P[x_] := Module[**{}**, x];**

**P[y_] := Module[**{}**, y]; P[x__] := Plus[Sequences[**{**x**}**]];**

**T42[x_, y_, z_] := x*y*z; R[x_] := Module[**{**a = 590**}**, x*a];**

**GSV := (#1^2 + #2^4 + #3^6) &**

In[9]**:= ActBFMuserQ[]**

Out[9]**=** True

In[10]**:= **{**ActBFMuserQ[t77], t77**}

Out[10]**=** {True* ,* {{

**"**Art

**"**

*{*

**,****"**PureFunction

**"**}}

**,**

{**"**G**",** {**"**CompiledFunction**"**}}**, **{**"**GS**",** {**"**Function**"**}}**,**

{**"**H**",** {**"**Block**", "**Function**"**}}**, **{**"**P1**",** {**"**Function**"**}}**,**

{**"**R**", **{**"**Module**"**}}**, **{**"**K**", "**ShortPureFunction**"**}**,**

{**"**V**",** {**"**CompiledFunction**"**}}**,**

{**"**P**",** {**"**Module**", "**Module**", "**Function**"**}**, **{**"**T42**",** {**"**Function**"**}}**,**

{**"**GSV**", "**ShortPureFunction**"**}}}}

The * ActBFMuserQ* procedure is of interest as an useful tool first of all in the system programming.

Along with the presented tools a number of other useful tools for working with user functions and instructive examples of their application can be found in [1-16]. Here again it should be noted that the examples of tools presented in this book use the tools of the mentioned * MathToolBox* package [16] that has freeware license. Given that this package and its tools will be frequently mentioned below, we will briefly describe it.

The package contains more than * 1420* tools which eliminate restrictions of a number of the standard

*tools and expand its software with new tools. In this context, the package can serve as a certain additional tool of modular programming, especially useful in numerous applications where certain non–standard evaluations have to accompany programming. At the same time, tools presented in the package have the most direct relation to certain principal questions of procedure*

**Mathematica***functional programming in*

**–***not only for decision of applied tasks, but, above all, for programming of software extending frequently used facilities of the system and/or eliminating their defects or extending the system with new facilities. Software presented in this package contains a number of useful enough and effective receptions of programming in*

**Mathematica,***and extends its software which allows in the system to programme the tasks of various purposes more simply and effectively. The additional tools composing the above package embrace a rather wide circle of sections of the*

**Mathematica,***system [15,16].*

**Mathematica**The given package contains definitions of some *functionally* equivalent tools programmed in various ways useful for use in practical programming. Along with this, they illustrate a lot of both efficient and undocumented features of * Math-*language of the system. In our opinion, the detailed analysis of source code of the package software can be a rather effective remedy on the path of the deeper mastering of programming in

*Experience of holding of the master classes of various levels on the systems*

**Mathematica.***and*

**Mathematica***in all evidence confirms expediency of joint use of both standard tools of the systems of computer mathematics, and the user tools created in the course of programming of various appendices. A lot of tools contained in the package and mentioned below were described in [1-15] in detail enough. We now turn to the procedural objects of the*

**Maple***system.*

**Mathematica** **Chapter 2: The user procedures in Mathematica**

* Procedure* is one of basic concepts of programming system of

*being not less important object in systems of programming as a whole. A*

**Mathematica,***procedure*is an object implementing the well

*known concept of*

**-**

**"***black box*

*when with known input*

**"***(actual arguments)*and output

*(returned result)*while the internal structure of the object, generally speaking, is closed.

*forms the basis of the so*

**Procedure***called*

**-**

**"***procedural programming*

*where in the future by the procedure we will understand such objects as*

**"***and*

**module***Procedural programming is one of basic paradigms of*

**block.***which in an essential degree differs from similar paradigm of the well*

**Mathematica***known*

**-***traditional*procedural programming languages. This circumstance is the cornerstone of certain system problems relating to

*procedural*programming in

*Above all, similar problems arise in the field of distinctions in implementation of the above paradigms in the*

**Mathematica.***and in the environment of traditional procedural languages. Along with that, unlike a number of traditional and built*

**Mathematica***in languages the built*

**-***in*

**-***language has no a number of useful enough tools for operating with procedural objects. In our books [1-15] and*

**Math–***package [16] are presented some such tools.*

**MathToolBox**A number of the problems connected with similar tools is considered in the present chapter with preliminary discussion of the concept of **`***procedure***`** in * Mathematica* system as bases of its procedural paradigm. In addition, tools of analysis of this section concern only the user procedures and functions because definitions of all built

*in system functions*

**–***(unlike*

**,***say*

**,***from the*

**Maple***system)*from the user are hidden, i.e. are inaccessible for processing by the standard tools of

*system. Note that the discussion of*

**Mathematica***procedural*objects will take place relative to the latest version of

*which can dissonance with*

**Mathematica 12.1,***of earlier versions. However this should not cause any serious misunderstandings.*

**Mathematica**

**Math-***language*possesses a rather high level of immutability in relation to its versions.

**2.1. Definition of procedures in Mathematica software**

*Procedures* in * Mathematica* system are formally represented by program objects of the following

*simple formats, namely*

**2****:**

**M****[****x****_ /; ****Test**_{x}**, ****y****_ /; ****Test**_{y}**,**** ****...****] **{**:=**** ****|**** ****=**}** Module[**{* locals*}

**,**

**Module Body****]**

**B****[****x****_ /; ****Test**_{x}**, ****y****_ /; ****Test**_{y}**,**** ****...****] **{**:=**** ****|**** ****=**}** Block[**{* locals*}

**,**

**Block Body****]**

i.e., procedures of both types represent the functions from two arguments * –* the procedure body

*(Body)*and local variables

*(locals)*.

*Local*variables

*the list of names, perhaps, with initial values which are attributed to them. These variables have the local character concerning the 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 the procedure have global character, sharing field of variables of the*

**'***current session. In addition, in the procedure definition it is possible to distinguish six following component, namely*

**Mathematica****:**

– **procedure name ***(***M ***and*** B ***in the both procedures definitions)***;**

– **procedure heading ***(*{* M|B*}

**[**

**x****_ /;**

**Test**_{x}

**,**

**y****_ /;**

**Test**_{y}

**,**

**...****]**

*in the both procedures definitions)*

**;**– * procedural brackets *(

**Module[**

**…****]**

*and*

**Block[**

**…****]**)

**;**

– **local variables ***(list of local variables** *{

*}*

**locals****;**

*can be empty list)*

**;**– **procedure ***(***Module, Block***)*** body;***can be empty***;**

– **testing Test**_{x}_{ }**function ***(the function call ***Test****[****x****]**** ***returns True or False depend on*** ***permissibility* *of an actual ***x*** argument***; ***can absent)***.**

When programmed, we typically try to program tasks as modular programs as possible to make them more readable and independent, and more convenient to maintain. One of ways of a solution of the given problem is use of the scope mechanism for variables, defining for them separate scopes. * Mathematica* provides

*basic mechanisms for limiting the scope of variables in form of*

**2***modules*and

*blocks*

*hereinafter referred to as general term*

**,**

**–**

**procedures.***Procedures*along with

*functions*play a

*decisive*role in solving the issue of

*optimal*

*organization*of program code. Note, real programming uses modules much more frequently, but

*blocks*are often more convenient in

*interactive*

*programming*.

Most traditional programming languages use a so* –*called

**"***lexical scoping*

*mechanism for variables, which is analogous to the mechanism of modules in*

**"***Whereas symbolic programming languages e.g.*

**Mathematica.***LISP*allow also

**"***dynamic scoping*

**"****,**analogous to the mechanism used by blocks in

*When*

**Mathematica.***lexical scoping*is used, variables are treated as local ones to a particular part of a program code. At a

*dynamic scoping*

*the values of the allocated variables are local only to a certain part of the program execution. A*

**,***carries out processing of the body when it is carried out as a component of the general program code, any variable from locals in the module body is considered as local one. Then natural execution of the general program code continues. A*

**Module***ignoring all expressions of a body, uses for it the current values of variables from locals. In the course of execution of body the*

**Block,***block*uses values of

*locals*for variables then

*recovers*their original values after completion of the body. Most vividly these differences an example illustrates

**:**

In[2254]**:= **{**b, c**}** = **{**m, n**}**;**

In[2255]**:= B[x_] := Block[**{**a = 7, b, c**}**, x*(a + b + c)]; B[7]**

Out[2255]**=** 7*****(7 **+** m **+** n)

In[2256]**:= **{**b, c**}

Out[2256]**=** {m**,** n}

In[2257]**:= LocVars[x_String] := ToExpression[x <> "$" <>**

**ToString[$ModuleNumber ****–**** 4]]**

In[2258]**:= M[x_] := Module[**{**a = 7, b, c**}**, x*(a + b + c)]; M[7]**

Out[2258]**=** 7*****(7 **+** b**$**21248 **+** c**$**21248)

In[2259]**:= Map[LocVars, **{**"a", "b", "c"**}**]**

Out[2259]**=** {a**$**21248, b**$**21248, c**$**21248}

Thus, * Module* is a scoping construct that implements

*lexical*scoping, while

*is a scoping construct implements*

**Block***dynamic*scoping of

*local*variables.

*creates new symbols to name each of its local variables every time it is called. Call of*

**Module***function immediately after calling a module*

**LocVars***(not containing calls of other modules)*with local variables {

**a,**

**b,**

*} returns the list of variables*

**c,...**

**Map****[**

**LocVars****,**

**{**

**"a",**

**"b",**

*}*

**"c",...****]**that were generated at the time the module was called.

In the context of testing blocks for procedural nature in the above sense, the * LocVars1* procedure may be of interest whose call

**LocVars1****[**

**x****]**returns

*True*if

*is a module or a block*

**x***has no local variables without initial values, or the list of local variables is empty, otherwise*

**x***False*is returned. While calling

**LocVars1****[**

**x,y****]**with the

**2**^{nd}optional argument

**y**

**–***an undefined symbol*

*through*

**–***additionally returns the*

**y***element list whose the first element defines the list of all local variables of*

**2-***while the*

**x,**

**2**^{nd}element defines the list of local variables without initial values. Below, fragment represents source code of the procedure with its use.

In[4]**:=**** ****LocVars1****[x_ /;**** ****BlockModQ****[x],**** ****y___]**** ****:=**** ****Module[**{**a,**** ****b,**** ****d**** ****=**** **{}}**,**

**a = Locals5[x, b];**

**Do[AppendTo[d, If[Length[b[[k]]] < 2, a[[k]], Nothing]],**

{**k, Length[a]**}**]; If[**{**y**}** != **{}** && SymbolQ[y], y = **{**a, d**}**, 7];**

**If[ModuleQ[x], True, If[a == d, True, False]]]**

In[5]**:= B[x_] := Block[**{**a = 7, b, c = 8, d**}**, x*a*b*c*d];**

**B1[x_] := Block[**{**a, b, c, d**}**, x*a*b*c*d]**

In[6]**:=** {**LocVars1[B, t1], t1**}

Out[6]**=** {False**,** {{**"**a **=** 7**", "**b**", "**c **=** 8**", "**d**"**}**,** {**"**b**", "**d**"**}}}

In[7]**:=** {**LocVars1[B1, t2], t2**}

Out[7]**=** {True**,** {{**"**a**", "**b**", "**c**", "**d**"**}**,** {**"**a**", "**b**", "**c**", "**d**"**}}}

In[8]**:= G[x_] := Block[**{}**, x^2]; **{**LocVars1[G, t72], t72**}

Out[8]**=** {True**,** {{}**,** {}}}

Considering importance of modular approach to software organization when a program code consists of set of the linked independent objects and reaction of objects is defined only by their *inputs*, in this quality to us the most preferable the *modules* are presented. In *general* software code of the *modular* structure, the output of the module is the input for another module. For this reason the lion share of tools of our package * MathToolBox* [16] is programmed in the form of modules.

Once again, pertinently to pay attention to one moment. A number of tools represented in the package are focused on the solution of identical problems, but they use various algorithms programmed with usage of various approaches. They not only illustrate variety of useful enough receptions but also revealing their shortcomings and advantages useful both in practical and system programming. In our opinion, such approach opens a rather wide field for *awakening* of creative activity of the reader in respect of improvement of his skills in the programming in * Mathematica* system. Now let

*s consider module components in more detail.*

**'**Let* '*s note that in certain cases duplication of definitions of blocks, modules and functions under new names on condition of saving their former definitions invariable is required. So, for assignment of a name that is

*unique*in the current session to the new means, the procedure whose call

**DupDef****[**

**x****]**returns a name

*(unique in the current session)*whose definition will be equivalent to definition of the

*symbol can be used. In addition, the given procedure successfully works with the means having multiple definitions too. The following fragment represents source code of the procedure with an example of its application.*

**x**In[3331]**:= DupDef[x_ /; BlockFuncModQ[x]] :=**

**Module[**{**a = Flatten[**{**Definition1[x]**}**],**

**b = Unique[ToString[x]]**}**,**

**ToExpression[Map[StringReplace[#, ToString[x] <> "[" ****–****>**

**ToString[b] <> "[", 1] &, a]]; b]**

In[3332]**:= Gs[x_, y_] := x + y**

In[3333]**:= Gs[x_] := Module[**{**a = 77**}**, a*x^2]**

In[3334]**:= DupDef[Gs]**

Out[3334]**=** Gs78

In[3335]**:= Definition[Gs78]**

Out[3335]**=** Gs78[x**_,** y**_**] **:=** x **+** y

Gs78[x**_**] **:=** Module[{a **=** 77}**,** a*****x**^**2]

In particular, the * DupDef* procedure is useful enough when debugging of the user software.

The call **Definition****[****x****]** of the standard function in a number of cases returns the definition of some * x* object with the context corresponding to it what at a rather large definitions becomes badly foreseeable and less acceptable for subsequent program processing as evidently illustrates a number of examples [6-15]. Moreover, the name of an object or its string format also can act as an actual argument. For elimination of this shortcoming we defined a number of tools allowing to obtain definitions of the procedures or functions in a certain optimized format. As such means it is possible to note the following

**:**

**DefOptimum, DefFunc, Definition1,**

**Definition2,**

**Definition3**

**÷**

**Definition5,**

*and*

**DefFunc1, DefOpt, DefFunc2**

**DefFunc3***These means along with some others are represented in [4-9] and included in the*

**.***package [16]. The following fragment represents the source code of the most used tool of them with an example of its application.*

**MathToolBox**In[49]**:= 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[50]**:= a[x_]**** ****:=**** ****x**** ****+**** ****6; a[x_, y_]**** ****:=**** ****Module[**{}**,**** ****x/y]; a[t_Integer]**** ****:=**** ****7**

In[51]**:= SetAttributes[a, **{**Protected, Listable**}**]; Definition2[a]**

Out[51]**=** {**"**a[t**_**Integer] **:=** 7**", "**a[x**_**] **:=** x **+** 6**",**

**"**a[x**_,** y**_**] **:=** Module[{}**,** x/y]**",** {Listable**,** Protected}}

The * Definition2* call on system functions returns the nested list, whose first element

**–**

**"***System*

*while the second element – the list of attributes ascribed to a factual argument. On the user function or procedure*

**",***the call*

**x**

**Definition2****[**

**x****]**also returns the nested list, whose first element

*the optimized definitions of*

**–**

**x***(in the sense of absence of contexts in them*

**,***at a series definitions in a case of multiplicity of*

**x***definition)*

*whereas the second element*

**,***the list of attributes ascribed to*

**–***in their absence the empty list acts as the second element of the returned list. In a case of*

**x;***False*value on a test ascribed to a formal

*argument, the procedure call*

**x**

**Definition2****[**

**x****]**will be returned unevaluated. Analogously to the above procedures, the procedure

*processes the main both the erroneous and especial situations.*

**Definition2**Using the * Definition2* procedure and the list representation, we give an example of a simple enough

*procedure whose call*

**Info**

**Info****[**

**x****]**in a convenient form returns the complete definition of a symbol

*including its usage. While the call*

**x,**

**Info****[**

**x,**

**y****]**with

**the second optional**

*argument*

**y**

**–***an*

*indefinite symbol*

*through it additionally returns the usage for*

**–***symbol in string format. The following fragment represents the source code of the*

**x***procedure with examples of its typical application.*

**Info** In[3221]**:= Info[x_ /; SymbolQ[x], y___] :=**

**If[!**** ****HowAct[x], $Failed, **{**If[StringQ[x::usage],**

**Print[If[**{**y**}** != **{}** && ! HowAct[y], y = x::usage, x::usage]],**

**Print["Usage on " <> ToString[x] <> " is absent"]],**

**ToExpression[Definition2[x][[1 ;–2]]]; Definition[x]**}**[[–1]]]**

In[3222]**:= Info[StrStr]**

The call StrStr[* x*] returns an expression

*in string format if*

**x***is different from string*

**x****;**otherwise, the double string obtained from an expression

*is returned.*

**x**Out[3222]**=** StrStr[x**_**] **:=** If[StringQ[x], **"\"" <>** x <> **"\"",**

ToString[x]]

In[3223]**:= x[x_] := x; x[x_, y_] := x*y; x[x_, y_, z_] := x*y*z**

In[3224]**:= Info[x]**

Usage on * x* is absent

Out[3224]**=** x[x**_**] **:=** x

x[x**_,** y**_**] **:=** x*****y

x[x**_,** y**_,** z**_**] **:=** x*****y*****z

In[3225]**:= Info[StrStr, g47]**

The call **StrStr****[****x****]** returns an expression * x* in string format if

*is different from string*

**x****;**otherwise, the double string obtained from an expression

*is returned.*

**x**Out[3225]**=** StrStr[x**_**] **:=** If[StringQ[x]**,** **"\"" <>** x <> **"\"", **ToString[x]]

In[3226]**:= g47**

Out[3226]**=** **"**The call StrStr[x] returns an expression x in string format if x is different from the string**;** otherwise, the double string obtained from an expression x is returned.**"**

In[3227]**:= Info[agn]**

Out[3227]**= $**Failed

If the first * x* argument – an indefined symbol, the procedure call

**Info****[**

**x****]**

**returns**

**$**

*Failed*.

Another moment should be mentioned. In some cases, the above procedural objects can be represented in functional form based on the list structures of the format**:**

**F****[****x_, …, z_****] := **{**Save****[****w, a, b, c, …****]; ****Clear****[****a, b, c, …****];**

**Procedure body****, ****Get****[****w****]; ****DeleteFile****[****w****]**}**[[****–2****]]**

The * Save* function saves all values of

*local*and

*global*procedure variables in a certain

*file, then clears all these variables, and then executes the*

**w***. Finally,*

**procedure body***function loads the*

**Get***file into the current session, restoring {*

**w**

**a,**

**b,**

*} variables, and then deletes the*

**c,...***file. The result of the function call of the type described is the*

**w***second*list element, beginning with its end in a case if the procedure returns the result of the call through the last sentence of its body, which is a fairly frequent case. We can use {

**;**|

**,**} as the list element separators, depending on need. Thus, on the basis of the above design it is possible to program

*functional*equivalents of quite complex procedures. An example is the functional equivalent of the

*procedure described in section*

**SubsDel**

**3.4.**In[77]**:= SubsDel[S_ /; StringQ[S], x_ /; StringQ[x], y_ /; ListQ[y] &&**

**AllTrue[Map[StringQ, y], TrueQ] &&**

**Plus[Sequences[Map[StringLength, y]]] == Length[y],**

**p_ /; MemberQ[**{**–1, 1**}**, p]] := **{**Save["#$#", **{**"b", "c", "d", "h", "k"**}**];**

**Clear[b, c, d, h, k]; **{**b, c = x, d, h = StringLength[S], k**}**;**

**If[StringFreeQ[S, x], Return[S], b = StringPosition[S, x][[1]]];**

**For[k = If[p == 1, b[[2]] + 1, b[[1]] – 1], If[p == 1, k <= h, k >= 1],**

**If[p == 1, k++, k––], d = StringTake[S, **{**k, k**}**];**

**If[MemberQ[y, d] || If[p == 1, k == 1, k == h], Break[],**

**If[p == 1, c = c <> d, c = d <> c]; Continue[]]];**

**StringReplace[S, c –> ""], Get["#$#"]; DeleteFile["#$#"]**}**[[–2]]**

In[78]**:= SubsDel["12345avz6789"****, ****"avz"****,**** **{**"8"****,**** "5"**}**, 1]**

Out[78]**= "**1234589**"**

A comparative analysis of both implementations confirms aforesaid.

It is well known [8-12,16], that the user package uploaded into the current session can contains tools * x* whose definitions obtained by means of the call

**Definition****[**

**x****]**aren

*t completely optimized, i.e. contain constructions of the kind*

**'**

**j**

**<>**

**"**

**x****`"**where

*a context from the system list*

**j –****$**

*Packages*. We have created a number of tools [16] that solve various problems of processing unoptimized definitions of both individual means and means in the user packages located in files of {

**"m",**

*} formats. So, the call*

**"mx"**

**DefFunc1****[**

**x****]**provides return of the optimized definition of an object

*whose definition is located in the user package or*

**x***document and that has been loaded into the current session. At that, a name*

**nb–***should define an object without any attributes and options or with attributes and/or options. Fragment below represents source code of the*

**x***procedure along with an example of its application.*

**DefFunc1**In[7]**:= Definition[ListListQ]**

Out[7]**=** ListListQ[Global**`**ListListQ**`**L_] **:=**

If[ListQ[Global**`**ListListQ**`**L] **&&** Global`ListListQ`L **!=** {} **&&**

Length[Global**`**ListListQ**`**L] **>=** 1 **&&**

Length[Select[Global**`**ListListQ**`**L, ListQ[**#**1] **&&**

Length[**#**1] **==** Length[Global**`**ListListQ**`**L[[1]]] **&**]] **==**

Length[Global**`**ListListQ**`**L], True, False]

In[8]**:= DefFunc1[x_ /; SymbolQ[x] || StringQ[x]] :=**

**Module[**{**a = GenRules[Map14[StringJoin, **{**"Global`",**

**Context[x]**}**, ToString[x] <> "`"], ""], b = Definition2[x][[1]]**}**,**

**ToExpression[Map[StringReplace[#, a] &, b]]; Definition[x]]**

In[9]**:= DefFunc1[ListListQ]**

Out[9]**=** ListListQ[L**_**] **:=** If[ListQ[L] **&&** L **!=** {} **&&**

Length[L] **>=** 1 **&&** Length[Select[L, ListQ[**#**1] **&&**

Length[**#**1] **==** Length[L[[1]]] **&**]] **==** Length[L], True, False]

So, the procedure call **DefFunc1****[****x****]** in an optimized format returns the definition of an object * x* contained in a package or a notebook loaded into the current session. The object name is set in string format or symbol format depending on the object type

*(procedure*

**,***function*

**,***global variable*

**,***procedure variable*

**,***etc.)*. Thus, in the

**2**^{nd}case the definition is essentially more readably, above all, for rather large source codes of procedures, functions, along

with other objects. The * TypesTools* procedure is rather useful.

Calling **TypesTools****[****x****]** procedure returns the three-element list whose elements are sub-lists containing names in the string format of tools with context * x* in the terms of the objects such as

**Functions****,**

**Procedures****,**and

**Others****,**accordingly. During the procedure run, lists of the form {

**n,**

*} are intermediately output, where*

**"Name"***is the number of the tool being tested from the tools list with context*

**n***and*

**x,***is the name of the tool being tested. The following fragment represents the source code of the*

**Name***procedure, followed by its application.*

**TypesTools**In[3325]**:= TypesTools[x_ /; ContextQ[x]] := Module[**{**a = **{}**,**

**b = **{}**, c = **{}**, d = CNames[x], t, j**}**, Monitor[j = 1;**

**While[j <= Length[d], Pause[0.1]; t = d[[j]]; If[QFunction[t],**

**AppendTo[a, t], If[ProcQ[t], AppendTo[b, t], AppendTo[c, t]]];**

**j++], **{**j, t**}**]; **{**a, b, c**}**]**

In[3326]**:= TypesTools["AladjevProcedures`"]**

{1**,****"**AcNb**"**}

** ==============**

{1416**,****"$**Version2**"**}

Out[3326]**:=** {{**"**AcNb**", "**ActBFM**"****, …,**** "**XOR1**"**}**,**

{**"**ActCsProcFunc**"****, …,**** "$**SysContextsInM1**"**}**,**

{**"**AddDelPosString**", "**Args**"****, …,**** "$**Version2**"**}}

Calling **ContextMonitor****[****x****]** procedure during its execution outputs the lists of the form {**n,**** ****N,**** ****Tp,**** *** PI*} where

*is the number of the tool being tested from the tools list with context*

**n**

**x,***is the name of the tool being tested,*

**N –***its type {*

**Tp –***Function*

**,***Block*

**,***Module*

**,**

*Other*} and

**PI**

*a progress indicator*

**–****;**returning nothing. The source code of the procedure is represented below.

**ContextMonitor[x_/; ContextQ[x]]**** ****:=**** ****Module[**{**c, d**** ****=**** ****CNames[x], t, j**}**, Monitor[c = 0; Map[**{**t = #, c++, j = TypeBFM[#], Pause[0.5]**}** &, d], **{**c, t, If[! MemberQ[**{**"Block", "Function", "Module"**}**, j], "Other", j], ProgressIndicator[c, **{**1, Length[d]**}**]**}**];]**

**TypesTools****&** * ContextMonitor* procedures use the

*function whose call*

**Monitor**

**Monitor****[**

**x,y****]**generates a temporary monitor place in which the continually updated current

*value will be displayed during the course of evaluation of*

**y***Such approach may be a rather useful in many rather important applications.*

**x.** **2.2. Headings of procedures in Mathematica software**

Procedures in * Mathematica* system are formally presented by

*and*

**Modules***whose program structure begins with a*

**Blocks***i.e.*

**Heading,***heading*

*the header part of a procedure definition, preceded to the sign {*

**–****:=**

**|**

**=**} of the delayed, as a rule, or instant assignment. The components of the heading are the procedure name and its formal arguments with patterns

*possibly also with testing functions assigned to them.*

**"_",**It is necessary to highlight that in * Mathematica* system as correct procedural objects {

*Block*

**,***Module*} only those objects are considered which contain the patterns of the formal arguments located in a certain order, namely

**:**

**1.***The coherent group of formal arguments with patterns ***"_"*** has to be located at the very beginning of the tuple of formal arguments in headings of the above procedural objects***;**

**2.***Formal arguments with patterns ***"__"*** or ***"___"*** can to finish the tuple of formal arguments***;*** at that***,*** couples of adjacent arguments with patterns consisting from* {**"__",*** ** "___"*}

*are inadmissible because of possible violation of correctness (in context of scheduled computing algorithm) of calls of the above procedural objects as a simple enough fragment illustrates*

**:**In[1221]**:= A[****x_, y__, z__****] := ****x*y^2*z^3**

In[1222]**:= **{**A[****x, y, z****], A[****x, y, h, z****], A[****x, y, h, x, a, b****]**}

Out[1222]**=** {x*****y**^**2*****z**^**3**,** h**^**z**^**3*****x*****y**^**2, h**^**x**^**a**^**b**^**3*****x*****y**^**2}

In[1223]**:= G[****x_, y__, z___****] := ****x + y + z**

In[1224]**:= **{**G[****x, y, z****], G[****x, y, m, n, z****], G[****x, y, z, h****]**}

Out[1224]**=** {x **+** y **+** z**,** m **+** n **+** x **+** y **+** z**,** h **+** x **+** y **+** z}

Other rather simple examples illustrate told. Thus, the real correctness of tuple of *formal* arguments can be coordinated to their arrangement in the tuple in context of patterns {**“_”, “__”, “___”**}. At the same time, for all patterns for formal arguments the testing **Test**_{x} function of a rather complex kind can be used as the following evident fragment illustrates**:**

In[1567]**:= Sg[x_ /; StringQ[x], y__ /; If[Length[**{**y**}**] == 1,**

**IntegerQ[y], MemberQ3[**{**Integer, List, String**}**,**

**Map[Head, **{**y**}**]]]] := **{**x, y**}

In[1568]**:= Sg["agn", 72, 77, "sv", **{**a, b**}**]**

Out[1568]**=** {**"**agn**",** 72**,** 77**, "**sv**",** {a**,** b}}

In[1569]**:= Sg1[x_ /; StringQ[x], y___ /; If[**{**y**}** == **{}**, True,**

**If[Length[**{**y**}**] == 1, IntegerQ[y], MemberQ3[**{**List, String,**

**Integer**}**, Map[Head, **{**y**}**]]]]] := **{**x, y**}

In[1570]**:= Sg1["agn", 72, 77, "sv", **{**a, b**}**, a + b]**

Out[1570]**=** Sg1[**"**agn**",** 72**,** 77**, "**sv**",** {a**,** b}**,** a** + **b]

Furthermore, a procedure and function headings in testing functions are allowed to use procedure and function definitions *(using the list structure)* that are activated in the current session at the time the objects containing them are called, for example**:**

In[1620]**:= M1[x_ /; **{**SetDelayed[h[a_], Module[**{}**, 42*a]],**

**h[x] < 2020**}**[[2]], y_] :=** **Module[**{**a=5, b=7**}**, a*x^2**** ****+**** ****b*y^2]**

In[1621]**:= M1[42, 47]**

Out[1621]**=** 24283

In[1622]**:= Definition[h]**

Out[1622]**=** h[a**_**] **:=** Module[{}**,** 42*****a]

Right there once again it should be noted one an essential moment. Definition of the testing **Test**_{x} function can be directly included to the procedure or function heading, becoming active in the current session by the first procedure or function call**:**

In[2]**:= P[x_, y_ /; **{**IntOddQ[t_]**** ****:=**** ****IntegerQ[t]**** ****&&**** ****OddQ[t],**

**IntOddQ[y]**}**[[****–****1]]] := x*y**

In[3]**:= P[72, 77]**

Out[3]**=** 5544

In[4]**:= Definition[IntOddQ]**

Out[4]**=** IntOddQ[t**_**] **:=** IntegerQ[t] **&&** OddQ[t]

In[5]**:= t = 77; Save["#", t]**

In[6**]:= P[x_ /; Module[**{}**, If[x^2 < Read["#"], Close["#"];**

**True, Close["#"]; False]], y_] := x*y**

In[7]**:= P[8, 7]**

Out[7]**=** 56

Generally speaking, **Mathematica'***s* syntax and semantics, when defining procedures *(modules and blocks)** , *allow the use of procedure definitions in both the definition of test functions for formal arguments and the definitions of local variables, as the following fairly simple fragment illustrates quite clearly, while for classical functions similar assumptions are only possible for test functions, of course.

In[9]**:= Avz[x_ /; If[SetDelayed[g[t_], Module[**{**a = 42**}**, t^2 + a]];**

**g[x] < 777, True, False]] := Module[**{**a = SetDelayed[v[t_],**

**Module[**{**b = 47, c = 67**}**, b*t^3 + c]]**}**, a = 77; a*v[x]]**

In[10]**:= Avz[7]**

Out[10]**=** 1246476

In[11]**:= Avz[100]**

Out[11]**=** Avz[100]

In[12]**:=** **Definition[g]**

Out[12]**=** g[t**_**] **:=** Module[{a **=** 42}, t^2 + a]

In[13]**:= Definition[v]**

Out[13]**=** v[t**_**] **:=** Module[{b **=** 47, c **=** 67}, b*****t^3 + c]

In[14]**:= Context[g]**

Out[14]**= "**AladjevProcedures**`"**

In[15]**:= Context[v]**

Out[15]**= "**Global**`"**

In[16]**:= ****$Context**

Out[16]**= "**Global**`"**

In[17]**:= Contexts[]**

Out[17]**=** {**"**AladjevProcedures**`", "**AladjevProcedures**`**BitGet1**`",**

**"**AladjevProcedures**`**CharacterQ**`",** * …*}

In[18]**:= ****Length****[%]**

Out[18]**=** 1611

The procedures whose definitions are contained in the test functions or in the local variables domain are activated in the current session when the procedure contains them is called. In addition, the symbol * v* defined in the local area has the current context, while the symbol

*defined in the test function obtains the context being the first in the list*

**g**

**Contexts****[]**of all contexts of the current session. The feasibility of using the above approach to defining procedures is discussed in some detail in [8,11,15].

In a number of tasks, substantially including debugging of the user software, there is a necessity of dynamic change of the testing functions for formal arguments of blocks, functions and modules in the moment of their call. The * ChangeLc* procedure allowing dynamically monitoring influence of testing functions of formal arguments of tools for correctness of their calls is for this purpose programmed. The following fragment submits the source code of the procedure with examples of its application.

In[4478]**:= ChangeLc[x_ /; StringQ[x] || ListQ[x],**

**P_ /; BlockFuncModQ[P], y___] :=**

**Module[**{**a = ArgsBFM2[P], b = Definition1[P],**

**p, c, d, g, n, m = Flatten[**{**x**}**], t = ToString[P]**}**,**

**p**** = Map[StringTake[#,**** ****Flatten[StringPosition[#, "_"]][[1]]]**** ****&, m];**

**b = StringReplace[b, "Global`" <> t <> "`" ****–****> ""];**

**c = StringReplace[b, t <> "[" ****–****> ToString[n] <> "[", 1];**

**a = Select[a, SuffPref[#, p, 1] &];**

**If[a == **{}**, P @@ **{**y**}**,**

**c**** ****=**** ****StringReplace[c,**** ****Rule1[Riffle[a,**** ****m]], 1];**

**ToExpression[c]; t = n @@ **{**y**}**;**

{**If[SuffPref[ToString1[t], ToString[n] <> "[", 1],**

**"Updating testing functions for formal arguments of " <>**

**ToString[P] <> " is unsuitable", t], Remove[n]**}**[[1]]]]**

In[4479]**:= G[x_, y_, z_Integer] := x^2 + y^2 + z^2**

In[4480]**:= ChangeLc["y_ /;IntegerQ[y]", G, 42, 47, 67]**

Out[4480]**=** 8462

In[4481]**:= ChangeLc["y_ /;RationalQ[y]", G, 42, 47, 67]**

Out[4481]**=** **"**Updating testing functions for formal

arguments of * G* is unsuitable

**"**

In[4482]**:= ChangeLc["y_ /;RationalQ[y]", G, 42, 47**/**72, 67]**

Out[4482]**=** 32417761/5184

The procedure call **ChangeLc****[****x,**** ****P,**** ****y****]** returns the result of a call **P****[****y****]** on condition of replacement of the testing functions of arguments of a *block***,***module* or *function* * P* by the new functions determined by a string equivalent

*or by their list. The string equivalent is coded in shape*

**x**

**"**

**x**

**_****/;**

**TestQ****[**

**x****]**

**",***an argument.*

**x –** The task of checking formal arguments of blocks, modules, functions for their validity to admissible values plays a rather important role and this problem is solved by means of the test functions assigned to the corresponding formal arguments of the above objects. The first part of the next fragment represents an example of how to organize a system to test the *actual* values obtained when the * Art* procedure is called. At that, if the formal arguments receive invalid actual values, then procedure call is returned unevaluated with the corresponding message printing for the first of such formal arguments. Note that built-in means

*also do quite so. Meantime, the task of checking all invalid values for formal arguments when calling the above objects is more relevant. Below is a possible approach to that.*

**Mathematica** In[2185]**:= Art[x_ /; If[IntegerQ[x], True,**

**Print["Argument x is not integer, but received: x = " <>**

**ToString1[x]]; False],**

**y_ /; If[ListQ[y], True,**

**Print["Argument y is not a list, but received: y = " <>**

**ToString1[y]]; False],**

**z_ /; If[StringQ[z], True,**

**Print["Argument z is not a string, but received: z = " <>**

**ToString1[z]]; False]] :=**

**Module[**{**a = 77**}**, N[x*(Length[y] + StringLength[z])**/**a]]**

In[2186]**:= Art[47, **{**a, b, c**}**, "RansIan"]**

Out[2186]**=** 6.1039

In[2187]**:= Art[47.42, 67, "abc"]**

Argument x is not integer, but received**:** x **=** 47.42

Out[2187]**=** Art[47.42, 67, **"**abc**"**]

In[2188]**:= Art[47.42, 67, "abc"]**

Argument x is not integer, but received**:** x **=** 47.42

Out[2188]**=** Art[47.42, 67, **"**abc**"**]

In[2189]**:= Art[500, 67, "abc"]**

Argument y is not a list, but received**:** y **=** 67

Out[2189]**=** Art[500, 67**,** **"**abc**"**]

In[2190]**:= Art[500, **{**a, b, c**}**, 77]**

Argument z is not a string, but received**:** z **=** 77

Out[2190]**=** Art[500, {a, b, c}, 77]

The above approach is based on the following construction**:**

**G[x_ /; If[****Test**_{x}**, $****x****$ = ****True, ****Print[****…****]; $****x****$ = ****False; True****],**

**y_ /; If[****Test**_{y}**, $****y****$ = ****True, ****Print[****…****]; $****y****$ = ****False; True****], …**

**h_ /; AllTrue[**{**$****x****$, $****y****$,**** *** …*}

**, # ==**

**True****&]] := Module[**{}

**,**

**…****]**

The * Kr* procedure is an example of using of the above approach.

In[2192]**:= Kr[x_ /; If[IntegerQ[x], $x$ = True,**

**Print["Argument x is not integer, but received: x = " <>**

**ToString1[x]]; $x$ = False; True],**

**y_ /; If[ListQ[y], $y$ = True,**

**Print["Argument y is not a list, but received: y = " <>**

**ToString1[y]]; $y$ = False; True],**

**z_ /; If[StringQ[z], $z$ = True,**

**Print["Argument z is not a string, but received: z = " <>**

**ToString1[z]]; $z$ = False; True],**

**h_ /; AllTrue[**{**$x$, $y$, $z$**}**, # == True &]] :=**

**Module[**{**a = 77**}**, N[x*(Length[y] + StringLength[z])**/**a]]**

In[2193]**:= Kr[47, **{**a, b, c**}**, "RansIan", 78]**

Out[2193]**=** 6.1039

In[2194]**:= Kr[42.47, 67, "abc", 78]**

Argument x is not integer, but received**:** x **=** 42.47

Argument y is not a list, but received**:** y **=** 67

Out[2194]**=** Kr[42.47, 67, **"**abc**",** agn]

In[2195]**:= Kr[42.47, 67, 90, 78]**

Argument x is not integer, but received**:** x **=** 42.47

Argument y is not a list, but received**:** y **=** 67

Argument z is not a string, but received**:** z **=** 90

Out[2195]**=** Kr[42.47, 67, 90, agn]

The final part of the above fragment represents the * Kr* procedure equipped with a system for testing the values of the

*actual*arguments passed to the formal arguments when the procedure is called. At that, only three {

**x,**

**y,**

*} arguments are used as the formal arguments used by the procedure body, whereas the*

**z**

**4**^{th}additional argument

*when the procedure is called obtains an arbitrary expression, and in the*

**h,***body is not used. Argument*

**Kr***at the procedure header level tests the validity of the actual values obtained by formal arguments when the procedure is called. The argument allows to obtain information on all inadmissible values for formal arguments at the procedure call. The fragment is fairly transparent and does not require any clarifying.*

**h** Based on the form of the *heading* shown above, it is possible to represent its rather useful extension, that allows to form the *function body* at the level of such heading. In general, the format of such header takes the following form**:**

**G[x_ /; If[Test[x], Save["#", a, b, c, ****…****]; a = **{**x, True**}**; True,**

**Save["#", a, b, c, ****…****]; Print["****Argument x is not integer, but received****:**

**x = " <> ToString1[x]]; a = **{**x, False**}**; True],**

**y_ /; If[Test[y], b = **{**y, True**}**; True,**

**Print["Argument y is not integer, but received:**

**y = " <> ToString1[y]]; b = **{**y, False**}**; True],**

**z_ /; If[Test[z], c = **{**z, True**}**; True,**

**Print["Argument z is not integer, but received:**

**z = " <> ToString1[z]]; c = **{**z, False**}**; True], ****…**

………………………………………………………………………

**h_ /; If[AllTrue[**{**a[[2]],b[[2]], c[[2]]**}**, # == True &],**

**Result = Function_Body[a[[1]], b[[1]], c[[1]]]; Get["#"];**

**DeleteFile["#"]; True, Get["#"]; DeleteFile["#"]; False]] := Result**

where **Test****[****g****] –** a testing expression, testing an expression * g* on admissibility to be

*as a valid value for the*

**g***argument and*

**g***is the result of*

**Result***Function*

**_**

*body*evaluation on formal arguments {

*}. Let give a concrete filling of the above structural form as an example*

**x,y,z,…****:**

In[3338]**:= ArtKr[x_ /; If[IntegerQ[x], Save["#", a, b, c];**

**a = **{**x, True**}**; True, Save["#", a, b, c];**

**Print["Argument x is not Integer, but received:**

**x = " <> ToString1[x]]; a = **{**x, False**}**; True],**

**y_ /; If[RealQ[y], b = **{**y, True**}**; True,**

**Print["Argument y is not Real, but received:**

**y = " <> ToString1[y]]; b = **{**y, False**}**; True],**

**z_ /; If[RationalQ[z], c = **{**z, True**}**; True,**

**Print["Argument z is not Rational, but received:**

**z = " <> ToString1[z]]; c = **{**z, False**}**; True],**

**h_ /; If[AllTrue[**{**a[[2]], b[[2]], c[[2]]**}**, # == True &],**

**$Result$**** ****=**** ****N[a[[1]]*b[[1]]*c[[1]]];**** ****Get["#"];**** ****DeleteFile["#"];**** ****True,**

**Get["#"]; DeleteFile["#"]; False]] := $Result$**

In[3339]**:= $Result$ = ArtKr[72, 77.8, 50**/**9, vsv]**

Out[3339]**=** 31120**.**

In[3340]**:= $Result$ =ArtKr[72, 77.8, 78, vsv]**

Argument z is not Rational, but received**:** z **=** 78

Out[3340]**=** ArtKr[72**,** 77* .*8

**,**78

**,**vsv]

In[3341]**:= ArtKr[72, 778, 78, vsv]**

Argument y is not Real, but received**:** y **=** 778

Argument z is not Rational, but received**:** z **=** 78

Out[3341]**=** ArtKr[72, 778, 78, vsv]

In[3342]**:= ArtKr[7.2, 77.8, 78, vsv]**

Argument x is not Integer, but received**:** x **=** 7.2

Argument z is not Rational, but received**:** z **=** 78

Out[3342]**=** ArtKr[7.2, 77.8, 78, vsv]

In[3343]**:= ArtKr[7.2, 900, 50, vsv]**

Argument x is not Integer, but received**:** x **=** 7.2

Argument y is not Real, but received**:** y **=** 900

Argument z is not Rational, but received**:** z **=** 50

Out[3343]**=** ArtKr[7.2, 900, 50, vsv]

The function call **ArtKr****[****x,*** ***y,**** ****z,**** ****h****] **returns** **the** **result of evaluation of a *Function***_***Body* on actual arguments {**x,**** ****y,**** *** z*}. In addition, the call

**ArtKr****[**

**x,**

**y,**

**z,**

**h****]**as a value for formal

*argument obtains an arbitrary expression. Through the global variable*

**h****$**

**Result****$**

*the call*

**,**

**ArtKr****[**

**x,**

**y,**

**z,**

**h****]**additionally returns the same value.

**At that, the above structural form is based on the processing principle of actual arguments passed to an object**

*(block*

**,***function*

**,***module)*

*namely*

**,***the values of actual arguments are processed by the corresponding testing functions from left to right until the first calculation*

**–***False*that is obtained by a testing function, after that the call of the object is returned as unevaluated, otherwise the result of the object calculation is returned.

Therefore, the test functions for the leading formal arguments of the form are formed in such way that they return *True* when fixing the real value of the test functions and the values passed to them. Whereas the test function for the auxiliary argument * h* determines both the evaluation of the object body and validity of the factual values for the principal arguments {

**x,**

**y,**

*}, solving the task of returning the result of the calculation of the body of the object or returns the result of the call unevaluated. Fragment above*

**z****is fairly transparent and does not require any clarifying.**

According to the scheme described above, * Mathematica* allows a number of useful modifications. In particular, the following form of organizing headers {

*block*

**,***function*

**,***module*} having the following format may well be of interest

**:**

**S[x_ /; **{**X**_{1}**; …; X**_{p}**;**** **{**Test**_{x}**|*** True*}}

**[[1]],**

**y_ /; **{**Y**_{1}**; … ; Y**_{n}**;**** ****Test**_{y}}**[[1]],**

………………………………………………………**..**

**z___ /; **{**Z**_{1}**; …; Z**_{t}**; Test**_{z}}**[[1]] := ****Object**

In addition as {**X****1****,…,X****p****;**** ****Y****1****,…,Y****n****;**** ****...;**** ****Z****1****,…,Z*** t*} act admissible offers of the

*language, including calls of blocks, functions and modules whereas as {*

**Mathematica**

**Test**

**x****,**

**Test**

**y**

**,…,Test***} act the testing functions ascribed to the corresponding formal {*

**z**

**x**

**,**

**y**

**,…,***} arguments. In a case if there is no the test function for a formal argument*

**z***(i.e. argument allows any type of actual value)*instead of it is used

*True*

*Moreover, the test function for pattern*

**.**

**"**

**x___***or*

**"****"**

**x__****"**should refer to all formal arguments relating thereto. In a case of such patterns used in an object header should be used or

*True*

*or a special test function, for example, that is presented below. In a number of cases similar approach can be interesting enough. The procedure call*

**,**

**TrueListQ****[**

**x,**

**y****]**returns

*True*if a list

*has elements whose types match to the corresponding elements of a list*

**x***otherwise*

**y,***False*is returned. If lengths of both lists are different, then the first

**Min****[**

**x,**

**y****]**their elements are analyzed. At that, the call with the third argument

**z –***an*

*indefinite symbol*

*additionally returns the list of elements positions of list*

**–***whose types different from the corresponding types from the*

**x***list. The source code of the*

**y***procedure is represented below.*

**TrueListQ** In[942]**:= TrueListQ[x_ /; ListQ[x], y_ /; ListQ[y], z___] :=**

**Module[**{**a = Length[x], b = Length[y], c = **{}**, t = **{}}**,**

**Do[If[SameQ[Head[x[[j]]], y[[j]]], AppendTo[c, True],**

**AppendTo[t, j]; AppendTo[c, False]], **{**j, Min[a, b]**}**];**

**If[**{**z**}** != **{}** && SymbolQ[z], z = t; If[t == **{}**, True, False],**

**If[t == **{}**, True, False]]]**

In[943]**:= TrueListQ[**{**77, 6, "abc"**}**, **{**Integer, Symbol, String**}**]**

Out[943]**=** False

In[944]**:= TrueListQ[**{**77, 7.8, "a"**}**, **{**Integer, Real, String**}**]**

Out[944]**=** True

In[945]**:= **{**TrueListQ[**{**a, 78, "2020"**}**, **{**Integer, Real, String**}**, g], g**}

Out[945]**=** {False, {1, 2}}

The following simple * GW* procedure uses the

**TrueListQ****in heading for definition of its optional formal**

*argument along with illustrative examples of the procedure calls.*

**y** In[63]**:= GW[x_, y___ /; TrueListQ[**{**y**}**, **{**Integer, Real, Rational**}**,**

**agn]] := Module[**{**a = 78**}**, x*(y + a)]**

In[64]**:= GW[77]**

Out[64]**=** 6006

In[65]**:= GW[77, 78, 7.8, 7**/**8]**

Out[65]**=** 12680**.**

In[66]**:= **{**GW[77, 78, 42, 47], agn**}

Out[66]**=** {GW[77, 78, 42, 47], {2, 3}}

As some instructive information, an example of a procedure whose heading is based on the principles mentioned above is presented. The procedure call **Mn****[****x,**** ****y,**** ****z****]** returns the list of all arguments passed to the procedure without reference to them.

In[3349]**:= Mn[x_ /; **{**WriteLine["#", x]; IntegerQ[x]**}**[[1]],**

**y_ /; **{**WriteLine["#", y]; ListQ[y]**}**[[1]],**

**z___ /; **{**WriteLine["#", z]; True**}**[[1]]] :=**

**Module[**{**Arg**}**, Close["#"]; Arg = ReadString["#"]; DeleteFile["#"];**

**Arg = StringReplace[Arg, "\n" –> ","];**

**Arg = StringTake[Arg, **{**1, –2**}**];**

**Arg = ToExpression[StringToList[Arg]]; Arg]**

In[3350]**:= Mn[77, **{**42, 47, 67**}**]**

Out[3350]**=** {77, {42, 47, 67}}

In[3351]**:= Mn[77, **{**42, 47, 67**}**, a + b]**

Out[3351]**=** {77, {42, 47, 67}, a + b}

In[3352]**:= Mn[m, **{**42, 47, 67**}**, a + b]**

Out[3352]**=** Mn[m, {42, 47, 67}, a + b]

In[3353]**:= Mn[m, **{**42, 47, 67**}**, a + b, 77, 78]**

Out[3353]**=** Mn[m, {42, 47, 67}, a + b, 77, 78]

Another point should be emphasized. As already mentioned, when calling an object (block, function or module), the factual arguments passed to it in its heading are processed in the list order, i.e., from left to right in the list of formal arguments. In this regard, and in view of the foregoing, there is a rather real possibility of setting in definition of some formal argument of a test function that can be used as test functions for subsequent formal arguments of the object *heading** .* The following fragment represents a rather simple

*function whose heading contains definitions of two Boolean functions, used by a testing function for the last formal*

**Av***argument of the*

**z***function. At the same time, when you call function*

**Av***both Boolean functions*

**Av,***and*

**B***become active in the current session, as it is well shown in the examples below.*

**V** In[3442]**:=**** ****Av[x_ /; **{**SetDelayed[B[t_], If[t <= 90, True, False]];**

**NumberQ[x]**}**[[1]],**

**y_ /; **{**SetDelayed[V[t_], ! RealQ[t]]; RealQ[y]**}**[[1]],**

**z_ /; B[z]**** ****&&**** ****V[z]||RationalQ[z]]**** ****:=**** ****N[Sqrt[x*y/z]]**

In[3443]**:= **{**Av[77, 7.8`, 42**/**47], Av[77, 90, 500]**}

Out[3443]**=** {25.9249, Av[77, 90, 500]}

In[3444]**:= Definition[B]**

Out[3444]**=** B[t**_**] **:=** If[t **<=** 90, True, False]

In[3445]**:= Definition[V]**

Out[3445]**=** V[t**_**] **:= !** RealQ[t]

In[3446]**:= **{**B[42], V[47]**}

Out[3446]**=** {True, True}

In[3447]**:= Ag[x_ /; **{**SetDelayed[W[t_], Module[**{**a = 77**}**, a*t^2]];**

**IntegerQ[x]**}**[[1]]] := W[x] + x^2**

In[3448]**:= **{**Ag[42], W[42]**}

Out[3448]**=** {137592, 135828}

In[3449]**:= Definition[W]**

Out[3449]**=** W[t**_**] **:=** Module[{a **=** 77}, a*****t**^**2]

Thus, in particular, the last example of the previous fragment also shows that the object **W***(block***,*** function***,*** module)* defined in the header of another * Ag* object allows a correct call in the body of the

*object yet when it is first called. When*

**Ag***is called,*

**Ag***becomes active in the current session. The above fragments are quite transparent and do not require any clarifying. Technique, presented in them are of some practical interest in programming of the objects headings and objects as a whole.*

**W**On the assumption of the general definition of a procedure, in particular, of modular type

**M****[****x****_ /; ****Test**_{x}**, ****y****_ /; ****Test**_{y}**,**** ****...****]**** ****:=**** ****Module[**{* Locals*}

**,**

**Procedure body****]**

and of the fact that concrete definition of procedure is identified not by its * name,* but its

*we will consider a set of useful enough tools [16] that provide the various manipulations with the headings of procedures and functions and play a important part in the procedural and functional programming and, above all, of programming of problems of the system character.*

**heading** Having defined such object useful in many appendices as the *heading* of a procedure or function in the form **"***Name***[***List of formal arguments with the testing tools ascribed to them***]*** ",* naturally arises the question of creating of means for testing of the objects regarding their relation to the

*type. We have created a number of tools [15,16] in the form of procedures*

**`Heading`**

**HeadingQ****÷**

**HeadingQ3****.**At the same time, between pairs of the procedures {

**HeadingQ****,**

**HeadingQ***} and {*

**1**

**HeadingQ**

**2****,**

**HeadingQ***} principal distinctions exist. Meantime, considering standard along with some other unlikely encoding formats of the procedures and functions headings*

**3****,**the above four tools can be considered as rather useful testing tools in programming. In addition, from experience of their use and their time characteristics it became clear that it is quite enough to be limited oneself only by tools

**HeadingQ****and**

*which cover a rather wide range of erroneous coding of headings. Meantime, taking into account the mechanism of expressions parse for their correctness, that*

**HeadingQ1**

**Mathematica****uses, creation of comprehensive means of testing of the headings is a rather difficult. Naturally, it is possible to use the non**

*standard receptions for receiving the testing tools for the headings having a rather wide set of the deviations from the standard ones, but such outlay often do not pay off by the received benefits.*

**–**In particular* ,* the possibilities of the

**HeadingQ**

**÷**

*procedures are overlapped by opportunities of the means whose call*

**HeadingQ3***returns*

**TestHeadingQ***True*if a

*represents the heading in*

**x** string format of a block, module,** **function, and *False* otherwise. Whereas the procedure call **TestHeadingQ****[****x,**** ****y****]** with the second optional * y* argument

**–***an indefinite variable*

*thru it additionally returns information specifying the reasons of the incorrectness of a heading*

**–**

**x****.**At that, on

*objects of the same name*

**x***(multiple objects)*the procedure call returns

**$**

*Failed*

**;****the**

**extension of the procedure to case of the multiple objects does not cause much difficulty. The source code of the**

*procedure and the comparative analysis of its use concerning the*

**TestHeadingQ**

**HeadingQ**

**÷**

*tools say about its preference at programming in*

**HeadingQ3***[8,9,15]. So, of the detailed analysis follows, that the*

**Mathematica***procedure on the opportunities surpasses the above testing tools of the same purpose.*

**TestHeadingQ**In the light of real correctness of formal arguments that has been defined above and is caused by mutual arrangements of formal arguments in the context of patterns {**"_",**** ****"__",**** *** "___"*} we can significantly generalize the above group of procedures

**HeadingQ****÷**

*intended for testing of correctness of headings of the user blocks, functions*

**HeadingQ3,****&**modules, additionally using the

*procedure. For this purpose the tool*

**CorrTupleArgs***can be used.*

**HeadingsUQ** Calling the **HeadingsUQ****[****x****]** procedure returns *True* if all components composing an object * x* in the context of the call

**Definition****[**

**x****]**have correct headings, and

*False*otherwise. While the call

**HeadingsUQ****[**

**x,**

**y****]**in addition through the

**2**^{nd}optional argument

**–***an undefined*

**y***symbol*

*returns the list the elements of which are*

**–***True*if the heading of the appropriate component of

*object is correct, or the list whose first element determines incorrect heading of a component of the*

**x***object, whereas the second element determines of the component number with this*

**x***heading*concerning the call

**Definition****[**

**x****].**The source code of the

*procedure with examples of its use can be found in [15,16]. The*

**TestHeadingQ***procedure rather exhaustively tests the correctness of the*

**HeadingsUQ***headings*of blocks, functions and modules.

It is appropriate to make one quite substantial remark here. As you know, * Mathematica* does not allow to use the testing functions in block, function, and module headers that will use factual argument values that relate to other formal arguments as the following simple fragment rather visually illustrates.

In[7]**:= V[x_ /;**** ****IntegerQ[x], y_ /;**** ****EvenQ[x]**** ****&&**** ****IntegerQ[y]]**** ****:=**** ****x/y**

In[8]**:= V[42, 77]**

Out[8]**=** V[42, 77]

In the example shown, the testing function assigned to the second formal argument * y* cannot include the value passed to the first formal argument

*otherwise by causing the return of*

**x,***function call unevaluated. We will offer here one interesting reception, allowing to solve similar and some other problems. Consider it with a rather simple example.*

**V**In[2296]**:= V[x_ /; **{**Save3["j", x], IntegerQ[x]**}**[[–1]],**

**y_ /; **{**If[Get["j"]*y**** ****>**** ****100, True, False], DeleteFile["j"]**}**[[1]]] := x*y**

In[2297]**:= V[42, 77]**

Out[2297]**=** 3234

In[2298]**:= V[7, 8]**

Out[2298]**=** V[7, 8]

In order to pass an actual value (passed to the * x* argument when the

*function is called) to a testing function of another*

**V***argument, by the function*

**y***the value is stored in a сertain temporary*

**Save3***file. Then call*

**j**

**Get****[**

**j****]**allows to read the stored value from the file

*in the required point of the testing function of*

**j***any*formal argument of the header, after necessity deleting file

*To solve such problems, a*

**j.***function is of interest*

**Save3***a version of the built*

**–***in*

**-***function whose*

**Save**

**Save3****[**

**f,**

**x****]**call saves in the

*of the*

**f***txt*–format an expression

*without returning anything.*

**x** In[2310]**:= Save3[f_, x_] := **{**Write[f****,**** x], Close[f]**}**[[1]]**

In[2311]**:= Save3["###"****,**** b*S + c*V + G*x]**

In[2312]**:= Get["##"]**

Out[2312]**=** b*****S **+** c*****V **+** G*****x

After calling **Save3****[****f,**** ****x****],** the file with expression * x* remains closed and is loaded into the current session by function

**Get****[**

**f****],**returning the

*value. Note that the*

**x***function used by the*

**Write***has a number of features discussed in detail in [8]. In the first place, this refers to preserving the sequence of expressions.*

**Save3**The following procedure serves as an useful enough tool at manipulating with functions and procedures, its call **HeadPF****[****x****]** returns heading in string format of a block, module or function with a * x* name activated in the current session, i.e. the function in its traditional understanding with heading. Whereas on other values of the

*argument the call is returned unevaluated. At the same time, the problem of definition of headings is actual also in a case of the objects of the above type of the same name which have more than one heading. In this case the procedure call*

**x**

**HeadPF****[**

**w****]**returns the list of headings in string format of the subobjects composing a

*object as a whole. The following fragment represents the source code of the*

**w***procedure along with a typical example of its application.*

**HeadPF**In[2225]**:= M[x_ /; x == "avzagn"] := Module[**{**a**}**, a*x];**

** M[x_, y_, z_] := x*y*z; M[x_String] := x;**

** M[x_ /; IntegerQ[x], y_String] := Module[**{**a, b, c**}**, x];**

** M[x_, y_] := Module[**{**a, b, c**}**, "abc"; x + y]**

In[2226]**:= HeadPF[x_ /; BlockFuncModQ[x]] := Module[**{**b,**

**c = ToString[x], a = Select[Flatten[**{**PureDefinition[x]**}**],**

**! SuffPref[#, "Default[", 1] &]**}**, b = Map[StringTake[#,**

{**1, Flatten[StringPosition[#, **{**" := ", " = "**}**]][[1]] – 1**}**] &, a];**

**If[Length[b] == 1, b[[1]], b]]**

In[2227]**:= HeadPF[M]**

Out[2227]**=** {**"**M[x_ /**;** x == \**"**avzagn\**"**]**", "**M[x_, y_, z_]**",**

**"**M[x_ /**;** IntegerQ[x], y_String]**", "**M[x_String]**", "**M[x_, y_]**"**}

Here, it is necessary to make one essential enough remark concerning the means dealing with the * headings* of procedures and functions. The matter is that as it was shown earlier, the testing tools ascribed to the formal arguments, as a rule, consist of the earlier defined testing functions or the

*reserved*keywords defining the type, for example,

*Integer*. While as a side effect the built

*in*

**–***Math*

*language allows to use the constructions that can contain definitions of the testing tools, directly in the headings of procedures and functions. Certain interesting examples of that have been represented above. Meanwhile, despite of such opportunity, the programmed means are oriented, as a rule, on use for testing of admissibility of the factual arguments or the predefined means, or including the testing algorithms in the body of the procedures and functions. For this reason,*

**–***procedure presented above in such cases can return incorrect results. Whereas the*

**HeadPF***procedure covers such peculiar cases. The procedure call*

**HeadPFU**

**HeadPFU****[**

**x****]**correctly returns the heading in string format of a block, module or function with a name

*activated in the current session regardless of a way of definition of testing of factual arguments. The fragment below presents the source code of the*

**x***procedure along with typical examples of its application.*

**HeadPFU**In[2230]**:= P[x_, y_ /; **{**IntOddQ[t_] := IntegerQ[t] && OddQ[t],**

**IntOddQ[y]**}**[[–1]]] := x*y**

In[2231]**:= HeadPF[P]**

Out[2231]**= "**P[x_, y_ /; {IntOddQ[t_]**"**

In[2232]**:= HeadPFU[x_ /; BlockFuncModQ[x]] :=**

**Module[**{**a = Flatten[**{**PureDefinition[x]**}**], b = **{}**, c, g**}**,**

**Do[c = Map[#[[1]] – 1**** ****&, StringPosition[a[[j]], " := "]];**

**Do[If[SyntaxQ[Set[g, StringTake[a[[j]], **{**1, c[[k]]**}**]]],**

**AppendTo[b, g]; Break[], Null], **{**k, Length[c]**}**], **{**j, Length[a]**}**];**

**If[Length[b] == 1, b[[1]], b]]**

In[2233]**:= HeadPFU[P]**

Out[2233]**= "**P[x_, y_ /**; **{IntOddQ[t_] **:=** IntegerQ[t] && OddQ[t]**,**

IntOddQ[y]}[[–1]]]**"**

In[2234]**:= V[x_ /; **{**Save3["#", x], IntegerQ[x]**}**[[–1]],**

**y_ /; **{**If[Get["#"]*y > 77,**** ****True,**** ****False], DeleteFile["#"]**}**[[1]]] := x*y**

In[2235]**:= HeadPFU[V]**

Out[2235]**= "**V[x_ /**;** {Save3[\**"**#\**", **x], IntegerQ[x]}[[–1]]**,**

y_ /**;** {If[Get[\**"**#\**"**]*****y > 77, True, False], DeleteFile[\**"**#\**"**]}[[1]]]**"**

In this regard the testing of a * x* object regarding to be of the same name is enough actually

**;**the

*procedure [16] solves the problem whose call*

**QmultiplePF**

**QmultiplePF****[**

**x****]**returns

*True*

*if*

**,***is an object of the same name*

**x***(Function*

**,**

*Block*

**,**

*Module)*

**,**and

*False*otherwise. Whereas the procedure call

**QmultiplePF****[**

**x,**

**y****]**with the second optional

*argument*

**y**

**–***an indefinite variable*

*through*

**–***returns the list of definitions of all sub*

**y***objects with a name*

**–**

**x.**Right there pertinently to note some more tools linked with

the * HeadPF* procedure. So, the

*procedure is a rather useful expansion of the*

**Headings***procedure in a case of blocks, functions and modules of the same name but with the different headings. Generally, the call*

**HeadPF**

**Headings****[**

**x****]**returns the nested list whose elements are the sub

*lists which determine respectively headings of sub*

**–****-**objects composing an object

*the first elements of such sub-lists defines the types of sub-objects*

**x;***whereas others define the headings corresponding to them. In a number of the appendices that widely use procedural programming, a rather useful is the*

**,***procedure that is an expansion of the previous procedure. Generally, the call*

**HeadingsPF**

**HeadingsPF****[]**returns the nested list, whose elements are sub

*lists that respectively define the headings of functions, blocks and modules, whose definitions have been evaluated in the current session; the first element of each such sub*

**–***list determines an object type in the context {*

**–**

**"***Block*

**", "***Module*

**", "***Function*

*} while the others define the headings corresponding to it. The procedure call returns a simple list if any of sub*

**"***lists does not contain headings*

**–****;**at that, if in the current session the evaluations of definitions of objects of the specified three types weren

*t made, the call returns empty list. The call with any arguments is returned unevaluated. The following fragment represents source code of the*

**'***procedure along with an example of its typical application.*

**HeadingsPF** In[2310]**:= HeadingsPF[x___ /; SameQ[x, **{}**]] := Module[**{**a = **{}**,**

**d = **{}**, k = 1, b, c = **{{**"Block"**}**, **{**"Function"**}**, **{**"Module"**}}**, t**}**,**

**Map[If[Quiet[Check[BlockFuncModQ[#], False]],**

**AppendTo[a, #], Null] &, Names["`*"]];**

**b = Map[Headings[#] &, a]; While[k <= Length[b], t = b[[k]];**

**If[NestListQ[t], d = Join[d, t], AppendTo[d, t]]; k++];**

**Map[If[#[[1]] == "Block", c[[1]] = Join[c[[1]], #[[2 ;****–****1]]],**

**If[#[[1]] == "Function", c[[2]] = Join[c[[2]], #[[2 ;****–****1]]],**

**c[[3]] = Join[c[[3]], #[[2 ;****–****1]]]]] &, d];**

**c = Select[c, Length[#] > 1 &]; If[Length[c] == 1, c[[1]], c]]**

In[2311]**:= M[x_ /; SameQ[x, "avz"], y_] := Module[**{**a, b, c**}**, y];**

** L1[x_] := x; M[x_, y_, z_] := x + y + z; L[x_, y_] := x + y;**

** M[x_ /; x == "avz"] := Module[**{**a, b, c**}**, x];**

** M[x_ /; IntegerQ[x], y_String] := Module[**{**a, b, c**}**, x];**

** M[x_, y_] := Module[**{**a, b, c**}**, "agn"; x + y]; M[x_String] := x;**

** M[x_ /; ListQ[x], y_] := Block[**{**a, b, c**}**, "agn"; Length[x] + y];**

** F[x_ /; SameQ[x, "avz"], y_] := **{**x, y**}**; F[x_ /; x == "avz"] := x**

In[2312]**:= HeadingsPF[]**

Out[2312]**=** {{**"**Block**", "**M[x_ /**;** ListQ[x], y_]**"**}**,**

{**"**Function**", "**F[x_ /**;** x === \**"**avz\**",** y_]**", "**F[x_ /**;** x == \**"**avz\**"**]**",**

**"**L[x_, y_]**", "**L1[x_]**", "**M[x_, y_, z_]**", "**M[x_String]**"**}**,**

{**"**Module**", "**M[x_ /; x === \**"**avz\**",** y_]**", "**M[x_, y_]**",**

**"**M[x_ /**;** x == \**"**avz\**"**]**", "**M[x_ /**;** IntegerQ[x], y_String]**"**}}

In the light of possibility of existence in the current session of procedures and functions of the same name with different headings the problem of removal from the session of an object with the concrete heading is of a certain interest**;** this problem is solved by the procedure * RemProcOnHead,* whose the source code with an example of its application is represented below.

In[7]**:= RemProcOnHead[x_ /; HeadingQ[x]||HeadingQ1[x]||**

**ListQ[x] && AllTrue[Map[HeadingQ[#] &, x], TrueQ]] :=**

**Module[**{**b, c, d, p, a = HeadName[If[ListQ[x], x[[1]], x]]**}**,**

**If[! MemberQ[Names["`*"] || ! HowAct[a], a], $Failed,**

**b = Definition2[a]; c = b[[1 ;****–****2]]; d = b[[****–****1]];**

**ToExpression["ClearAttributes["<>a<> ","<>ToString[d]<>"]"];**

**y = Map[StandHead, Flatten[**{**x**}**]];**

**p = Select[c, ! SuffPref[#, x, 1] &];**

**ToExpression["Clear[" <> a <> "]"];**

**If[p == **{}**, "Done", ToExpression[p];**

**ToExpression["SetAttributes["<>a <> "," <> ToString[d] <> "]"];**

**"Done"]]]**

In[8]**:= V[x_] := Module[**{}**, x^6]; V[x_Integer] := x^2**

In[9]**:= **{**RemProcOnHead["V[x_Integer]"],**

**RemProcOnHead["V[x_]"]**}

Out[9]**=** {**"**Done**", "**Done**"**}

In[10]**:= Definition[V]**

Out[10]**=** Null

The call **RemProcOnHead****[****x****]** returns **"***Done***"** with removing from the current session a procedure, function or their list with heading or with list of * x* headings that are given in string format

**;**headings in call

**RemProcOnHead****[**

**x****]**is coded according to the format

**ToString1****[**

**x****].**

The task, closely adjacent to the headings, is to determine the arity of objects. For this purpose, we have created a number of means [8,9]. In particular, the * ArityBFM1* procedure defining

*arity*of objects of the type {

*module*

**,***classical function*

**,***block*} serves as quite useful addition to the procedure

*and some others.*

**Arity**The procedure call **ArityBFM1****[****x****]** returns the **arity***(number of the formal arguments)* of a block, function or module * x* in the format of

**4***element list whose the*

**–**

**1**^{st}

*the*

**,**

**2**^{nd}

*the*

**,**

**3**^{rd}

*elements define quantity of formal arguments with the patterns*

**"****_**

**", "****__**

*and*

**"**

**"****___**

*accordingly. While the*

**"**

**4**^{th}element defines common quantity of formal arguments which can be different from the quantity of actual arguments. In addition, the

*heading should has classical type, i.e. it should not include non*

**x***standard, but acceptable methods of headings definition. The unsuccessful procedure call returns*

**–****$**

*Failed*

**.**The following procedure serves for definition of arity of system functions. The procedure call **AritySystemFunction****[****x****]** returns the * 2–*element list whose

**1**^{st}element defines number of formal arguments, while the second element

*quantity of admissible actual arguments. The call with the second optional*

**–***argument*

**y**

**–***an indefinite variable*

*thru it returns the generalized template of formal arguments.*

**–**In[3341]**:= AritySystemFunction[x_, y___] := Module[**{**a, b, c, d, g, p**}**,**

**If[! SysFunctionQ[x], $Failed, a = SyntaxInformation[x];**

**If[a == **{}**, $Failed, c = **{**0, 0, 0, 0}; b = Map[ToString, a[[1]][[2]]];**

**b = Map[If[SuffPref[#, "**{**", 1], "_",**

**If[SuffPref[#, **{**"Optional", "OptionsPattern"**}**, 1], "_.", #]] &, b];**

**If[**{**y**}** != **{}** && ! HowAct[y],**

**y = Map[ToExpression[ToString[Unique["x"]] <> #] &, b], 77];**

**Map[If[# == "_", c[[1]]++, If[# == "_.", c[[2]]++,**

**If[# == "__", c[[3]]++, c[[4]]++]]] &, b]; **{**p, c, d, g**}** = c;**

**d = DeleteDuplicates[**{**p + d, If[d != 0||g != 0, Infinity, p + c]**}**];**

**If[d != **{**0, Infinity**}**, d, Quiet[x[Null]]; If[Set[p, Messages[x]] == **{}**, d,**

**p = Select[Map[ToString, Map[Part[#, 2] &, p]],**

**!**** ****StringFreeQ[#, " expected"] &]; p = Map[StringTake[#,**

{**Flatten[StringPosition[#, ";"]][[1]] + 1, –2**}**] &, p];**

**p = ToExpression[Flatten[StringCases[p, DigitCharacter ..]]];**

**If[p == **{}**, **{**1**}**, If[Length[p]**** ****>**** ****1, **{**Min[p], Max[p]**}**, p]]]]]]]**

In[3342]**:=** {**AritySystemFunction[If, g72], g72**}

Out[3342]**=** {{2**,** 4}**,** {x16**_,** x17**_,** x18**_.,** x19**_.**}}

**2.3. Optional arguments of procedures and functions**

When programming procedures and functions often there is an expediency to define some of their formal arguments as optional. In addition, in case of explicit lack of such arguments by a call of tools, they receive values *by* *default*. System built* –*in

*functions use two basic methods for dealing with optional arguments that are suitable for the user tools too. The*

**Mathematica***first*method consists in that that a value of each argument

*that is coded by pattern*

**x**

**"****_**

**:"****in the form**

**x****_**

*should be replaced by*

**:b***if the argument omitted. Almost all built*

**b,***in system functions that use this method, omit arguments since the end of the list of formal arguments. So, simple function*

**–**

**G****[**

**x**

**_:**

**5,**

**y**

**_:**

**7****]**

**:=**

**{**

**x**

**,**

*} two optional arguments have, for which values by default*

**y***and*

**– 5***respectively. As*

**7***system assumes that arguments are omitted since end of the list of formal arguments then we have not a possibility by positionally*

**Mathematica***(in general selectively)*do an argument as optional.

In[3376]**:= G[x_: 5, y_: 6] := **{**x, y**}

In[3377]**:= **{**G[], G[42, 77], G[42]**}

Out[3377]**=** {{5, 6}, {42, 77}, {42, 6}}

So, from a simple example follows that for function * G* from two optional arguments the call

**G****[**

**42****]**refers value by default to the second argument, but not to the first. Therefore this method has a rather limited field of application.

The second method of organization of optional arguments consists in use of explicit names for the optional arguments by allowing to give them values using transformation rules. This method is particularly convenient for means like * Plot* function which have a rather large number of optional arguments, only a few of which usually need to be set in a particular example. The typical method is that values for so

*called named optional arguments can be specified by including the appropriate rules at the end of the arguments at a function call. At determining of the named optional arguments for a procedure or function*

**–***it is conventional to store the default values for these arguments as a list of transformation rules assigned to*

**g,**

**Options****[**

**g****].**So, as a typical example of definition for a tool with zero or more

*named*optional arguments can be

**:**

**g[x_, y_, OptionsPattern[]]**** ****:=**** ****Module[**{}**, x*y]**

Then for this means a list of transformation rules assigned to **Options****[****g****] **is determined

**Options[g] = **{**val1 ****–****> a, val2 ****–****> b**}

Whereas expression **OptionValue****[****w****]** for a named optional argument * w* has to be included to the body of the tool, in order that this mechanism worked. Below is presented the definition of a function

*that allows up to*

**g***named optional arguments*

**2****:**

In[2114]**:= g[x_, y_, OptionsPattern[]] :=**

**(OptionValue[val1]*x + OptionValue[val2]*y)**/

**(OptionValue[val1]*OptionValue[val2])**

In[2115]**:= Options[g] = **{**val1 ****–****> 42, val2 ****–****> 47**}

Out[2115]**=** {val1 **–****>** 42, val2 **–****>** 47}

In[2116]**:= g[90, 500]**

Out[2116]**=** 13640/987

In[2117]**:= g[90, 500, val1 ****–****> 77]**

Out[2117]**=** 30430/3619

In[2118]**:= g[90, 500, val1 ****–****> 10, val2 ****–****> 100]**

Out[2118]**=** 509/10

From the represented example the second method of work with named optional arguments is rather transparent. You can to familiarize with optional arguments in more detail in [22].

Other way of definition of optional arguments of functions and procedures consists in use of the template **"****_.****"*** ,* representing an optional argument with a default value specified by built

*in*

**–***function*

**Default**

**–**

**Default****[**

**w****] =**

*. Let*

**Value****'**s note, the necessary values for call

**Default****[**

**w****]**for a tool

*must always precede an optional argument of the*

**w***tool. Values defined for*

**w**

**Default****[**

**w****]**are saved in

**DefaultValues****[**

**w****]**

*Fragment below illustrates told*

**.****:**

In[1346]**:= Default[w] = 5;**

In[1347]**:= w[x_****.,**** y_****.,**** z_****.****] := **{**x, y, z**}**; **{**w[], w[42, 47], w[42]**}

Out[1347]**=** {{5, 5, 5}**,** {42, 47, 5}**,** {42, 5, 5}}

More detailed information on this way can be found in [15] and by a call **?****D*** efault* in the current session of

**M***At the same time all considered approaches to the organization of work with optional arguments do not give the chance to define values by default for an arbitrary tuple of formal arguments.*

**athematica.**The reception described below on a simple example can be for this purpose used. Definition of a procedure * G* for which we going to make all three formal arguments

**x,**

*and*

**y***optional, is made out as follows*

**z****:**

*defines the list of formal arguments in string format,*

**Res***determines the list of values by default for all formal arguments, the procedure body is made out in the form*

**Def***{*

**"***}*

**Body***moreover, of the*

**",***definition is complemented with an obligatory argument*

**G***which represents the binary list of signs whose elements correspond to*

**Opt***list elements. The zero element of the*

**Res***list determines non-obligation of the*

**Opt***list element corresponding to it, and vice versa. After the specified definition of the procedure body*

**Res***(*

**d***)*the

*[16] procedure which provides substitution in the procedure body of the actual arguments*

**StringReplaceVars***(sign*

**1***)*or their values by default

*(sign*

**0***)*is applied to it. So, the procedure call

**G[**

**x,**

**y,**

**z,**

**Opt****]**returns the simplified value of the

*source*procedure body on the arguments transferred to it. The simple example visually illustrates told.

In[7]**:= G[x_., y_., z_., Opt_] := Module[**{**Res = **{**"x"****,**** ****"y"****,**** ****"z"**}**,**

**Def = Map[ToString1[#] &, **{**42****,**** 47****,**** 67**}**],**

**args = Map[ToString1[#] &, **{**x, y, z**}**], b, c, d**}**,**

**d = "Simplify[**{**b = (x + y)**/**(x + z); c = b*x*y*z; (b + c)^2**}**]";**

**d = StringReplaceVars[d,**** ****Map[If[Opt[[#]]**** ****==**** ****0,**** ****Res[[#]]**** ****–****>**

**Def[[#]], Res[[#]] ****–****> args[[#]]] &, Range[Length[Res]]]];**

**ToExpression[d][[1]]]**

In[8]**:= G[a, s, t, **{**0, 1, 1**}**]**

Out[8]**=** ((42 **+** s)**^**2*****(1 **+** 42*****s*****t)**^**2)/(42 **+** t)**^**2

In[9]**:= G[a, s, t, **{**1, 1, 1**}**]**

Out[9]**=** ((a **+** s)**^**2*****(1 **+** a*****s*****t)**^**2)/(a **+** t)**^**2

In[10]**:= G[a, s, t, **{**0, 0, 0**}**]**

Out[10]**=** 138557641644601/11881

In certain cases the above reception can be rather useful.

The problem for testing of correctness of the tuple of formal arguments in the user *modules***,***blocks* or *functions* can be solved by procedure whose call **CorrTupleArgs****[****x****]** returns *True* if tuple of formal arguments of a procedure or a function * x* is correct in the sense stated above, and

*False*otherwise [8,16].

On the other hand, the problem of preliminary definition of correctness of the factual arguments passing to a procedure or a function is of a rather interesting. If tool has no mechanisms of testing of actual arguments passing to it at a call, then the call on *incorrect* actual arguments as a rule is returned unevaluated. The procedure * TestActArgs* is one of variants of solution of the problem, whose call

**TestActArgs****[**

**x,**

**y****]**returns

*empty*list if tuple of actual arguments meets the tuple of testing functions of the corresponding formal arguments of

*otherwise the procedure call trough*

**x,***returns the integer list of numbers of the formal arguments to which*

**y***inadmissible*actual arguments are supposed to be passed [1-16].

Meantime, use of the above procedure assumes that testing for correctness of actual arguments for formal arguments with patterns {* "__", "___"*} is carried out only for the first elements of tuples of actual arguments passing to formal arguments with the appropriate patterns. Whereas further development of the procedure is left to the interested reader as an useful exercise. In addition, it should be noted the important circumstance. If in the traditional programming languages the identification of an arbitrary procedure

**or**

**function is made according to its**

*name*

*in case of*

**,***language the identification is made according to its*

**Math–***heading*

*This circumstance is caused by that the definition of a procedure or function in the*

**.***language is made by the manner different from traditional [1]. Simultaneous existence of procedures of the same name with different headings in such situation is admissible as it illustrates a simple fragment*

**Math-****:**

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}]

At the call of procedure or function of the same name from the list is chosen the one, whose formal arguments of heading correspond to actual arguments of the call, otherwise the call is returned unevaluated* ,* excepting simplifications of arguments according to the standard system agreements. At compliance of formal arguments of

*heading*with actual ones the component of

*procedure or function is caused, whose definition is the first in the list returned at the call*

**x**

**Definition****[**

**x****];**particularly, whose definition has been evaluated in the

*by the first. Therefore, in order to avoid possible misunderstandings in case of procedure override with a name*

**Mathematica***which includes a change of its header also, the call*

**x,**

**Clear****[**

**x****]**must first undo the previous procedure definition.

The works [1-16] present a range of interesting software for dealing with the headings and formal arguments that make up them. In particular, the following tools can be mentioned**:**

**ProcQ****[****x****]** **–***returns* *True* *if* **x***is a procedure and* *False* *otherwise***;**

**BlockModQ****[****x****]** **–***returns* *True* *if* **x***is a name defining a block* *or* *module***;*** otherwise* *False* *is returned*. *At that***,***thru optional argument ***y**** –** *an indefinite variable the call* **BlockModQ****[****x,**** ****y****]** *returns the type of the object ***x*** in the context* of {**"***Block***",**** ****"***Module** "*}

*on condition that main result is True*

**;****ArgsP****[****x****]** **–***returns the list whose elements ***–*** formal arguments of Block or Module ***x*** ***–*** are grouped with the preceding words ***Block*** and ***Module.*** **Groups arise in the case of multiple object definition ***x;**

In[72]**:= ArgsP[x_ /; BlockModQ[x]] := Module[**{**b, c = **{}**, j,**

**a = Headings[x]**}**,**

**a = If[MemberQ3[a, **{**"Module", "Block"**}**], a, **{**a**}**];**

**b = Length[a];**

**Do[Map[AppendTo[c, If[StringFreeQ[#, "["], #,**

**StringReplace[StringTake[#, StringLength[#] ****–**** 1],**

**ToString[x] <> "[" ****–****> "**{**"] <> "**}**"]] &, a[[j]]], **{**j, 1, b**}**];**

**ToExpression[c]]**

In[73]**:= M[x_ /; IntegerQ[x]] := Module[**{}**, x^2];**

**M[x_, y_] := Module[**{}**, x*y^3]; M[x__] := Module[**{}**, **{**x**}**];**

**M[x_, y__] := Block[**{**a = 42, b = 47**}**, **{**a*x, b*y**}**]**

In[74]**:= ArgsP[M]**

Out[74]**=** {Block* ,* {x

**_,**y

**__**}

*Module*

**,***{x*

**,****_**/

**;**IntegerQ[x]}

**,** {x**_,** y**_**}* ,* {x

**__**}}

**RenameP****[****x,**** ****y****]** **–***returns the empty list***,*** renaming a Function***,*** Block or Module ***x*** to a name***,*** defined by the second argument ***y*** with its activation in the current session***; ***note***,*** object ***x*** remains unchanged*

In[32]**:= RenameP[x_ /; BlockFuncModQ[x], y_Symbol] :=**

**ReplaceAll[ToExpression[Map[StringReplace[#,**

**ToString[x] <> "[" ****–****> ToString[y] <> "[", 1] &,**

**DefToStrM[x]]], Null ****–****> Nothing]**

In[33]**:= M[x_ /; IntegerQ[x]] := Module[**{}**, x^2];**

**M[x_, y_] := Module[**{}**, x*y^3]; M[x__] := Module[**{}**, **{**x**}**];**

**M[x_, y__] := Block[**{}**, **{**x, y**}**]**

In[34]**:= RenameP[M, Agn]**

Out[34]**=** {}

In[35]**:= Definition[Agn]**

Out[35]**=** Agn[x**_** /**;** IntegerQ[x]] **:=** Module[{}, x**^**2]

Agn[x**_,** y**_**] **:=** Module[{}, x*****y**^**3]

Agn[x**_,** y**__**] **:=** Block[{}, {x, y}]

Agn[x**__**] **:=** Module[{}, {x}]

Note that we have programmed a lot of other useful tools for different processing of both the headings, as a whole, and their separate components, first of all, formal arguments [1-16]. Some of these are used in examples given in this book. Before further consideration, it should be noted once again that, the block and module headings handling tools are also functionally suitable for the classical functions determined by the headings according to a general mechanism used by the blocks, modules, and classical functions. Thus, what is said about the procedure headings fully applies to functions, making it easy to convert the second ones to the first.

One of the main tasks at working with formal arguments is

to define them for the user procedures *(modules and blocks) *and functions. In this direction, we have created a number of means of various purposes. At the same time, the definition of testing functions for formal arguments may itself contain definitions of procedures and functions, which implies consideration is given to this circumstance in the development of means of processing formal arguments. So, the * ArgsProcFunc* procedure considers this circumstance illustrating it on an example of its application to the

*procedure presented below.*

**M**The procedure call **ArgsProcFunc****[****x****]** generally returns the nested list whose single elements define formal arguments in the string format, and * 2–*element sub

*lists by the first element define formal arguments, while by the second define the testing functions assigned to them*

**–***(conditions of their admissibility)*also in the string format of a procedure, block or function

**x.**In[1938]**:= ArgsProcFunc[x_ /; BlockModQ[x]] :=**

**Module[**{**a = Definition1[x], b, c = "", d, j, f, g**}**,**

**d = StringLength[g = ToString[x]]; c = g;**

**For[j = d + 1, j <= StringLength[a], j++,**

**If[!**** ****SyntaxQ[g**** ****=**** ****g**** ****<>**** ****StringTake[a, **{**j, j**}**]], Continue[], Break[]]]****;**

**b = StringReplace[g, c <> "[" ****–****> ",", 1];**

**b = StringInsert[b, ",", ****–****1]; c = "";**

**Do[c = c <> StringTake[b, **{**j, j**}**]; If[SyntaxQ[c], Break[],**

**Continue[]], **{**j, 1, StringLength[b]**}**];**

**d = StringDrop[c, ****–****2] <> ","; c = **{}**;**

**Label[Agn]; f = StringPosition[d, ","];**

**f = DeleteDuplicates[Flatten[f]];**

**For[j = 2, j <= Length[f], j++,**

**If[SyntaxQ[g = StringTake[d, **{**f[[1]] + 1, f[[j]] ****–**** 1**}**]],**

**AppendTo[c, g]; d = StringReplace[d, "," <> g ****–****> "", 1];**

**Goto[Agn], Continue[]]];**

**c = Map[StringReplace[#, GenRules[**{**"___", "__", " /;", "_:",**

**"_.", "_"**}**, "@[email protected]"], 1] &, c];**

**c**** ****=**** ****M****ap[StringTrim[#]**** ****&,**** ****M****ap[StringSplit[#,**** ****"@[email protected]"]**** ****&,**** ****c]];**

**Map[If[Length[#]**** ****==**** ****1, #[[1]], If[SuffPref[#[[2]],**** ****g**** ****=**** ****"/;**** ****",**** ****1],**

{**#[[1]], StringReplace[#[[2]], g ****–****> "", 1]**}**, #]] &, c]]**

In[1939]**:= M[x_, y_ **/**; **{**g[t_] := Module[**{}**, t^2], If[g[y] > 50,**

**True, False]**}**[[2]], r_: 77, p_., z___] :=**

**Module[**{}**, x*y*r*p**/**g[z]]**

In[1940]**:= **{**M[77, 8, 42, 72, 7], M[77, 7, 42, 72, 7]**}

Out[1940]**=** {38016**,** M[77**,** 7**,** 42**,** 72**,** 7]}

In[1941]**:= Definition[g]**

Out[1941]**=** g[t**_**] **:=** Module[{}**,** t**^**2]

In[1942]**:= ArgsProcFunc[M]**

Out[1942]**=** {**"**x**",** {**"**y**", "**{g[t**_**] **:=** Module[{}**,** t**^**2]**,** If[g[y] **>** 50**,**

True, False]}[[2]]**"**}**,** {**"**r**", "**77**"**}**,** **"**p**", "**z**"**}

It follows from the fragment that for a tool defined in the testing function of a formal argument, the availability domain is the entire current session, including the procedure body that generated it. * ArgsProcFunc1* and

*procedures, unlike*

**ArgsProcFunc2***are based on other principles, returning the lists of formal arguments with testing functions ascribed to them, while through the second optional argument is returned the same list with elements in the string format.*

**ArgsProcFunc,**In[19]**:= ArgsProcFunc1[x_ /; BlockFuncModQ[x], y___] :=**

**Module[**{**a = Definition1[x], b, c = "", d, j, f, g**}**,**

**d = StringLength[g = ToString[x]]; c = g;**

**For[j = d + 1, j <= StringLength[a], j++,**

**If[! SyntaxQ[g**** ****=**** ****g**** ****<>**** ****StringTake[a, **{**j, j**}**]],**** ****Continue[],**** ****Break[]]];**

**b = ToExpression["**{**" <> StringTrim[g, **{**c <> "[", "]"**}**] <> "**}**"];**

**If[**{**y**}** == **{}**, b, If[SymbolQ[y], b; y = Map[ToString1, b]]]]**

In[20]**:= ArgsProcFunc1[M, t]**

Out[20]**=** {**"**x**_", "**y**_** /; {g[t**_**] **:=** Module[{}, t**^**2], If[g[y] **>** 50**,**

True, False]}[[2]]**", "**r**_:**77**", "**p**_.****", "**z**___"**}

In[77]**:= ArgsProcFunc2[x_ /; BlockFuncModQ[x], y___] :=**

**Module[**{**a = ToExpression[HeadPFU[x]], b = **{}**, c, k**}**,**

**Do[c = Quiet[Check[Part[a, k], Error, Part::partw]];**

**If[c === Error, Return[If[**{**y**}** == **{}**, b, If[SymbolQ[y], b;**

**y**** ****=**** ****Map[ToString1,**** ****b],**** ****b]]], AppendTo[b,**** ****c]],**** **{**k,**** ****Infinity**}**]]**

In[78]**:= ArgsProcFunc2[M]**

Out[78]**=** {x**_,** y**_** /; {g[t**_**] **:=** Module[{}, t**^**2], If[g[y] **>** 50**,**

True, False]}[[2]]**,** r**_** **:** 77**,** p**_.,** z**___**}

The question of processing of the formal arguments with good reason can be considered as the first problem relating to the calculations of the tuples of formal arguments of the user functions, modules and blocks that have been activated in the current session directly or on the basis of download of packages containing their definitions. In our works [1-15] certain tools for the solution of this problem have been programmed in the form of procedures **Args,**** ****Args0**** ****÷**** ****Args2****,** then we presented similar tools in narrower assortment and with the improved some functional characteristics. Above all, as a rather useful tool, we present the * Args3* procedure whose call

**Args3****[**

**x****]**returns the list of formal arguments of the user module, block or function

*At the same time, the argument*

**x.***can present an multiple object of the same name. The following fragment represents the source code of the*

**x***procedure with the most typical examples of its use.*

**Args3**In[3122]**:= M[x_ /; SameQ[x, "avz"], y_] := Module[**{**a, b, c**}**, y];**

**M[x_ /; x == "avz"] := Module[**{**a, b, c**}**, x];**

**M[x_ /; IntegerQ[x], y_String] := Module[**{**a, b, c**}**, x];**

**M[x_, y_] := Module[**{**a, b, c**}**, "agn"; x + y]; M[x_String] := x;**

**M[x_ /; ListQ[x], y_] := Block[**{**a, b, c**}**, "agn"; Length[x] + y];**

**F[x_ /; SameQ[x, "avz"], y_] := **{**x, y**}

In[3123]**:= Args3[s_ /; BlockFuncModQ[s]] :=**

**Module[**{**a = Headings[s], b, c = 7**}**,**

**If[SimpleListQ[a], a = **{**a**}**, Set[c, 77]]; a = Map[#[[2]] &, a];**

**b = Map[StringReplace[#, ToString[s] –> "", 1] &, a];**

**b = Map[StringToList[StringTake[#, **{**2, –2**}**]] &, b];**

**If[c == 77, b, Flatten[b, 1]]]**

In[3124]**:= Args3[M]**

Out[3124]**=** {{**"**x**_** /**;** ListQ[x]**", "**y**_"**}**,** {**"**x**_", "**y**_", "**z**_"**}**,**

{**"**x**_** /**;** x **===** \**"**avz\**"", "**y**_"**}}

In[3125]**:= Args3[F]**

Out[3125]**=** {**"**x**_** /**;** x **===** \**"**avz\**"", "**y**_"**}

In[3126]**:= Args3[L]**

Out[3126]**=** {**"**x**_", "**y**_"**}

At that, in case of the returned nested list its sub-lists define tuples of formal arguments in the order that is defined by order of components of * x* object according to the call

**Definition****[**

**x****].**

The following procedure is an useful modification of our argument processing means. The call **ArgsBFM1****[****x****]** generally returns the list of the *ListList*** **type whose two* -*element sub

*lists in string format determine the name of a formal argument*

**–***(*

**1**^{st}

*element)*and its admissibility test

*(*

**2**^{nd}

*element)*of block, function or module

**x****.**Lack of the test is coded as

**"**

*Arbitrary*

**";**in addition, under lack of test is understood not only its actual lack, but also the optional or default patterns ascribed to a formal argument. The procedure successfully processes the objects of the same name too, i.e. objects with several headings. The next fragment represents source code of the

**ArgsBFM1****procedure with typical examples of its application.**

In[3336]**:= ArgsBFM1[x_ /; BlockFuncModQ[x]] :=**

**Module[**{**b, c, d, g = **{}**, t, a = ToString2[Args[x]]**}**,**

**a = If[QmultiplePF[x], a, **{**a**}**];**

**Do[**{**b, c, d**}** = **{{}**, **{}**, **{}}**; t = a[[j]];**

**Do[AppendTo[b, If[ListQ[t[[k]]],**

**Map[StringSplit[#, **{**"/;", "__", "___", "_", ":", "_:", "_."**}**] &, t[[k]]],**

**StringSplit[t[[k]],**** **{**"****/;****",**** ****"__",**** ****"****___****",**** ****"_",**** ****"****:****",**** ****"****_:****",**** ****"****_.****"**}