Skip to content
Snippets Groups Projects
Commit eb33f305 authored by Stéphane Del Pino's avatar Stéphane Del Pino
Browse files

Correct many things as suggested by Emmanuel

parent 45618198
Branches
Tags
1 merge request!145git subrepo clone git@gitlab.com:OlMon/org-themes.git packages/org-themes
#+SETUPFILE: ../packages/org-themes/src/bigblow_inline/bigblow_inline.theme #+SETUPFILE: ../packages/org-themes/src/readtheorg_inline/readtheorg_inline.theme
#+STARTUP: org-pretty-entities entitiespretty #+STARTUP: org-pretty-entities entitiespretty
#+PROPERTY: header-args :comments no #+PROPERTY: header-args :comments no
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#+HTML_HEAD_EXTRA: <style> .remark{ @extend .todo !optional;} </style> #+HTML_HEAD_EXTRA: <style> .remark{ @extend .todo !optional;} </style>
#+LATEX_CLASS_OPTIONS: [10pt] #+LATEX_CLASS_OPTIONS: [10pt]
#+LATEX_HEADER: \usepackage[hmargin=2.5cm,vmargin=1.5cm]{geometry} #+LATEX_HEADER: \usepackage[hmargin=2.5cm,vmargin=1.5cm]{geometry}
#+LATEX_HEADER: \usepackage{ae,lmodern}
#+LATEX_HEADER: \usepackage[OT1]{fontenc}
#+LATEX_COMPILER: pdflatex --shell-escape #+LATEX_COMPILER: pdflatex --shell-escape
#+LATEX_HEADER_EXTRA: \usepackage{amsmath} #+LATEX_HEADER_EXTRA: \usepackage{amsmath}
...@@ -37,8 +39,7 @@ ...@@ -37,8 +39,7 @@
~pugs~[fn:pugs-def] is a general purpose solver collection built to ~pugs~[fn:pugs-def] is a general purpose solver collection built to
approximate solutions of partial differential equations. It is mainly approximate solutions of partial differential equations. It is mainly
(but not only) designed to deal with hyperbolic problems using (but not only) designed to deal with finite-volume methods.
finite-volume methods.
~pugs~ is a parallel software that uses ~MPI~[fn:MPI-def] and multi-threading ~pugs~ is a parallel software that uses ~MPI~[fn:MPI-def] and multi-threading
for parallelism. Multi-threading is achieved through an encapsulation for parallelism. Multi-threading is achieved through an encapsulation
...@@ -50,8 +51,7 @@ close to the mathematics) to build more complex solvers. This approach ...@@ -50,8 +51,7 @@ close to the mathematics) to build more complex solvers. This approach
is inspired by the success of [[http://freefem.org][FreeFEM]], which use a similar approach. is inspired by the success of [[http://freefem.org][FreeFEM]], which use a similar approach.
Before detailing the leading concepts and choices that we have made to Before detailing the leading concepts and choices that we have made to
develop ~pugs~, we give a simple example that should illustrate the develop ~pugs~, we give a simple example.
capabilities of the code.
** An example ** An example
For instance, the following code builds a uniform Cartesian grid of For instance, the following code builds a uniform Cartesian grid of
...@@ -276,28 +276,22 @@ common utilities are available directly in scripts. ...@@ -276,28 +276,22 @@ common utilities are available directly in scripts.
~pugs~ is a research oriented software, thus generally the user is also ~pugs~ is a research oriented software, thus generally the user is also
a developer. If this paragraph is indeed more dedicated to the a developer. If this paragraph is indeed more dedicated to the
developer, by reading it, the user will have a better understanding of developer, by reading it, the user will have a better understanding of
the development choices and the underlying policy that that the code the development choices and the underlying policy that the code
follows. follows.
Actually the development framework imposed by the DSL tends to guide Actually the development framework imposed by the DSL tends to guide
writing of new methods. writing of new methods.
- A natural consequence is that the developer is encourage to write - In the process of writing a *new numerical methods*, one must create
small independent ~C++~ methods (even if it does not forbid to write *new functions in the language*. Moreover, if a new method is close to
big monolithic pieces of code). However as already said, one should an existing one, it is generally *better* to use completely new
try to respect the following precept: write small piece of code to underlying ~C++~ code than to patch existing methods. Starting from a
ease their testing and validation, try to do simple things the right *copy* of the existing code ~C++~ is *encouraged* for developments. This
way. may sound weird since classical development guidelines encourage
- Also, in the process of writing a *new numerical methods*, one must inheritance or early redesign. Actually, this policy is the result
create *new functions in the language*. Moreover, if a new method is of the following discussion.
close to an existing one, it is generally *better* to use completely
new underlying ~C++~ code than to patch existing methods. Starting
from a *copy* of the existing code ~C++~ is *encouraged* for
developments. This may sound weird since classical development
guidelines encourage inheritance or early redesign. Actually, this
policy is the result of the following discussion.
- Using this approach, one *separates* clearly the *design* of a - Using this approach, one *separates* clearly the *design* of a
numerical method and the *design* of the code! numerical method and the *design* of the code.
- From the computer science point of view, early design for new - From the computer science point of view, early design for new
numerical methods is generally wrong: usually one cannot numerical methods is generally wrong: usually one cannot
anticipate precisely enough eventual problems or method anticipate precisely enough eventual problems or method
...@@ -368,12 +362,12 @@ generally the implementation itself. It is even more true when the ...@@ -368,12 +362,12 @@ generally the implementation itself. It is even more true when the
developer feels that changes to the code are natural and that the developer feels that changes to the code are natural and that the
modifications themselves look easy. Obviously, any experienced modifications themselves look easy. Obviously, any experienced
programmer knows that writing the code is only the first step of a programmer knows that writing the code is only the first step of a
much longer process which requires rigorous tests and validations, the much longer process which requires rigorous tests and validations (the
enrichment of a non-regression database. Generally one also desires to enrichment of a non-regression database). Generally one also desires
ensure that the development is used within the correct bounds which to ensure that the development is used within the correct bounds which
requires to implement data verification. In a perfect world, an requires to implement data verification. In a perfect world, an
up-to-date documentation of the functionality and its domain of up-to-date documentation of the functionality and its domain of
validity. validity should be provided.
This is even more true when defining a language (or a DSL). Enriching This is even more true when defining a language (or a DSL). Enriching
a language syntax (or grammar) is not something that must be done to a language syntax (or grammar) is not something that must be done to
...@@ -391,7 +385,7 @@ integrate low-level instructions. Low-level instructions give too much ...@@ -391,7 +385,7 @@ integrate low-level instructions. Low-level instructions give too much
freedom and thus are a source of errors. Several things are already freedom and thus are a source of errors. Several things are already
done to forbid this kind of evolution. The constness of high-level done to forbid this kind of evolution. The constness of high-level
data is a good illustration. For instance, meshes or discrete data is a good illustration. For instance, meshes or discrete
functions *cannot* be modified. This is not only a security to protects functions *cannot* be modified. This is not only a security to protect
the user from doing "dangerous" manipulations, but it also permits to the user from doing "dangerous" manipulations, but it also permits to
define high-level optimizations. define high-level optimizations.
- Since meshes are constant objects, one can for instance compute - Since meshes are constant objects, one can for instance compute
...@@ -517,11 +511,11 @@ produces the following compilation error ...@@ -517,11 +511,11 @@ produces the following compilation error
#+results: uninitialized-variable #+results: uninitialized-variable
For more complex constructions, it can be very difficult to detect it For more complex constructions, it can be very difficult to detect it
at /compile time/, this is why it is *encourage* to use variable at /compile time/, this is why it is *encouraged* to use variable
definition (see [[definition-simple-variables]]). definition (see [[definition-simple-variables]]).
Observe nonetheless, ~pugs~ checks at /run time/ that used variables are Observe nonetheless that ~pugs~ checks at /run time/ that used variables
correctly defined. If not an error is produced. are correctly defined. If not an error is produced.
#+END_warning #+END_warning
**** Definition of simple variables<<definition-simple-variables>> **** Definition of simple variables<<definition-simple-variables>>
...@@ -742,7 +736,7 @@ Here is a table of implicit type conversions *when allowed*. ...@@ -742,7 +736,7 @@ Here is a table of implicit type conversions *when allowed*.
| ~N~ | ~B~, ~Z~ | | ~N~ | ~B~, ~Z~ |
| ~Z~ | ~B~, ~N~ | | ~Z~ | ~B~, ~N~ |
| ~R~ | ~B~, ~N~, ~Z~ | | ~R~ | ~B~, ~N~, ~Z~ |
| ~R^1~ | ~B~, ~N~, ~Z~, ~R~, ~0~ (special value) | | ~R^1~ | ~B~, ~N~, ~Z~, ~R~ |
| ~R^2~ | ~0~ (special value) | | ~R^2~ | ~0~ (special value) |
| ~R^3~ | ~0~ (special value) | | ~R^3~ | ~0~ (special value) |
| ~R^1x1~ | ~B~, ~N~, ~Z~, ~R~, ~0~ (special value) | | ~R^1x1~ | ~B~, ~N~, ~Z~, ~R~, ~0~ (special value) |
...@@ -1171,73 +1165,27 @@ temporary. One will see bellow that one can write ~A = A*B;~ if needed. ...@@ -1171,73 +1165,27 @@ temporary. One will see bellow that one can write ~A = A*B;~ if needed.
- ~N~: natural integer ($\mathbb{N}$ or $\mathbb{Z}_{\ge0}$) left hand side variable. - ~N~: natural integer ($\mathbb{N}$ or $\mathbb{Z}_{\ge0}$) left hand side variable.
| ~/=~ allowed expression type | | ~/=~ allowed expression type |
|----------------------------| |----------------------------|
| ~B~ |
| ~N~ | | ~N~ |
| ~Z~ (for convenience) | | ~Z~ (for convenience) |
- ~Z~: integer ($\mathbb{Z}$) left hand side variable. - ~Z~: integer ($\mathbb{Z}$) left hand side variable.
| ~/=~ allowed expression type | | ~/=~ allowed expression type |
|----------------------------| |----------------------------|
| ~B~ |
| ~N~ | | ~N~ |
| ~Z~ | | ~Z~ |
- ~R~: real ($\mathbb{R}$) left hand side variable. - ~R~: real ($\mathbb{R}$) left hand side variable.
| ~/=~ allowed expression type | | ~/=~ allowed expression type |
|----------------------------| |----------------------------|
| ~B~ |
| ~N~ | | ~N~ |
| ~Z~ | | ~Z~ |
| ~R~ | | ~R~ |
- ~R^1~: vector of dimension 1 ($\mathbb{R}^1$) left hand side variable. - ~R^d~: the ~/=~ operator is not defined for left hand side vector (of
| ~/=~ allowed expression type | dimension $d\in\{1,2,3\}$) variables.
|----------------------------|
| ~B~ |
| ~N~ |
| ~Z~ |
| ~R~ |
- ~R^2~: vector of dimension 2 ($\mathbb{R}^2$) left hand side variable.
| ~/=~ allowed expression type |
|----------------------------|
| ~B~ |
| ~N~ |
| ~Z~ |
| ~R~ |
- ~R^3~: vector of dimension 3 ($\mathbb{R}^3$) left hand side variable.
| ~/=~ allowed expression type |
|----------------------------|
| ~B~ |
| ~N~ |
| ~Z~ |
| ~R~ |
- ~R^1x1~: matrix of dimensions $1\times1$ ($\mathbb{R}^{1\times1}$) left hand side variable.
| ~/=~ allowed expression type |
|----------------------------|
| ~B~ |
| ~N~ |
| ~Z~ |
| ~R~ |
- ~R^2x2~: matrix of dimension $2\times2$ ($\mathbb{R}^{2\times2}$) left hand side variable.
| ~/=~ allowed expression type |
|----------------------------|
| ~B~ |
| ~N~ |
| ~Z~ |
| ~R~ |
- ~R^3x3~: matrix of dimension $3\times3$ ($\mathbb{R}^{3\times3}$) left hand side variable.
| ~/=~ allowed expression type |
|----------------------------|
| ~B~ |
| ~N~ |
| ~Z~ |
| ~R~ |
- ~R^dxd~: the ~/=~ operator is not defined for left hand side matrix (of
dimension $d\times d$ with $d\in\{1,2,3\}$) variables.
**** Unary operators **** Unary operators
...@@ -1317,15 +1265,15 @@ Here is the list of binary operators ...@@ -1317,15 +1265,15 @@ Here is the list of binary operators
| keyword | operator | | keyword | operator |
|---------+-----------------------| |---------+-----------------------|
| ~and~ | logic and | | ~and~ | logic and |
| ~or~ | logic and | | ~or~ | logic or |
| ~xor~ | logic exclusive or | | ~xor~ | logic exclusive or |
|---------+-----------------------| |---------+-----------------------|
| ~==~ | equality | | ~==~ | equality |
| ~!=~ | non-equality | | ~!=~ | non-equality |
| ~<~ | lower than | | ~<~ | lower than |
| ~<=~ | lower than or equal | | ~<=~ | lower or equal than |
| ~>~ | greater than | | ~>~ | greater than |
| ~>=~ | greater than or equal | | ~>=~ | greater or equal than |
|---------+-----------------------| |---------+-----------------------|
| ~<<~ | shift left | | ~<<~ | shift left |
| ~>>~ | shift right | | ~>>~ | shift right |
...@@ -1419,12 +1367,20 @@ they follow a few rules. ...@@ -1419,12 +1367,20 @@ they follow a few rules.
\left| \left|
\begin{array}{rl} \begin{array}{rl}
\mathtt{+}:& \mathbb{S}_1 \times \mathbb{S}_2 \to \mathbb{N}\\ \mathtt{+}:& \mathbb{S}_1 \times \mathbb{S}_2 \to \mathbb{N}\\
\mathtt{*}:& \mathbb{S}_1 \times \mathbb{S}_2 \to \mathbb{N}\\ \mathtt{*}:& \mathbb{S}_1 \times \mathbb{S}_2 \to \mathbb{N}
\mathtt{/}:& \mathbb{S}_1 \times \mathbb{S}_2 \to \mathbb{N}
\end{array} \end{array}
\right. \right.
\end{equation*} \end{equation*}
#+end_src #+end_src
Boolean values (type ~B~) are not allowed as the right operand of a
division.
#+begin_src latex :results drawer :exports results
\begin{equation*}
\forall \mathbb{S} \in \{\mathbb{B},\mathbb{N}\},
\mathtt{/}: \mathbb{S} \times \mathbb{N} \to \mathbb{N}
\end{equation*}
#+end_src
Observe that ~-~ is *not* in the list. Observe that ~-~ is *not* in the list.
- Operators that return an integer ~Z~. - Operators that return an integer ~Z~.
...@@ -1443,6 +1399,15 @@ they follow a few rules. ...@@ -1443,6 +1399,15 @@ they follow a few rules.
\right. \right.
\end{equation*} \end{equation*}
#+end_src #+end_src
The divide operator does not allow boolean values as a right
operand.
#+begin_src latex :results drawer :exports results
\begin{align*}
\forall \mathbb{S}_1 \in \{\mathbb{B},\mathbb{N},\mathbb{Z}\}&\mbox{ and } \mathbb{S}_2 \in \{\mathbb{N},\mathbb{Z}\},
\mbox{ such that }\mathbb{S}_1 = \mathbb{Z}\mbox{ or }\mathbb{S}_2 = \mathbb{Z},\\
&\mathtt{/}: \mathbb{S}_1 \times \mathbb{S}_2 \to \mathbb{Z}.
\end{align*}
#+end_src
Finally the following operator is also defined Finally the following operator is also defined
#+begin_src latex :results drawer :exports results #+begin_src latex :results drawer :exports results
\begin{equation*} \begin{equation*}
...@@ -1461,12 +1426,20 @@ they follow a few rules. ...@@ -1461,12 +1426,20 @@ they follow a few rules.
\begin{array}{rl} \begin{array}{rl}
\mathtt{+}:& \mathbb{S}_1 \times \mathbb{S}_2 \to \mathbb{R}\\ \mathtt{+}:& \mathbb{S}_1 \times \mathbb{S}_2 \to \mathbb{R}\\
\mathtt{-}:& \mathbb{S}_1 \times \mathbb{S}_2 \to \mathbb{R}\\ \mathtt{-}:& \mathbb{S}_1 \times \mathbb{S}_2 \to \mathbb{R}\\
\mathtt{*}:& \mathbb{S}_1 \times \mathbb{S}_2 \to \mathbb{R}\\ \mathtt{*}:& \mathbb{S}_1 \times \mathbb{S}_2 \to \mathbb{R}
\mathtt{/}:& \mathbb{S}_1 \times \mathbb{S}_2 \to \mathbb{R}
\end{array} \end{array}
\right. \right.
\end{equation*} \end{equation*}
#+end_src #+end_src
The divide operator does not allow boolean values as a right
operand.
#+begin_src latex :results drawer :exports results
\begin{align*}
\forall \mathbb{S}_1 \in \{\mathbb{B},\mathbb{N},\mathbb{Z},\mathbb{R}\}&\mbox{ and } \mathbb{S}_2 \in \{\mathbb{N},\mathbb{Z},\mathbb{R}\},
\mbox{ such that }\mathbb{S}_1 = \mathbb{R}\mbox{ or }\mathbb{S}_2 = \mathbb{R},\\
&\mathtt{/}: \mathbb{S}_1 \times \mathbb{S}_2 \to \mathbb{Z}.
\end{align*}
#+end_src
- Operators that return a small vector ~R^d~. - Operators that return a small vector ~R^d~.
#+begin_src latex :results drawer :exports results #+begin_src latex :results drawer :exports results
...@@ -1523,7 +1496,7 @@ they follow a few rules. ...@@ -1523,7 +1496,7 @@ they follow a few rules.
**** Operator precedence and associativity **** Operator precedence and associativity
To avoid confusions, the operators precedence in ~pugs~ language follow To avoid confusions, the operators precedence in ~pugs~ language follows
the same rules as in ~C++~. the same rules as in ~C++~.
This is summarized in the following table, where ~a~ and ~b~ denotes two This is summarized in the following table, where ~a~ and ~b~ denotes two
...@@ -1640,20 +1613,22 @@ illustrate this, let us consider the following example. ...@@ -1640,20 +1613,22 @@ illustrate this, let us consider the following example.
In this example, we are dealing with 3 ~mesh~ variables. In this example, we are dealing with 3 ~mesh~ variables.
- First, ~m1~ is defined as a uniform cartesian mesh in dimension 2 of - First, ~m1~ is defined as a uniform cartesian mesh in dimension 2 of
$]0,1[^2$ made of $10\times10$ identical square cells. $]0,1[^2$ made of $10\times10$ identical square cells. Let us call this
- Then ~m2~ is a copy of the variable ~m1~. It is a copy of the variable, resident mesh $\mathcal{M}_a$ for clarity.
but the underlying mesh is *the same*! There is no duplication of the - Next, the variable ~m2~ is defined as a copy of the variable ~m1~. It is
mesh in memory. a copy of the variable, but its content is *the same*. The variable ~m2~
- Then, the mesh variable ~m3~ is *defined* to refer to a *new* mesh. It is is also referring to the mesh $\mathcal{M}_a$: there is no
/similar/ to the mesh contained in ~m1~ and ~m2~, but it is *not* the same duplication of the mesh in memory.
one! When ~m3~ is defined two meshes, (and two connectivities) are - Then, the variable ~m3~ is defined to refer to a *new* mesh (called
resident in memory. One of the mesh is referred by either ~m1~ or ~m2~ $\mathcal{M}_b$. It is /similar/ to $\mathcal{M}_a$, but it is *not* the
and the other one is referred by ~m3~. same one! When ~m3~ is defined two meshes $\mathcal{M}_a$ and
- Finally, the last instruction (~m3 = m1;~) sets ~m3~ to also refer the $\mathcal{M}_b$ (and two distinct connectivities) are resident in
mesh referred by ~m1~ and ~m2~. Since no other variable refers to its memory.
former mesh, the mesh is destroyed (memory is freed). At the end of - Finally, the last instruction (~m3 = m1;~) sets ~m3~ to also refer
the program, all the variables ~m1~, ~m2~ and ~m3~ are referring to the $\mathcal{M}_a$. Since no other variable refers to $\mathcal{M}_b$,
same mesh, and there is only one mesh that resides in memory. this mesh is destroyed (memory is freed). At the end of the program,
all the variables ~m1~, ~m2~ and ~m3~ are referring to $\mathcal{M}_a$
which is the only mesh that resides in memory.
*** Compound types *** Compound types
...@@ -1812,7 +1787,7 @@ boundary conditions to a method. ...@@ -1812,7 +1787,7 @@ boundary conditions to a method.
The ~pugs~ language supports classical statements to control the data The ~pugs~ language supports classical statements to control the data
flow. For simplicity, these statements syntax follow their ~C++~ flow. For simplicity, these statements syntax follow their ~C++~
counterpart. The only statement that is not implemented in ~pugs~ is the counterpart. The only statement that is not implemented in ~pugs~ is the
~switch...case~. This may change but in the one hand, up now to it was ~switch...case~. This may change but in the one hand, up to now it was
never necessary (we did not use chained ~if...else~ statements), and on never necessary (we did not use chained ~if...else~ statements), and on
the other hand, keeping the language as simple as possible remains the the other hand, keeping the language as simple as possible remains the
policy in ~pugs~ development. policy in ~pugs~ development.
...@@ -1868,15 +1843,6 @@ the conditional statements to use instruction blocks: ...@@ -1868,15 +1843,6 @@ the conditional statements to use instruction blocks:
cout << "sin(100)>0: " << sin100_positive << "\n"; cout << "sin(100)>0: " << sin100_positive << "\n";
#+END_SRC #+END_SRC
#+results: if-else-block-of-one #+results: if-else-block-of-one
Obviously in this simple case, it would be better to write
#+BEGIN_SRC pugs :exports both :results output
import math;
let sin100_positive:B, sin100_positive = (sin(100) > 0);
// parenthesis are useless but ease reading
cout << "sin(100)>0 ? " << sin100_positive << "\n";
#+END_SRC
but this is not the purpose here.
We give a final illustration We give a final illustration
#+NAME: if-block #+NAME: if-block
...@@ -1966,20 +1932,6 @@ construction which executes /at least/ one time the enclosed ~statement~. ...@@ -1966,20 +1932,6 @@ construction which executes /at least/ one time the enclosed ~statement~.
The ~statement~ is either a single instruction or a block of The ~statement~ is either a single instruction or a block of
instructions. The ~condition~ is an expression of boolean value (type instructions. The ~condition~ is an expression of boolean value (type
~B~). ~B~).
#+NAME: do-while-instr
#+BEGIN_SRC pugs :exports both :results output
let sum:N, sum = 0;
let i:N, i = 0;
do
sum += i++;
while (i<=10);
cout << "sum = " << sum << "\n";
#+END_SRC
This code produces
#+results: do-while-instr
However, to ease the reading, it is probably better to write
#+NAME: do-while-block #+NAME: do-while-block
#+BEGIN_SRC pugs :exports both :results output #+BEGIN_SRC pugs :exports both :results output
let sum:N, sum = 0; let sum:N, sum = 0;
...@@ -1990,7 +1942,7 @@ However, to ease the reading, it is probably better to write ...@@ -1990,7 +1942,7 @@ However, to ease the reading, it is probably better to write
} while (i<=10); } while (i<=10);
cout << "sum = " << sum << "\n"; cout << "sum = " << sum << "\n";
#+END_SRC #+END_SRC
It gives also It gives
#+results: do-while-block #+results: do-while-block
*** ~while~ loops *** ~while~ loops
...@@ -2012,7 +1964,7 @@ An example of the ~while~ loop is the following. ...@@ -2012,7 +1964,7 @@ An example of the ~while~ loop is the following.
#+BEGIN_SRC pugs :exports both :results output #+BEGIN_SRC pugs :exports both :results output
let sum:N, sum = 0; let sum:N, sum = 0;
let i:N, i = 1; let i:N, i = 1;
while (sum<=10) { while (i<=10) {
sum += i; sum += i;
++i; ++i;
} }
...@@ -2030,7 +1982,7 @@ statements. They follow their ~C++~ counterparts. ...@@ -2030,7 +1982,7 @@ statements. They follow their ~C++~ counterparts.
- The ~continue~ keyword is used to skip the instructions that follow in - The ~continue~ keyword is used to skip the instructions that follow in
the loop statement and continue the loop. the loop statement and continue the loop.
- The ~break~ keyword is leaves the current loop. - The ~break~ keyword leaves the current loop.
An example of use of the ~continue~ keyword is An example of use of the ~continue~ keyword is
#+NAME: nested-continue #+NAME: nested-continue
...@@ -2106,11 +2058,10 @@ functions. They act as operators. ...@@ -2106,11 +2058,10 @@ functions. They act as operators.
#+BEGIN_note #+BEGIN_note
Actually these functions are not strictly /pure functions/ in the Actually these functions are not strictly /pure functions/ in the
computer science sense. The reason for that is that they can computer science sense. The reason is that they can eventually have
eventually have side effects. A good example for that, is that it is side effects. As an example, it is possible to modify the random seed
possible to modify the random seed used by the code. In that case, the used by the code. In that case, the modified value is not a variable
modified value is not a variable of the language itself but the of the language itself but the internal random seed.
internal random seed.
#+END_note #+END_note
*** Implicit type conversion for parameters and returned values *** Implicit type conversion for parameters and returned values
...@@ -2159,7 +2110,7 @@ returned type ...@@ -2159,7 +2110,7 @@ returned type
#+BEGIN_SRC pugs :exports both :results output #+BEGIN_SRC pugs :exports both :results output
let f: R -> R^1, x -> 2*x; let f: R -> R^1, x -> 2*x;
cout << "f(3.2) = " << f(2.3) << "\n"; cout << "f(3.2) = " << f(3.2) << "\n";
#+END_SRC #+END_SRC
#+results: R-to-R1-function #+results: R-to-R1-function
...@@ -2226,10 +2177,11 @@ in function expressions. ...@@ -2226,10 +2177,11 @@ in function expressions.
cout << "plus(2.2) = " << plus(2.2) << "\n"; cout << "plus(2.2) = " << plus(2.2) << "\n";
cout << "plus(-3.2) = " << plus(-3.2) << "\n"; cout << "plus(-3.2) = " << plus(-3.2) << "\n";
#+END_SRC #+END_SRC
Running the example, one gets
#+results: non-arg-variables-in-functions
While the function itself is a constant object, one sees that since While the function itself is a constant object, one sees that since
the value of ~a~ is changed, the value function is implicitly the value of ~a~ is changed, the value function is implicitly
modified. /This is a dangerous feature and should be avoid!/ modified. /This is a dangerous feature and should be avoid!/
#+results: non-arg-variables-in-functions
Since functions themselves are variables one can use functions in Since functions themselves are variables one can use functions in
function expressions. function expressions.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment