• Aucun résultat trouvé

Definition of the user functions and pure functions in software of theMathematicasystem

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

Chapter 6. Problems of procedural programming in the Mathematicasoftware

6.2. Definition of the user functions and pure functions in software of theMathematicasystem

First of all, we will notice that so –calledfunctional programming isn’t any discovery ofMathematica system, and goes back to a number of software means that appeared long before the above system. In this regard we quite pertinently have focused slightly more in details the attention on theconcept of functional programming in a historical context [30-33]. Whereas here we only will note certain moments characterizing specifics of the paradigm of functional programming. We will note only that the foundation offunctional programming has been laid approximately at the same time, asimperative programming that is the most widespread now, i.e. in the30th years of the last century.A. Church(USA)–

the author ofλ–calculus and one of founders of the concept of Homogeneous

structures(Cellular Automata) in connection with his works in the field of infinite abstract automata and mathematical logic along withH. Curry(England) andM.

Schönfinkel(Germany) that have developed the mathematical theory ofcombinators, with good reason can be considered as the main founders of mathematical foundation of

functional programming. At that,functional programming languages, especiallypurely functional ones such asHope andRex, have largely been used in academical circles rather than in commercial software development. While prominent functional programming languages such asLisp have been used in industrial and commercial applications. Today, functional programming paradigm is also supported in somedomain-specific programming languages for example byMathlanguage of theMathematica system. From rather large number of languages of functional programming it is possible to note the following

languages which exerted a great influence on progress in this field, namely: Lisp, Scheme, ISWIM, familyML, Miranda, Haskell, Clean, etc. [33]. By and large, if theimperative languages are based on operations of assignment and cycle, thefunctional languages on recursions. From advantages of functional languages can be noted the following the most important, namely:

–programs on functional languagess as a rule are much shorter and simpler than their analogs on imperative languages;

–almost all modern functional languages are strictly typified ensuring the safety of programs;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 call;

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

languages can imitate the certain useful imperative properties. Not all functional languages are pure forasmuch in many 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 [74]. While with quite interesting critical remarks on functional languages and possible ways of their elimination it is possible to familiarize oneself in [28-33,75].

A series of concepts and paradigms are specific for functional programming and are absent inimperative programming. Meanwhile, many programming languages, as a rule, are

based on several paradigms of programming, thus imperative programming languages can quite use and concepts offunctional programming. In particular, as an important enough concept are so–called pure functions, whose result of performance depends only on their factual 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.

Questions of realization of certain properties of pure functions in the environment of imperativeMaple–language have been considered in [28-33]. In principle, there are no special difficulties for programming in the functional style in languages that aren’t the functional. TheMath–language professing the mixed paradigm of functional and procedural programming supports functional programming, then theMaple–language professing the concept of especially procedural programming at the same time only allows certain elements of functional programming.

However, first of all a few words about the system functions, i.e. functions belonging properly to the Math–language and its environment. Generally speaking, to call these system tools by functions is not entirely correct since realization of many of them is based on the procedural organization, but we stopped on such terminology inherent actually to the system. So, theMathematica system has very large number of the built-in functions, at the same time it provides simple enough mechanisms for definition of the user functions.

In the simplest case a certain functionF with several formal argumentsx, y, z, … has the following very simple format, namely:

F[x_,y_,z_,…] {:=|=}an expression dependent on variables x, y, z,… as a rule

So, F[x_]:=x^3+80 defines the functionF(x)=x^3+80 in standardmathematical notation;

the call of such function on concrete actual argument is defined as F[x], in particular, as illustrates the following simple example, namely: In[2442]:= F[x_] := x^3 + 90; F[500]

Out[2442]= 125000090

For receiving of definition of an arbitrary function (and not only functions,but an arbitrary definition on the basis of operator of postponed“:=”or immediate“=” assignments),

excepting the built–in functions, serve the built–inDefinition function along with our means considered in the previous section, allowing to receive the optimized definitions in the above sense of as procedures and functions. We will consider briefly elements of functional programming in theMathematica in whose basis the concept of thepure

function lays. So, thepure functions– one of the basic concepts offunctional programming that is a component of all programming system in theMathematica in general. Further, the questions relating to this component will be considered in more detail, here we will define only the basic concepts. In theMathematica pure functions are defined as follows.

