1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1">
<META NAME="VPSiteProject" CONTENT="file:///E|/euler/docs/Euler.vpp">
<META NAME="GENERATOR" Content="Visual Page 2.0 for Windows">
<TITLE>Programming Euler</TITLE>
<BASE target="_self">
<LINK REL="stylesheet" TYPE="text/css" HREF="euler.css">
</HEAD>
<BODY>
<H1 ALIGN="CENTER">Programming EULER</H1>
<P>Another long section explaining
<UL>
<LI><A HREF="#EULER%20functions">what EULER functions and function parameters are</A>,
<LI><A HREF="#Global%20Variables">how to use global variables in functions</A>,
<LI><A HREF="#Parameter%20by%20Value%20or%20Reference%3F">that parameters are passed by reference</A>,
<LI><A HREF="#Variable%20Parameter%20Number">variable parameter numbers</A>,
<LI><A HREF="#Default%20Values%20for%20Parameters">default parameter values</A>,
<LI><A HREF="#Returning%20Multiple%20Values">multiple return values</A>,
<LI><A HREF="#Function%20Comments">how to document your functions</A>,
<LI><A HREF="#Program%20flow">the control statements of the EULER language (if, for etc.)</A>,
<LI><A HREF="#Debugging%20EULER%20programs">how to debug</A>,
<LI><A HREF="#Passing%20functions%20as%20parameters">how to pass a function as a parameter to another function</A>,
<LI><A HREF="#User%20interface">how to interact with the user</A>.
<LI><A HREF="#Hints">some programming hints</A>.
</UL>
<H2 ALIGN="CENTER"><A NAME="EULER functions"></A>EULER functions</H2>
<P>EULER would not be as powerful as it is, if there wasn't the possibility to extend it with user defined functions.
A function can be entered from the keyboard or better from a file. Since there may be errors in a function, it
is best to call an editor, edit the function in a file and then load that file.</P>
<P>Loading a file is done with</P>
<PRE> >load "filename"
</PRE>
<P>A function is declared by the following commands</P>
<PRE> >function name (parameter,...,parameter)
>...
>endfunction
</PRE>
<P>It can have several parameters or none. If the function is entered from the keyboard, the prompt changes to
"$". "endfunction" finishes the function definition. An example</P>
<PRE> >function cosh (x)
$ return (exp(x)+exp(-x))/2
$endfunction
</PRE>
<P>Every function must have a return statement, which ends the execution of the function and defines the value
it returns. A function can be used in any expression, just as the built-in functions. If a function is not used
in an assignment and with surpressed output (followed by ";"), it is used like a procedure and its result
is evidently lost. However, the function may have had some side effect.</P>
<P>A function can call itself recursively. In this case, you have to take care that the recursion stops. If a function
overrides an internal function, you can call the internal function with an underscore _ before its name. Thus a
function is able to call the internal function, even if it has the same name. This is useful to give enhanced flexibility
to built-in functions.
<H2 ALIGN="CENTER"><A NAME="Global Variables"></A>Global Variables</H2>
<P>Inside a function one cannot access global variables or variables of the function which called the function.
To use global variables use the command</P>
<PRE> >global variablename
</PRE>
<P>in the function body. Of course, one can use other functions in expressions inside a function, one can even
use the function inside itself recursively. All variables defined inside a function are local to that function
and undefined after the return from the function. There is no way to define global variables or change the type
or size of global variables from within a function, even if one defines these variables in a "global"
statement.</P>
<P>
<PRE> >useglobal
</PRE>
<P>lets you access all global variables from inside the function. This is only valid for the function containing
the useglobal command.
<H2 ALIGN="CENTER"><A NAME="Parameter by Value or Reference?"></A>Parameter by Value or Reference?</H2>
<P>Variables are passed as references.</P>
<P>That means that a change of a parameter results in the change of the variable, which was passed as the parameter.
For example</P>
<PRE> >function test(x)
$ x=3;
$ return x
$endfunction
>a=5;
>test(a);
>a
</PRE>
<P>prints the value 3. There is an exeption to this. A submatrix is passed by value. Thus</P>
<PRE> >a=[1,2,3];
>test(a(1));
>a(1)
</PRE>
<P>prints the value 1.
<H2 ALIGN="CENTER"><A NAME="Variable Parameter Number"></A>Variable Parameter Number</H2>
<P>A function can have a variable number of parameters. The number of parameters passed to a function can be determined
with the built-in function "argn()". If the parameters are not named in the function definition, they
are given the names arg1, arg2 and so on.</P>
<P>You can access the parameters from the n-th parameter on with args(n). This functions returns multiple values
(argn,...) and these values may be passed to another function as several parameters. pargs() will return all parameters
from the first non-named parameter. These additional parameters may be passed to a function. If the parameter list
in the function call contains a semicolon ";", args() will return all parameters after the semicolon.
<H2 ALIGN="CENTER"><A NAME="Default Values for Parameters"></A>Default Values for Parameters</H2>
<P>Parameters can have default values. The syntax is parameter=value in the parameter definition; e.g.,</P>
<PRE> >function f(x=3,y,z=1:10)
</PRE>
<P>assigns the default value 3 to x and the vector 1 to 10 to z, if the function is called in the form</P>
<PRE> >f(,4,)
</PRE>
<P>If the function is called</P>
<PRE> >f(1,4)
</PRE>
<P>x has the value 1, y the value 4, and z the value 1:10.</P>
<P>The function can even be given a named parameter. Consider the function</P>
<PRE> >function f(x,y,z=4,w=4,t=5)
</PRE>
<P>Then</P>
<PRE> >f(1,2,t=7)
</PRE>
<P>calls the function as if</P>
<PRE> >f(1,2,4,4,7)
</PRE>
<P>was entered. Actually the name needs not be a parameter name. Thus</P>
<PRE> >f(1,2,s=7)
</PRE>
<P>defines a local variable s with value 7.
<H2 ALIGN="CENTER"><A NAME="Returning Multiple Values"></A>Returning Multiple Values</H2>
<P>A function can return multiple values. This is done with the return statement</P>
<PRE> > return {x,y,...}
</PRE>
<P>You can assign all the return values of a function to variables, using</P>
<PRE> >{a,b,...}=function(...);
</PRE>
<P>If the result of such a function is assigned to a number of variables smaller than the number of returned values,
only the first values are used. If is is assigned to a larger number of variables, the last value is used more
than once. Some built-in functions return multiple values.
<H2 ALIGN="CENTER"><A NAME="Function Comments"></A>Function Comments</H2>
<P>Comments can be included, starting with ##. Comments are ignored by Euler and do not appear, when you type the
function body with</P>
<PRE> >type functionname
</PRE>
<P>If the lines immediately after the function header start with ##, then those lines are considered to be help
text. The help text can be displayed with</P>
<PRE> >help functionname
</PRE>
<P>This feature is a good way to remember the parameters of the function. Also</P>
<PRE> >list
</PRE>
<P>can be used to display a list of the names of the user defined functions.</P>
<P>A function or several functions can be removed with</P>
<PRE> >forget name,...
</PRE>
<P>By the way, a variable can be removed with</P>
<PRE> >clear name,...
</PRE>
<H2 ALIGN="CENTER"><A NAME="Program flow"></A>Program flow</H2>
<P>Like in any other programming language, EULER has commands for changing the execution flow. These commands can
only be used inside user defined functions.</P>
<P>First there is the "if" command.</P>
<PRE> >if expression; ...;
>else; ....;
>endif;
</PRE>
<P>The expression is any EULER numerical expression. If it is a non-zero scalar ora a matrix with <EM>all</EM>
entries different from zero, then the part from the ";" to the "else;" is evaluated. Else the
part from "else;" to "endif" is evaluated. Of course "..." may spread over several
lines. To work correctly, keywords like "if", "else", "endif" and others should be
the first nonblank characters in a line, or should be preceded by "," or ";" (plus blanks or
TABs). The "else" may be omitted. In this case the evaluation skips behind the "endif", if
the matrix contains zero elements (resp. the number is zero).</P>
<P>You may also include one or several elseif commands</P>
<PRE> >if expression; ...;
>elseif expression; ...;
>else; ....;
>endif;
</PRE>
<P>This is the same as an if command inside the else part. However, you do not have to type several endifs.</P>
<P>There is the function "any(A)", which yields 1, if there is any nonzero element in A, 0 otherwise.
The function is useful in connection with the if statement.</P>
<P>Next, there are several loops.</P>
<PRE> >repeat; ...; end;
>loop a to b; ...; end;
>for i=a to b step c; ...; end;
</PRE>
<P>All loops can be aborted by the break command (usually inside an "if"), especially the seemingly infinite
"repeat". "loop" loops are fast long integer loops. The looping index can be accessed with
the function "index()" or with "#". In a "for" loop the looping index is the variable
left of the "=". The step size can be omitted. Then it is assumed to be 1. As an example, the following
loops count from 1 to 10</P>
<PRE> > i=1;
> repeat;
> i, i=i+1;
> if i>10; break; endif;
> end;
</PRE>
<P>and</P>
<PRE> > loop 1 to 10; #, end;
</PRE>
<P>and</P>
<PRE> > for i=1 to 10; i, end;
</PRE>
<H2 ALIGN="CENTER"><A NAME="Debugging EULER programs"></A>Debugging EULER programs</H2>
<P>The command</P>
<PRE> >trace on
</PRE>
<P>sets tracing of all functions on. Then any new line in a user defined function will be printed with the function
name before it is executed. The uses has to press a key, before execution continues
<UL>
<LI>Control-F1 debugs every function.
<LI>Control-F2 debugs no function called in the current line.
<LI>Control-F3 will stop debugging until return of the current function.
<LI>Control-F4 will prompt for an expression and evaluate it.
<LI>Control-F9 aborts execution of the program.
<LI>Control-F10 ends tracing for this command.
</UL>
<P>Any other key will display the available keys. Note that the help key is mapped to the insert key on a PC.</P>
<PRE> >trace off
</PRE>
<P>switches tracing off.</P>
<P>Note, that with F4 you can evaluate any expression, even if it contains local variables or subroutine calls.
Tracing is switched off during evaluation of the expression.</P>
<P>A single function can be traced with</P>
<PRE> >trace function
</PRE>
<P>or</P>
<PRE> >trace "function"
</PRE>
<P>Execution will stop only in this function. The same command switches the trace bit of this function off.</P>
<PRE> >trace alloff
</PRE>
<P>switches tracing for all functions off.
<H2 ALIGN="CENTER"><A NAME="Programming style"></A>Programming style</H2>
<P>All internal EULER functions can handle vector or matrix input. And so should user defined functions. To achieve
this, sometimes nothing special needs to be done. E.g., the function</P>
<PRE> >function kap (r,i,n)
> p=1+i/100;
> return p*r*(p^n-1)/(p-1)
>endfunction
</PRE>
<P>is automatically capable to handle matrix intput. Thus</P>
<PRE> >kap(1000,5:0.1:10,10)
</PRE>
<P>will produce a vector of values. However, if the function uses a more complicated algorithm, one needs to take
extra care. E.g.,</P>
<PRE> >function lambda1 (a,b)
> return max(abs(polysolve([1,a,b,1])));
>endfunction
>function lambda (a,b)
> return map("lambda1",a,b);
>endfunction
</PRE>
<P>shows the fastest way to achieve the aim.</P>
<P>Forthermore, as a matter of good style, one should use the help lines extensively. All parameters of the function
and its result should be explained. This is a good way to remember what the function really does.
<H2 ALIGN="CENTER"><A NAME="Passing functions as parameters"></A>Passing functions as parameters</H2>
<P>It is possible to pass functions to a function. E.g., the function "bisect" in UTIL finds the zero
of a function using bisection. This function works in the following way</P>
<PRE> >function f(x)
> return x*x-2
>endfunction
>bisect("f",1,2)
</PRE>
<P>The result will be equal to sqrt(2). If "f" needs extra parameters, those can also be passed to "bisect"</P>
<PRE> >function f(x,a)
> return x*x-a
>endfunction
>bisect("f",0,a,a)
</PRE>
<P>will result is equal to sqrt(a) (for a>=0). The search interval is set to [0,a].</P>
<P>The way to write a function like "bisect" is to use the "args" function.</P>
<PRE> >function bisect (function,a,b)
>...
> y=function(x,args(4));
>...
>endfunction
</PRE>
<P>Then "function" will be called with the parameter "x" and all parameters from the 4-th on
(if any) which have been passed to "bisect". Of course, "function" should be assigned a string,
containing the name of the function which we want the zero of.</P>
<P>The function bisect does also accept an expression in the variable "x". The programmer can use</P>
<PRE> >evaluate(expression)</PRE>
<P>to evaluate an expression. The variable "x" should be defined either globally (then useglobal must
be used), or in the function bisect itself. To determine, if a string is a function or an expression, the function
isfunction("f") may be used.</P>
<P>Another way to achieve this result is the use of args() without parameter. This will return all parameters from
the first additional parameter on. If the user calls bisect like this</P>
<PRE> >bisect ("f",a,b;4,5)
</PRE>
<P>All parameter after the ";" will be passed to function, when it is called</P>
<PRE> >y=function(x,args());
</PRE>
<H2 ALIGN="CENTER"><A NAME="User interface"></A>User interface</H2>
<P>Clearly, EULER is designed to run interactively. The user loads a file containing the functions he needs. The
file may inform the user of its content by simply printing some messages with commands like</P>
<PRE> >"The content of this file is:",
>...
</PRE>
<P>Alternatively, the file could contain a comment section.</P>
<PRE>comment
Any comment!
Even in several lines.
endcomment
</PRE>
<P>Then the user can use the help facility to retrieve further information on the functions, its parameters and
so on. He (or she) then calls the particular function with the parameters he desires.</P>
<P>However, it is also possible to run a file as a standalone program. If you start EULER from a shell simply put
the file into the command line.</P>
<P>If you wish a standalone application, the user will have to enter data. You can prompt him with</P>
<PRE> >data=input("prompt");
</PRE>
<P>The prompt</P>
<PRE> prompt? >
</PRE>
<P>will appear and the user may enter any valid EULER expression, even if it uses variables. Errors are catched
and force the user to reenter the input. If you wish the user to enter a string, use</P>
<PRE> >string=lineinput("prompt");
</PRE>
<P>The string may then be evaluated with</P>
<PRE> >data=interpret(string);
</PRE>
<P>and if it does not consist of a valid EULER expression the result is the string "error". Also</P>
<PRE> >errorlevel(string)
</PRE>
<P>returns a nonzero number, if there is an error in the string.</P>
<P>Output is printed to screen. All expressions and assignments produce output unless followed by ";".
If formated output is wanted, use</P>
<PRE> >printf("formatstring",realdata)
</PRE>
<P>The format string obeys the C syntax; e.g., "%15.10f" prints the data on 15 places with 10 digits
after decimal dot, and "%20.10e" produces the exponential format. You can concatenate strings with |
to longer output in a single line.</P>
<P>Output is surpressed globally with</P>
<PRE> >output off;
</PRE>
<P>and</P>
<PRE> >output on;
</PRE>
<P>turns the output on again. This is useful if a dump file is defined by</P>
<PRE> >dump "filename";
</PRE>
<P>Then all output is echoed into the dump file. The command</P>
<PRE> >dump;
</PRE>
<P>turns the dump off. Note that the dump is always appended to the file. Furthermore, that file may not be edited
while dump is on! The utility function</P>
<PRE> >varwrite(x,"x")
</PRE>
<P>is defined, which writes x in a format readable by EULER on input. If you omit the name "x", the name
of x is used automatically. This is done with the help of the function</P>
<PRE> >name(x)
</PRE>
<P>which is a string containing the name of x.</P>
<P>
<PRE> >cls;
</PRE>
<P>clears the screen.</P>
<PRE> >clg;
</PRE>
<P>clears the graphics. Also to show graphics to the user, use</P>
<PRE> >shg;
</PRE>
<P>Subsequent output will switch back to the text screen.</P>
<P>Finally, an error can be issued with the function</P>
<PRE> >error("error text")</PRE>
<H2 ALIGN="CENTER"><A NAME="Hints"></A>Hints</H2>
<P>One can make all sorts of mistakes in EULER. This section tries to warn you of the more common ones, most of
which the author has some experience with.</P>
<P>As already mentioned, you should not assign to the parameter of a function. This will generally produce strange
errors, which are difficult to debug.</P>
<P>The next mistake is to produce matrices with 0 rows or columns. EULER can not do any computation with these
matrices. Make sure that every index you use is in range. And use special handling, if there is nothing to do.
However, you may generate such matrices for the special purpose of appending vectors to it.</P>
<P>Another subtlety concerns the use of multiple return values. The following simply does not work</P>
<PRE> >x=random(1,10); sin(sort(x))
</PRE>
<P>The reason is that sort returns not only the sorted array but also the indices of the sorted elements. This
works as if sin was passed two parameters and EULER will not recognize that use of sin. To work around this either
assign the sorted array to a variable or put extra brackets around it</P>
<PRE> >x=random(1,10); sin((sort(x)))
</PRE>
<P>Also a return statement like</P>
<PRE> >return {sort(x),y}
</PRE>
<P>really returns 3 (or more) values! Use</P>
<PRE> >return {(sort(x)),y}
</PRE>
<P>One further misfortune results from the use of strings as functions, like in</P>
<PRE> >function test(f,x)
> return f(x*x)
>endfunction
>test("sin",4)
</PRE>
<P>This works well as long as there is no function by the name of "f". If there is, this function is
called rather than the sine function. The only way to avoid this is to use really strange names for function parameters.
I prefer "test(ffunction,x)" and used it throughout UTIL.</P>
<P>Finally, I like to stress that the user defined functions are serached before the biult-in functions. If you
want to call the built-in function explicitely, you can prepend it with an underscore "_".
</BODY>
</HTML>
|