[translation] scripts and functions done... maybe

This commit is contained in:
Jan Grewe 2016-10-14 12:16:43 +02:00
parent 40d2eb4aa0
commit d23c2f577e
2 changed files with 130 additions and 94 deletions

View File

@ -29,6 +29,10 @@
\item Doppelte for-Schleife
\item File output and input (load, save, fprintf, scanf) (extra chapter?)
\item help() und doc()
\item A box about sampling of contiunous data.
\item A box about foo and bar?
\item function arguments, order does matter, names do as well.
\item function return values. order does not matter, names do
\end{itemize}
\end{document}

View File

@ -15,7 +15,7 @@ variable is read from the memory, this binary pattern is interpreted
according to the data type. The example shown in
figure~\ref{variablefig} shows that the very same bit pattern is either
interpreted as a 8-bit integer type (numeric value 38) or as a
ampersand (&) character. In \matlab{} data types are of only minor
ampersand (\&) character. In \matlab{} data types are of only minor
importance but there are occasions where it becomes important to know
the type of a variable and we will come back to them later on.
@ -261,7 +261,7 @@ c =
The length of a vector, that is the number of elements, can be
requested using the \code{length()} or \code{numel()}
functions. \code{size()} provides the same information in a slightly,
yet more powerful way (listing~\ref{vectorsizelisting}). The above
yet more powerful way (listing~\ref{vectorsizeslisting}). The above
used vector \varcode{a} has the following size:
\begin{lstlisting}[label=vectorsizeslisting, caption={Size of a vector.}]
@ -937,9 +937,10 @@ The basic concept is that applying a Boolean operation on a vector
results in a \code{logical} vector of the same size (see
listing~\ref{booleanexpressions}. This logical vector is then used to
select only those values for which the logical vector is true. Line 14
in listing~\ref{logicalindexing} can be read: ``Give me all those
in listing~\ref{logicalindexing1} can be read: ``Select all those
elements of \varcode{x} where the Boolean expression \varcode{x < 0}
evaluates to true''.
evaluates to true and store the result in the variable
\emph{x\_smaller\_zero}''.
\begin{lstlisting}[caption={Logical indexing.}, label=logicalindexing1]
>> x = randn(1, 6) % a vector with 6 random numbers
@ -1193,7 +1194,7 @@ that defines against which the \emph{switch expression} is tested. It
is important to note that the case expression always checks for
equality! Optional the case expressions may be followed by the keyword
\code{otherwise} which catches all cases that were not explicitly
stated above (listing~\ref{switchlistin}).
stated above (listing~\ref{switchlisting}).
\begin{lstlisting}[label=switchlisting, caption={Structure of a \varcode{switch} statement.}]
@ -1309,20 +1310,20 @@ programs increases the re-usability. So far we have used
\emph{scripts} to store the solutions of the exercises. Any variable
that was created appeared in the \codeterm{workspace} and existed even
after the program was finished. This is very convenient but also bears
some risks. Consider the case that \file{script_a.m} creates a certain
variable and assigns a value to it for later use. Now it calls a
second program (\file{script_b.m}) that, by accident, uses the same
some risks. Consider the case that \file{script\_a.m} creates a
certain variable and assigns a value to it for later use. Now it calls
a second program (\file{script\_b.m}) that, by accident, uses the same
variable name and assigns a different value to it. When
\file{script_b.m} is done, the control returns to \file{script_a.m}
and if it now want to read the previously stored variable, it will
\file{script\_b.m} is done, the control returns to \file{script\_a.m}
and if it now wants to read the previously stored variable, it will
contain a different value than expected. Bugs like this are hard to
track down since each of the programs alone is perfectly fine and
works as intended. A solution for this problem are the
find since each of the programs alone is perfectly fine and works as
intended. A solution for this problem are the
\codeterm[Function]{functions}.
\subsection{Functions}
Functions in \matlab{} are similar to a mathematical functions
Functions in \matlab{} are similar to mathematical functions
\[ y = f(x) \] Here, the mathematical function has the name $f$ and it
has one \codeterm{argument} $x$ that is transformed into the
function's output value $y$. In \matlab{} the syntax of a function
@ -1361,10 +1362,10 @@ using functions instead of scripts we gain several advantages:
\end{itemize}
The following listing (\ref{badsinewavelisting}) shows a function that
calculates and displays a bunch of sines with different amplitudes.
calculates and displays a bunch of sine waves with different amplitudes.
\begin{lstlisting}[caption={Bad example of a function that displays a series of sines.},label=badsinewavelisting]
\begin{lstlisting}[caption={Bad example of a function that displays a series of sine waves.},label=badsinewavelisting]
function meineFirstFunction() % function head
t = (0:0.01:2);
frequency = 1.0;
@ -1407,36 +1408,36 @@ defined:
As indicated above the \code{myFirstFunction} does three things at
once, it seems natural, that the task should be split up into three
parts. (i) Calculation of the individual sine-wave defined by the
frequency and the amplitude (ii) graphical display of the data and
parts. (i) Calculation of the individual sine waves defined by the
frequency and the amplitudes (ii) graphical display of the data and
(iii) coordination of calculation and display.
\paragraph{I. Calculation of a single sine-wave}
\paragraph{I. Calculation of a single sine wave}
Before we start coding it is best, to again think about the task and
Before we start coding it is best to again think about the task and
define (i) how to name the function, (ii) which information it needs
(arguments), and (iii) what it should return to the caller.
\begin{enumerate}
\item \codeterm[Funktion!Name]{Name}: der Name sollte beschreiben, was
die Funktion tut. In diesem Fall berechnet sie einen Sinus. Ein
geeigneter, kurzer Name w\"are also \code{sinewave()}.
\item \codeterm[Funktion!Argumente]{Argumente}: die zu brechnende
Sinusschwingung sei durch ihre Frequenz und die Amplitude
bestimmt. Des Weiteren soll noch festgelegt werden, wie lang der
Sinus sein soll und mit welcher zeitlichen Aufl\"osung gerechnet
werden soll. Es werden also vier Argumente ben\"otigt, sie k\"onnten
hei{\ss}en: \varcode{amplitude}, \varcode{frequency},
\varcode{t\_max}, \varcode{t\_step}.
\item \codeterm[Funktion!R{\"u}ckgabewerte]{R\"uckgabewerte}: Um den
Sinus korrekt darstellen zu k\"onnen brauchen wir die Zeitachse und
die entsprechenden Werte. Es werden also zwei Variablen
zur\"uckgegeben: \varcode{time}, \varcode{sine}
\item \codeterm[Function!Name]{Name}: the name should be descriptive
of the function's purpose, i.e. the calculation of a sine wave. A
appropriate name might be \code{sinewave()}.
\item \codeterm[Function!Arguments]{Arguments}: What information does
the function need to do the calculation? There are obviously the
frequency as well as the amplitude. Further we may want to be able
to define the duration of the sine wave and the temporal
resolution. We thus need four arguments which should also named to
describe their content: \code{amplitude, frequency, t\_max,} and
\code{t\_step} might be good names.
\item \codeterm[Function!Return values]{Return values}: For a correct
display of the data we need two vectors. The time, and the sine wave
itself. We just need two return values: \varcode{time}, \varcode{sine}
\end{enumerate}
Mit dieser Information ist es nun gut m\"oglich die Funktion zu
implementieren (Listing \ref{sinefunctionlisting}).
\begin{lstlisting}[caption={Funktion zur Berechnung eines Sinus.}, label=sinefunctionlisting]
Having defined this we can start coding
(listing~\ref{sinefunctionlisting}).
\begin{lstlisting}[caption={Function that calculates a sine wave.}, label=sinefunctionlisting]
function [time, sine] = sinewave(frequency, amplitude, t_max, t_step)
% Calculate a sinewave of a given frequency, amplitude,
% duration and temporal resolution.
@ -1452,23 +1453,36 @@ function [time, sine] = sinewave(frequency, amplitude, t_max, t_step)
% time: vector of the time axis
% sine: vector of the calculated sinewave
time = (0:t_step:t_max);
sine = sin(frequency .* time .* 2 * pi) .* amplitude;
sine = sin(frequency .* time .* 2 .* pi) .* amplitude;
end
\end{lstlisting}
\paragraph{II. Plotten einer einzelnen Schwingung}
Das Plotten der berechneten Sinuschwingung kann auch von einer
Funktion \"ubernommen werden. Diese Funktion hat keine andere Aufgabe,
als die Daten zu plotten. Ihr Name sollte sich an dieser Aufgabe
orientieren (z.B. \code{plotFunction()}). Um einen einzelnen Sinus
zu plotten werden im Wesentlichen die x-Werte und die zugeh\"origen
y-Werte ben\"otigt. Da mehrere Sinus geplottet werden sollen ist es
auch sinnvoll eine Zeichenkette f\"ur die Legende an die Funktion zu
\"ubergeben. Da diese Funktion keine Berechnung durchf\"uhrt wird kein
R\"uckgabewert ben\"otigt (Listing \ref{sineplotfunctionlisting}).
\begin{lstlisting}[caption={Funktion zur graphischen Darstellung der Daten.}, label=sineplotfunctionlisting]
\paragraph{II. Plotting a single sine wave}
The display of the sine waves can also be delegated to a function. We
can now decide whether we want the function to plot all sine waves at
once, or if we want design a function that plots a single sine wave
and that we then call repeatedly for each frequency/amplitude
combination. The most flexible approach is the latter and we will
thus implement it this way. We might come up with the following
specification of the function:
\begin{enumerate}
\item It should plot a single sine wave. But it is not limited to sine
waves. It's name is thus: \code{plotFunction()}.
\item What information does it need to solve the task? The
to-be-plotted data as there is the values \code{y\_data} and the
corresponding \code{x\_data}. As we want to plot series of sine
waves we might want to have a \code{name} for each function to be
displayed in the figure legend.
\item Are there any return values? No, this function is just made for
plotting, we do not need to return anything.
\end{enumerate}
With this specification we can start to implement the function
(listing~\ref{sineplotfunctionlisting}).
\begin{lstlisting}[caption={Function for the graphical display of data.}, label=sineplotfunctionlisting]
function plotFunction(x_data, y_data, name)
% Plots x-data against y-data and sets the display name.
%
@ -1483,31 +1497,41 @@ end
\end{lstlisting}
\paragraph{III. Erstellen eines Skriptes zur Koordinierung}
Die letzte Aufgabe ist die Koordinierung der Berechung und des
Plottens f\"ur mehrere Amplituden. Das ist die klassische Aufgabe
f\"ur ein \codeterm{Skript}. Auch hier gilt es einen ausdrucksvollen
Name zu finden. Da es keine Argumente und R\"uckgabewerte gibt,
m\"ussen die ben\"otigten Informationen direkt in dem Skript
defniniert werden. Es werden ben\"otigt: ein Vektor f\"ur die
Amplituden, je eine Variable f\"ur die gew\"unschte Frequenz, die
maximale Zeit auf der x-Achse und die zeitliche Aufl\"osung. Das
Skript \"offnet schlie{\ss}lich noch eine neue Abbildung mit
\code{figure()} und setzt das \code{hold on} da nur das Skript
wei{\ss}, das mehr als ein Plot erzeugt werden soll. Das Skript ist in
Listing \ref{sinesskriptlisting} dargestellt.
\begin{lstlisting}[caption={Kontrollskript zur Koordination von Berechnung und graphischer Darstellung.},label=sinesskriptlisting]
\paragraph{III. One script to rule them all}
The last task is to write a script to control the calculations and the
plotting of the sine waves. Classically, such controlling of sub-tasks
is handled in a script. It could be done with a function but if
there is a reason for the existence of scripts then it is this.
Again, we need to specify what needs to be done:
\begin{enumerate}
\item The task is to display multiple sine waves. We want to have a
fixed frequency but there should be various amplitudes displayed. An
appropriate name for the script (that is the name of the m-file)
might be \file{plotMultipleSinewaves.m}.
\item What information do we need? we need to define the
\code{frequency}, the range of \code{amplitudes}, the
\code{duration} of the sine waves, and the temporal resolution given
as the time between to points in time, i.e. the \code{stepsize}.
\item We then need to create an empty figure, and work through the
rang of \code{amplitudes}. We must not forget to switch \code{hold
on} if we want to see all the sine waves in one plot.
\end{enumerate}
The implementation is shown in listing~\ref{sinesskriptlisting}.
\begin{lstlisting}[caption={Control script for the plotting of sine waves.},label=sinesskriptlisting]
amplitudes = 0.25:0.25:1.25;
frequency = 2.0;
t_max = 10.0;
t_step = 0.01;
duration = 10.0; % seconds
stepsize = 0.01; % seconds
figure()
hold on
for i = 1:length(amplitudes)
[x_data, y_data] = sinewave(frequency, amplitudes(i), ...
t_max, t_step);
duration, stepsize);
plotFunction(x_data, y_data, sprintf('freq: %5.2f, ampl: %5.2f',...
frequency, amplitudes(i)))
end
@ -1516,34 +1540,42 @@ legend('show')
\end{lstlisting}
\begin{exercise}{plotMultipleSinewaves.m}{}
Erweiter das Programm so, dass die Sinusse f\"ur einen Satz von
Frequenzen geplottet wird.
Extend the program to plot also a range of frequencies.
\pagebreak[4]
\end{exercise}
\subsection{Einsatz von Funktionen und Skripten}
Funktionen sind kleine Codefragmente, die im Idealfall genau eine
Aufgabe erledigen. Sie besitzen einen eigenen
\determ{G\"ultigkeitsbereich}, das hei{\ss}t, dass Variablen aus dem
globalen Workspace nicht verf\"ugbar sind und Variablen, die lokal in
der Funktion erstellt werden nicht im globalen Workspace sichtbar
werden. Dies hat zur Folge, dass Funktionen all die Informationen, die
sie ben\"otigen, von au{\ss}en erhalten m\"ussen. Sie nehmen
\determ{Argumente} entgegen und k\"onnen \determ{R\"uckgabwerte}
zur\"uckliefern.
Die Verwendung von Funktionen ist der Verwendung von Skripten fast
immer vorzuziehen sind. Das hei{\ss}t aber nicht, das Skripte zu
verteufeln w\"aren und und vermieden werden sollten. In Wahrheit sind
beide daf\"ur gemacht, Hand in Hand ein Problem zu l\"osen. W\"ahrend
die Funktionen relativ kleine ``verdauliche'' Teilprobleme l\"osen,
werden Skripte eingesetzt um den Rahmen zu bilden und den Ablauf zu
koordinieren (Abbildung \ref{programlayoutfig}).
\begin{figure}
\includegraphics[width=0.5\columnwidth]{simple_program.pdf}
\titlecaption{Ein typisches Programmlayout.}{Das Kontrollskript
koordiniert den Aufruf der Funktionen, \"ubergibt Argumente und
nimmt R\"uckgabewerte entgegen.}\label{programlayoutfig}
\end{figure}
\begin{ibox}[t]{\label{whenscriptsbox}When to use scripts and functions}
It is easily possible to solve any programming problem only with
functions. Avoiding functions is also possible but ends very messy
and extremely hard to debug when the project grows. The effort for
avoiding naming conflicts or cleaning up the workspace increases
with the size of the project. Generally, functions should be
preferred over scripts in almost all cases. There are, however,
situations when a script offers advantages.
\begin{minipage}{0.5\textwidth}
\includegraphics[width=0.9\columnwidth]{simple_program}
\end{minipage}
\begin{minipage}{0.5\textwidth}
\textbf{Controlling a task} that involves calling sub-routines, as
we did above, is one of these situations (see figure). The script
calls functions and takes care of passing the right arguments and
storing the return values. During the development phase a script
grows as one \emph{interactively} works on the command
line. Commands that have been tested are then transferred to the
script.
\end{minipage}\vspace{0.25cm}
Interactive programming is one of the main strengths of
\matlab{}. Interactive refers to the interaction between the
commands executed on the command line and the variables stored in
the workspace. The immediate feedback if a certain operation works
on the data stored in a variable or if the returned results are
correct speeds up the developmental progress.
As soon as there is code duplication in a script or it grows too
large, it is high time to consider extracting features into separate
functions.
\end{ibox}