A pure function in the environment of the Mathematica has the following three formats of coding, namely:

Function[x, Function body] –a pure function with one formal argumentx;

Function[ {x1,x2, …,xp},Function body] –a pure function with formal argumentsx1, x2,

…,xp;

(Function body)& –a pure function with formal arguments#,#1,#2,…, #n.

At that, at using of the third format that is often called as short form of pure function for its identification theampersand (&) serves whose absence causes either erroneous

situations or incorrect results at impossibility to identify the demanded pure function. The reader familiar with formal logic or theLisp programming language can simply identify pure functions with unnamed functions orλ–expressions. Moreover, the pure functions are rather close to mathematical concept of operators. In definition of apure function

so–called substitutes(#) of variables are used, namely:

# –the first variable of a pure function;

#n – n–th variable of a pure function;

## –sequence of all variables of a pure function;

##n –sequence of variables of a pure function starting withn–th variable.

At application of pure functions, unlike traditional functions and procedures, 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. So, selection from a listW of the elements meeting certain conditions and elementwise application of a function to elements of a list can be carried out by constructions of the formatSelect[W, Test[#] &] andMap[F[#] &,W]

respectively as illustrates the following simple example, namely:

In[2341] := Select [{a, 72, 75, 42, g,67,Art, Kr, 2015, s,47,500}, IntegerQ[#] &]

Out[2341]= {72, 75, 42, 67, 2015, 47, 500}

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

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

At using 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, the expression#1+ #2– #3+

#2& withoutparentheses is correct while, generally speaking, they are obligatory, in

particular, at using of apure function as the right part of a transformation rule as illustrates very simple example: In[2392]:= {a /. a–> #1 + #2 + #3 &, a /. a–> (#1 + #2 + #3 &)}

Out[2392]= {a /. a–> #1+ #2+ #3&, #1+ #2+ #3&}

In[2393]:= {Replace[a, a–> #1*#2*#3 &], a /. a–> (#1*#2*#3 &)}

Replace::reps: {a–> #1#2#3&} is neither a list of replacement rules nor a valid dispatch table, and so cannot be used for replacing. >> Out[2393]= {Replace[a, a–> #1#2#3&],

#1#2#3&}

In combination with a number of functions, in particular, Map, Select and some others the using of pure functions is rather convenient, therefore the question of converting from traditional functions into pure functions seems a quite topical; for its decision various approaches, including creation of the program converters can be used. We used pure

functions a rather widely at programming of a number of problems of different types of the applied and the system character [28-33,48].

The following procedure provides converting of a function determined by the formatG[x_, y_, …]: =W(x, y, …) into pure function of any admissible format, namely: the

callFuncToPure[x] returns the pure function that is an analog of a functionx of the third format, whereas the callFuncToPure[x, p] wherep – any expression, returns pure function of thetwo first formats. The fragment below represents source code of theFuncToPure procedure along with typical examples of its usage.

In[2822] := FuncToPure[x_ /; QFunction[ToString[x]], y___] := Module[{d, t, a = HeadPF[x], b = Map[ToString, Args[x]], c = Definition2[x][[1]], k = 1, h, g = {}, p}, d

= Map[First, Mapp[StringSplit, b, “_”]]; p = StringTrim[c, a <> ” := “]; h = “Hold[”

<> p <> “]”; {t, h}= {Length[b], ToExpression[h]}; While[k <= t, AppendTo[g, d[[k]]

<> “–> #” <> ToString[k]]; k++]; h = ToString1[ReplaceAll[h, ToExpression[g]]]; g = StringTake[h, {6,–2}]; ToExpression[If[{y}!= {}, “Function[” <> If[Length[b] == 1, StringTake[ToString[d], {2,–2}], ToString[d]] <> “, ” <> p <> “]”, g <> ” &”]]]

In[2823] := G[x_Integer, y_Integer, z_Real] := z*(x + y) + Sin[x*y*z]; FuncToPure[G]

Out[2823]=#3 (#1+ #2) + Sin[#1#2#3]&

In[2824]:= G[x_Integer, y_Integer, z_Real] := z*(x + y) + Sin[x*y*z]; FuncToPure[G, 80]

Out[2824]= Function[{x, y, z}, z*(x+ y)+ Sin[x*y*z]]

In[2825]:= V[x_ /; IntegerQ[x]] := If[PrimeQ[x], True, False];

Select[{47, 72, 25, 18, 480, 13, 7, 41, 561, 2, 123, 322, 17, 23}, FuncToPure[V]]

Out[2825]= {47, 13, 7, 41, 2, 17, 23}

In[2826]:= {S[x_] := x^2 + 23*x + 16; FuncToPure[S, 47], FuncToPure[S][80]}

Out[2826]= {Function[x, x^2+ 23*x+ 16], 8256}

However, at using of the FuncToPure procedure for converting of a certain traditional function into pure function it must be kept in mind a number of the essential enough

moments. First, the resultant pure function won’t have attributes, options and initial values of arguments along with logic tests for admissibility of the actual arguments. Secondly, a converting automatically doesn’t do the resultant function as a pure function if a original traditional function such wasn’t, i.e. result of the procedure call should depend only on the obtained actual arguments. A number of useful means of operating with pure functions will be considered in the book slightly below.

On the other hand, the following procedure in a certain measure is inverse to the previous procedure, its callPureToFunc[x, y] wherex – definition of a pure function, andy – an unevaluated symbol– returnsNull, i.e. nothing, providing converting of definition of a pure functionx into the evaluated definition of equivalent function with a namey. In addition, on inadmissible actual arguments the procedure call is returned unevaluated. The fragment below represents source code of the procedure with an example of its usage.

In[2525]:= PureToFunc[x_ /; PureFuncQ[x], y_ /; ! HowAct[y]] :=

Module[ {a = Map[ToString, OP[x]], b, c, d, k = 1}, b = Select[a, StringTake[#, {1, 1}]

== “#” &]; d = Map[StringReplace[#, “#”–> “x”] &, b]; c = ToString[y] <> “[“;

For[k, k <= Length[b], k++, c = c <> d[[k]] <> “_,”]; c = StringTake[c, {1,–2}] <> “]

:= “; ToExpression[StringTake[c <> StringReplace[ToString1[x], GenRules[b, d]], {1,–4}]]]

In[2526] := PureToFunc[#4*(#1 + #2)/(#3–#4) + #1*#4 &, Gs] In[2527]:=

Definition[Gs]

Out[2527]= Gs[x1_, x2_, x3_, x4_]:= (x4 (x1+ x2))/(x3– x4)+ x1 x4

Unlike FuncToPure the callModToPureFunc[x] provides the converting of a module or blockx into pure function under following conditions:(1) the module/blockx can’t have local variables or all local variables should have initial values;(2) the module/blockx can’t have active global variables, i.e. variables for which in an arbitrary objectx assignments are done;(3) formal arguments of the returned function don’t save tests for their

admissibility; (4) the returned function inherits attributes and options of an objectx. The fragment below represents procedure code with examples of its application.

In[2428] := ModToPureFunc[x_ /; QBlockMod[x]] := Module[{a, c, d, p, j, t, Atr = Attributes[x], O = Options[x], n = “$$$” <> ToString[x], b =

Flatten[{PureDefinition[x]}][[1]], k = 1, q = {}}, ToExpression[“$$$” <> b]; c = LocalsGlobals1[Symbol[n]]; a = Args[Symbol[n], 80]; d =

StringReplace[PureDefinition[n], HeadPF[n] <> ” := “–> ””, 1];

ToExpression[“ClearAll[” <> n <> “]”]; If[c[[3]] != {}, Return[{$Failed, “Globals”, c[[3]]}]]; c = Map[{#, ToString[Unique[#]]}&, Join[a, c[[1]]]]; While[k <= Length[c], p = c[[k]]; d = StringReplaceS[d, p[[1]], p[[2]]]; k++]; d = ToString[ToExpression[d]];

t = Map[ToString, UnDefVars[ToExpression[d]]];

t = Map[StringTake[#, {1, If[StringFreeQ[#, “$”],–1, Flatten[StringPosition[#, “$”]]

[[1]]–1]}] &, t]; k = 1; While[k <= Length[t], j = 1; While[j <= Length[c], If[t[[k]] ==

c[[j]][[2]], AppendTo[q, c[[j]][[1]]]]; j++]; k++]; k = 1; While[k <= Length[c], p = c[[k]]; d = StringReplaceS[d, p[[2]], p[[1]]]; k++]; If[p = MinusList[q, a]; p != {}, {$Failed, “Locals”, p}, ToExpression[“ClearAll[” <> n <> “]”]; n = “$$$” <>

ToString[x]; ToExpression[n <> ” := Function[” <> ToString[a] <> “, ” <> d <> “]”];

If[Atr != {}, ToExpression[“SetAttributes[” <> n <> “,” <>

ToString[Atr] <> “]”]]; If[O != {}, ToExpression[“SetOptions[” <> n <> “,” <>

ToString[O] <> “]”]]; n]] In[2429]:= B[x_, y_] := Block[{a, b = 80, c, d}, (a + b + c)*(x + y + d)]; B1[x_, y_] := Block[{a = 480, b = 80, c = 72}, (a + b + c)*(x + y)];

SetAttributes[B1, {Protected, Listable}]; B2[x_, y_] := Block[{a = 480, b = 80}, h = (a + b)*(x + y); t = 42]; B3[x_, y_] := Block[{a = 480, b, c}, h = (a + b + c)*(x + y); g = 67]; B4[x_, y_] := Block[{a = 480, b = 80}, h = (a + b)*(x + y); t = z]; B5[x_, y_] :=

Module[{a = 480, b, c, d = 80}, (a + b)*(c + d)]

In[2430] := ModToPureFunc[B]

Out[2430]= {$Failed, “Locals“, {”a“, “c“, “d”}}

In[2431]:= ModToPureFunc[B1]

Out[2431]= “$$$B1”

In[2432]:= Definition[“$$$B1”]

Out[2432]= Attributes[$$$B1]= {Listable, Protected}

$$$B1:= Function[{x, y}, 632*(x+ y)]

In[2433] := ModToPureFunc[B2]

Out[2433]= {$Failed, “Globals“, {”h“, “t”}}

In[2434]:= ModToPureFunc[B3]

Out[2434]= {$Failed, “Globals“, {”h“, “g”}}

In[2435]:= ModToPureFunc[B4]

Out[2435]= {$Failed, “Globals“, {”h“, “t”}}

In[2436]:= ModToPureFunc[B5]

Out[2436]= {$Failed, “Locals“, {”b“, “c”}}

In[2437]:= A[m_, n_, p_ /; IntegerQ[p], h_ /; PrimeQ[h]] :=

Module[ {a = 42.80}, h*(m+n+p)/a] In[2438]:= ModToPureFunc[A]

Out[2438]= “$$$A”

In[2439]:= Definition[“$$$A”]

Out[2439]= $$$A:= Function[{m, n, p, h}, 0.0233645*h*(m+ n+ p)] In[2440]:= M[x_, y_

/; StringQ[y]] := Module[{a, b = 80, c = 6, d}, a*x + b*y] In[2441]:= SetAttributes[M, Protected]; ModToPureFunc[M] Out[2441]= {$Failed, “Locals“, {”a“, “d”}}

In[2442]:= G[x_] := Module[{a = 90, b = 500}, a + b]; ModToPureFunc[G];

Definition[$$$G]

Out[2442]= $$$G:= Function[{x}, 590]

A successful call ModToPureFunc[x] returns the name of the resultant pure function in the formToString [Unique[x]], otherwise procedure call returns the nested list of the format {$Failed, {”Locals”|”Globals”}, {list of variables in string format}} whose the first element$Failed determines inadmissibility of converting,second element– the type of the variables that were as a reason of it while the third element– the list of variables of this type in string format. At that, the name of a block or module should be as the actual

argumentx, otherwise the procedure call is returned unevaluated. Along with standard means the procedure in very essential degree uses our proceduresHeadPF,

Args,LocalsGlobals1, ClearAllMinusList, PureDefinition, StringReplaceS,

QBlockMod, UnDefVars that are considered in the present book and in considered in the present book and in 33], that allowed to considerably simplify programming of this

procedure. These means and at programming some other appendices are rather useful. In general, it must be kept in mind that the mechanism of thepure functions composes a core of the paradigm offunctional programming inMathematica.

6.3. Means of testing of procedures and functions in the

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