diff doc/interpreter/stmt.txi @ 3294:bfe1573bd2ae

[project @ 1999-10-19 10:06:07 by jwe]
author jwe
date Tue, 19 Oct 1999 10:08:42 +0000
parents
children abdd5ed1bb4e
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/interpreter/stmt.txi	Tue Oct 19 10:08:42 1999 +0000
@@ -0,0 +1,802 @@
+@c Copyright (C) 1996, 1997 John W. Eaton
+@c This is part of the Octave manual.
+@c For copying conditions, see the file gpl.texi.
+
+@node Statements, Functions and Scripts, Evaluation, Top
+@chapter Statements
+@cindex statements
+
+Statements may be a simple constant expression or a complicated list of
+nested loops and conditional statements.
+
+@dfn{Control statements} such as @code{if}, @code{while}, and so on
+control the flow of execution in Octave programs.  All the control
+statements start with special keywords such as @code{if} and
+@code{while}, to distinguish them from simple expressions.
+Many control statements contain other statements; for example, the
+@code{if} statement contains another statement which may or may not be
+executed.
+
+@cindex @code{end} statement
+Each control statement has a corresponding @dfn{end} statement that
+marks the end of the end of the control statement.  For example, the
+keyword @code{endif} marks the end of an @code{if} statement, and
+@code{endwhile} marks the end of a @code{while} statement.  You can use
+the keyword @code{end} anywhere a more specific end keyword is expected,
+but using the more specific keywords is preferred because if you use
+them, Octave is able to provide better diagnostics for mismatched or
+missing end tokens.
+
+The list of statements contained between keywords like @code{if} or
+@code{while} and the corresponding end statement is called the
+@dfn{body} of a control statement.
+
+@menu
+* The if Statement::            
+* The switch Statement::        
+* The while Statement::         
+* The for Statement::           
+* The break Statement::         
+* The continue Statement::      
+* The unwind_protect Statement::  
+* The try Statement::           
+* Continuation Lines::          
+@end menu
+
+@node The if Statement, The switch Statement, Statements, Statements
+@section The @code{if} Statement
+@cindex @code{if} statement
+@cindex @code{else} statement
+@cindex @code{elseif} statement
+@cindex @code{endif} statement
+
+The @code{if} statement is Octave's decision-making statement.  There
+are three basic forms of an @code{if} statement.  In its simplest form,
+it looks like this:
+
+@example
+@group
+if (@var{condition})
+  @var{then-body}
+endif
+@end group
+@end example
+
+@noindent
+@var{condition} is an expression that controls what the rest of the
+statement will do.  The @var{then-body} is executed only if
+@var{condition} is true.
+
+The condition in an @code{if} statement is considered true if its value
+is non-zero, and false if its value is zero.  If the value of the
+conditional expression in an @code{if} statement is a vector or a
+matrix, it is considered true only if @emph{all} of the elements are
+non-zero.
+
+The second form of an if statement looks like this:
+
+@example
+@group
+if (@var{condition})
+  @var{then-body}
+else
+  @var{else-body}
+endif
+@end group
+@end example
+
+@noindent
+If @var{condition} is true, @var{then-body} is executed; otherwise,
+@var{else-body} is executed.
+
+Here is an example:
+
+@example
+@group
+if (rem (x, 2) == 0)
+  printf ("x is even\n");
+else
+  printf ("x is odd\n");
+endif
+@end group
+@end example
+
+In this example, if the expression @code{rem (x, 2) == 0} is true (that
+is, the value of @code{x} is divisible by 2), then the first
+@code{printf} statement is evaluated, otherwise the second @code{printf}
+statement is evaluated.
+
+The third and most general form of the @code{if} statement allows
+multiple decisions to be combined in a single statement.  It looks like
+this:
+
+@example
+@group
+if (@var{condition})
+  @var{then-body}
+elseif (@var{condition})
+  @var{elseif-body}
+else
+  @var{else-body}
+endif
+@end group
+@end example
+
+@noindent
+Any number of @code{elseif} clauses may appear.  Each condition is
+tested in turn, and if one is found to be true, its corresponding
+@var{body} is executed.  If none of the conditions are true and the
+@code{else} clause is present, its body is executed.  Only one
+@code{else} clause may appear, and it must be the last part of the
+statement.
+
+In the following example, if the first condition is true (that is, the
+value of @code{x} is divisible by 2), then the first @code{printf}
+statement is executed.  If it is false, then the second condition is
+tested, and if it is true (that is, the value of @code{x} is divisible
+by 3), then the second @code{printf} statement is executed.  Otherwise,
+the third @code{printf} statement is performed.
+
+@example
+@group
+if (rem (x, 2) == 0)
+  printf ("x is even\n");
+elseif (rem (x, 3) == 0)
+  printf ("x is odd and divisible by 3\n");
+else
+  printf ("x is odd\n");
+endif
+@end group
+@end example
+
+Note that the @code{elseif} keyword must not be spelled @code{else if},
+as is allowed in Fortran.  If it is, the space between the @code{else}
+and @code{if} will tell Octave to treat this as a new @code{if}
+statement within another @code{if} statement's @code{else} clause.  For
+example, if you write
+
+@example
+@group
+if (@var{c1})
+  @var{body-1}
+else if (@var{c2})
+  @var{body-2}
+endif
+@end group
+@end example
+
+@noindent
+Octave will expect additional input to complete the first @code{if}
+statement.  If you are using Octave interactively, it will continue to
+prompt you for additional input.  If Octave is reading this input from a
+file, it may complain about missing or mismatched @code{end} statements,
+or, if you have not used the more specific @code{end} statements
+(@code{endif}, @code{endfor}, etc.), it may simply produce incorrect
+results, without producing any warning messages.
+
+It is much easier to see the error if we rewrite the statements above
+like this,
+
+@example
+@group
+if (@var{c1})
+  @var{body-1}
+else
+  if (@var{c2})
+    @var{body-2}
+  endif
+@end group
+@end example
+
+@noindent
+using the indentation to show how Octave groups the statements.
+@xref{Functions and Scripts}.
+
+@defvr {Built-in Variable} warn_assign_as_truth_value
+If the value of @code{warn_assign_as_truth_value} is nonzero, a
+warning is issued for statements like
+
+@example
+if (s = t)
+  ...
+@end example
+
+@noindent
+since such statements are not common, and it is likely that the intent
+was to write
+
+@example
+if (s == t)
+  ...
+@end example
+
+@noindent
+instead.
+
+There are times when it is useful to write code that contains
+assignments within the condition of a @code{while} or @code{if}
+statement.  For example, statements like
+
+@example
+while (c = getc())
+  ...
+@end example
+
+@noindent
+are common in C programming.
+
+It is possible to avoid all warnings about such statements by setting
+@code{warn_assign_as_truth_value} to 0, but that may also
+let real errors like
+
+@example
+if (x = 1)  # intended to test (x == 1)!
+  ...
+@end example
+
+@noindent
+slip by.
+
+In such cases, it is possible suppress errors for specific statements by
+writing them with an extra set of parentheses.  For example, writing the
+previous example as
+
+@example
+while ((c = getc()))
+  ...
+@end example
+
+@noindent
+will prevent the warning from being printed for this statement, while
+allowing Octave to warn about other assignments used in conditional
+contexts.
+
+The default value of @code{warn_assign_as_truth_value} is 1.
+@end defvr
+
+@node The switch Statement, The while Statement, The if Statement, Statements
+@section The @code{switch} Statement
+@cindex @code{switch} statement
+@cindex @code{case} statement
+@cindex @code{otherwise} statement
+@cindex @code{endswitch} statement
+
+The @code{switch} statement was introduced in Octave 2.0.5.  It should
+be considered experimental, and details of the implementation may change
+slightly in future versions of Octave.  If you have comments or would
+like to share your experiences in trying to use this new command in real
+programs, please send them to
+@email{octave-maintainers@@bevo.che.wisc.edu}.  (But if you think you've
+found a bug, please report it to @email{bug-octave@@bevo.che.wisc.edu}.
+
+The general form of the @code{switch} statement is
+
+@example
+@group
+switch @var{expression}
+  case @var{label}
+    @var{command_list}
+  case @var{label}
+    @var{command_list}
+  @dots{}
+
+  otherwise
+    @var{command_list}
+endswitch
+@end group
+@end example
+
+@itemize @bullet
+@item
+The identifiers @code{switch}, @code{case}, @code{otherwise}, and
+@code{endswitch} are now keywords. 
+
+@item
+The @var{label} may be any expression.
+
+@item
+Duplicate @var{label} values are not detected.  The @var{command_list}
+corresponding to the first match will be executed.
+
+@item
+You must have at least one @code{case @var{label} @var{command_list}}
+clause.
+
+@item
+The @code{otherwise @var{command_list}} clause is optional.
+
+@item
+As with all other specific @code{end} keywords, @code{endswitch} may be
+replaced by @code{end}, but you can get better diagnostics if you use
+the specific forms.
+
+@item
+Cases are exclusive, so they don't `fall through' as do the cases
+in the switch statement of the C language.
+
+@item
+The @var{command_list} elements are not optional.  Making the list
+optional would have meant requiring a separator between the label and
+the command list.  Otherwise, things like
+
+@example
+@group
+switch (foo)
+  case (1) -2
+  @dots{}
+@end group
+@end example
+
+@noindent
+would produce surprising results, as would
+
+@example
+@group
+switch (foo)
+  case (1)
+  case (2)
+    doit ();
+  @dots{}
+@end group
+@end example
+
+@noindent
+particularly for C programmers.
+
+@item
+The implementation is simple-minded and currently offers no real
+performance improvement over an equivalent @code{if} block, even if all
+the labels are integer constants.  Perhaps a future variation on this
+could detect all constant integer labels and improve performance by
+using a jump table.
+@end itemize
+
+@defvr {Built-in Variable} warn_variable_switch_label
+If the value of this variable is nonzero, Octave will print a warning if
+a switch label is not a constant or constant expression
+@end defvr
+
+@node The while Statement, The for Statement, The switch Statement, Statements
+@section The @code{while} Statement
+@cindex @code{while} statement
+@cindex @code{endwhile} statement
+@cindex loop
+@cindex body of a loop
+
+In programming, a @dfn{loop} means a part of a program that is (or at least can
+be) executed two or more times in succession.
+
+The @code{while} statement is the simplest looping statement in Octave.
+It repeatedly executes a statement as long as a condition is true.  As
+with the condition in an @code{if} statement, the condition in a
+@code{while} statement is considered true if its value is non-zero, and
+false if its value is zero.  If the value of the conditional expression
+in a @code{while} statement is a vector or a matrix, it is considered
+true only if @emph{all} of the elements are non-zero.
+
+Octave's @code{while} statement looks like this:
+
+@example
+@group
+while (@var{condition})
+  @var{body}
+endwhile
+@end group
+@end example
+
+@noindent
+Here @var{body} is a statement or list of statements that we call the
+@dfn{body} of the loop, and @var{condition} is an expression that
+controls how long the loop keeps running.
+
+The first thing the @code{while} statement does is test @var{condition}.
+If @var{condition} is true, it executes the statement @var{body}.  After
+@var{body} has been executed, @var{condition} is tested again, and if it
+is still true, @var{body} is executed again.  This process repeats until
+@var{condition} is no longer true.  If @var{condition} is initially
+false, the body of the loop is never executed.
+
+This example creates a variable @code{fib} that contains the first ten
+elements of the Fibonacci sequence.
+
+@example
+@group
+fib = ones (1, 10);
+i = 3;
+while (i <= 10)
+  fib (i) = fib (i-1) + fib (i-2);
+  i++;
+endwhile
+@end group
+@end example
+
+@noindent
+Here the body of the loop contains two statements.
+
+The loop works like this: first, the value of @code{i} is set to 3.
+Then, the @code{while} tests whether @code{i} is less than or equal to
+10.  This is the case when @code{i} equals 3, so the value of the
+@code{i}-th element of @code{fib} is set to the sum of the previous two
+values in the sequence.  Then the @code{i++} increments the value of
+@code{i} and the loop repeats.  The loop terminates when @code{i}
+reaches 11.
+
+A newline is not required between the condition and the
+body; but using one makes the program clearer unless the body is very
+simple.
+
+@xref{The if Statement} for a description of the variable
+@code{warn_assign_as_truth_value}.
+
+@node The for Statement, The break Statement, The while Statement, Statements
+@section The @code{for} Statement
+@cindex @code{for} statement
+@cindex @code{endfor} statement
+
+The @code{for} statement makes it more convenient to count iterations of a
+loop.  The general form of the @code{for} statement looks like this:
+
+@example
+@group
+for @var{var} = @var{expression}
+  @var{body}
+endfor
+@end group
+@end example
+
+@noindent
+where @var{body} stands for any statement or list of statements,
+@var{expression} is any valid expression, and @var{var} may take several
+forms.  Usually it is a simple variable name or an indexed variable.  If
+the value of @var{expression} is a structure, @var{var} may also be a
+list.  @xref{Looping Over Structure Elements}, below.
+
+The assignment expression in the @code{for} statement works a bit
+differently than Octave's normal assignment statement.  Instead of
+assigning the complete result of the expression, it assigns each column
+of the expression to @var{var} in turn.  If @var{expression} is a range,
+a row vector, or a scalar, the value of @var{var} will be a scalar each
+time the loop body is executed.  If @var{var} is a column vector or a
+matrix, @var{var} will be a column vector each time the loop body is
+executed.
+
+The following example shows another way to create a vector containing
+the first ten elements of the Fibonacci sequence, this time using the
+@code{for} statement:
+
+@example
+@group
+fib = ones (1, 10);
+for i = 3:10
+  fib (i) = fib (i-1) + fib (i-2);
+endfor
+@end group
+@end example
+
+@noindent
+This code works by first evaluating the expression @code{3:10}, to
+produce a range of values from 3 to 10 inclusive.  Then the variable
+@code{i} is assigned the first element of the range and the body of the
+loop is executed once.  When the end of the loop body is reached, the
+next value in the range is assigned to the variable @code{i}, and the
+loop body is executed again.  This process continues until there are no
+more elements to assign.
+
+Although it is possible to rewrite all @code{for} loops as @code{while}
+loops, the Octave language has both statements because often a
+@code{for} loop is both less work to type and more natural to think of.
+Counting the number of iterations is very common in loops and it can be
+easier to think of this counting as part of looping rather than as
+something to do inside the loop.
+
+@menu
+* Looping Over Structure Elements::  
+@end menu
+
+@node Looping Over Structure Elements,  , The for Statement, The for Statement
+@subsection Looping Over Structure Elements
+@cindex structure elements, looping over
+@cindex looping over structure elements
+
+A special form of the @code{for} statement allows you to loop over all
+the elements of a structure:
+
+@example
+@group
+for [ @var{val}, @var{key} ] = @var{expression}
+  @var{body}
+endfor
+@end group
+@end example
+
+@noindent
+In this form of the @code{for} statement, the value of @var{expression}
+must be a structure.  If it is, @var{key} and @var{val} are set to the
+name of the element and the corresponding value in turn, until there are
+no more elements. For example,
+
+@example
+@group
+x.a = 1
+x.b = [1, 2; 3, 4]
+x.c = "string"
+for [val, key] = x
+  key
+  val
+endfor
+
+     @print{} key = a
+     @print{} val = 1
+     @print{} key = b
+     @print{} val =
+     @print{} 
+     @print{}   1  2
+     @print{}   3  4
+     @print{} 
+     @print{} key = c
+     @print{} val = string
+@end group
+@end example
+
+The elements are not accessed in any particular order.  If you need to
+cycle through the list in a particular way, you will have to use the
+function @code{struct_elements} and sort the list yourself.
+
+The @var{key} variable may also be omitted.  If it is, the brackets are
+also optional.  This is useful for cycling through the values of all the
+structure elements when the names of the elements do not need to be
+known.
+
+@node The break Statement, The continue Statement, The for Statement, Statements
+@section The @code{break} Statement
+@cindex @code{break} statement
+
+The @code{break} statement jumps out of the innermost @code{for} or
+@code{while} loop that encloses it.  The @code{break} statement may only
+be used within the body of a loop.  The following example finds the
+smallest divisor of a given integer, and also identifies prime numbers:
+
+@example
+@group
+num = 103;
+div = 2;
+while (div*div <= num)
+  if (rem (num, div) == 0)
+    break;
+  endif
+  div++;
+endwhile
+if (rem (num, div) == 0)
+  printf ("Smallest divisor of %d is %d\n", num, div)
+else
+  printf ("%d is prime\n", num);
+endif
+@end group
+@end example
+
+When the remainder is zero in the first @code{while} statement, Octave
+immediately @dfn{breaks out} of the loop.  This means that Octave
+proceeds immediately to the statement following the loop and continues
+processing.  (This is very different from the @code{exit} statement
+which stops the entire Octave program.)
+
+Here is another program equivalent to the previous one.  It illustrates
+how the @var{condition} of a @code{while} statement could just as well
+be replaced with a @code{break} inside an @code{if}:
+
+@example
+@group
+num = 103;
+div = 2;
+while (1)
+  if (rem (num, div) == 0)
+    printf ("Smallest divisor of %d is %d\n", num, div);
+    break;
+  endif
+  div++;
+  if (div*div > num)
+    printf ("%d is prime\n", num);
+    break;
+  endif
+endwhile
+@end group
+@end example
+
+@node The continue Statement, The unwind_protect Statement, The break Statement, Statements
+@section The @code{continue} Statement
+@cindex @code{continue} statement
+
+The @code{continue} statement, like @code{break}, is used only inside
+@code{for} or @code{while} loops.  It skips over the rest of the loop
+body, causing the next cycle around the loop to begin immediately.
+Contrast this with @code{break}, which jumps out of the loop altogether.
+Here is an example:
+
+@example
+@group
+# print elements of a vector of random
+# integers that are even.
+
+# first, create a row vector of 10 random
+# integers with values between 0 and 100:
+
+vec = round (rand (1, 10) * 100);
+
+# print what we're interested in:
+
+for x = vec
+  if (rem (x, 2) != 0)
+    continue;
+  endif
+  printf ("%d\n", x);
+endfor
+@end group
+@end example
+
+If one of the elements of @var{vec} is an odd number, this example skips
+the print statement for that element, and continues back to the first
+statement in the loop.
+
+This is not a practical example of the @code{continue} statement, but it
+should give you a clear understanding of how it works.  Normally, one
+would probably write the loop like this:
+
+@example
+@group
+for x = vec
+  if (rem (x, 2) == 0)
+    printf ("%d\n", x);
+  endif
+endfor
+@end group
+@end example
+
+@node The unwind_protect Statement, The try Statement, The continue Statement, Statements
+@section The @code{unwind_protect} Statement
+@cindex @code{unwind_protect} statement
+@cindex @code{unwind_protect_cleanup}
+@cindex @code{end_unwind_protect}
+
+Octave supports a limited form of exception handling modelled after the
+unwind-protect form of Lisp.  
+
+The general form of an @code{unwind_protect} block looks like this:
+
+@example
+@group
+unwind_protect
+  @var{body}
+unwind_protect_cleanup
+  @var{cleanup}
+end_unwind_protect
+@end group
+@end example
+
+@noindent
+Where @var{body} and @var{cleanup} are both optional and may contain any
+Octave expressions or commands.  The statements in @var{cleanup} are 
+guaranteed to be executed regardless of how control exits @var{body}.
+
+This is useful to protect temporary changes to global variables from
+possible errors.  For example, the following code will always restore
+the original value of the built-in variable @code{do_fortran_indexing}
+even if an error occurs while performing the indexing operation.
+
+@example
+@group
+save_do_fortran_indexing = do_fortran_indexing;
+unwind_protect
+  do_fortran_indexing = 1;
+  elt = a (idx)
+unwind_protect_cleanup
+  do_fortran_indexing = save_do_fortran_indexing;
+end_unwind_protect
+@end group
+@end example
+
+Without @code{unwind_protect}, the value of @var{do_fortran_indexing}
+would not be restored if an error occurs while performing the indexing
+operation because evaluation would stop at the point of the error and
+the statement to restore the value would not be executed.
+
+@node The try Statement, Continuation Lines, The unwind_protect Statement, Statements
+@section The @code{try} Statement
+@cindex @code{try} statement
+@cindex @code{catch}
+@cindex @code{end_try_catch}
+
+In addition to unwind_protect, Octave supports another limited form of
+exception handling.
+
+The general form of a @code{try} block looks like this:
+
+@example
+@group
+try
+  @var{body}
+catch
+  @var{cleanup}
+end_try_catch
+@end group
+@end example
+
+Where @var{body} and @var{cleanup} are both optional and may contain any
+Octave expressions or commands.  The statements in @var{cleanup} are
+only executed if an error occurs in @var{body}.
+
+No warnings or error messages are printed while @var{body} is
+executing.  If an error does occur during the execution of @var{body},
+@var{cleanup} can access the text of the message that would have been
+printed in the builtin constant @code{__error_text__}.  This is the same
+as @code{eval (@var{try}, @var{catch})} (which may now also use
+@code{__error_text__}) but it is more efficient since the commands do
+not need to be parsed each time the @var{try} and @var{catch} statements
+are evaluated.  @xref{Error Handling}, for more information about the
+@code{__error_text__} variable.
+
+Octave's @var{try} block is a very limited variation on the Lisp
+condition-case form (limited because it cannot handle different classes
+of errors separately).  Perhaps at some point Octave can have some sort
+of classification of errors and try-catch can be improved to be as
+powerful as condition-case in Lisp.
+
+@cindex continuation lines
+@cindex @code{...} continuation marker
+@cindex @code{\} continuation marker
+
+@node Continuation Lines,  , The try Statement, Statements
+@section Continuation Lines
+
+In the Octave language, most statements end with a newline character and
+you must tell Octave to ignore the newline character in order to
+continue a statement from one line to the next.  Lines that end with the
+characters @code{...} or @code{\} are joined with the following line
+before they are divided into tokens by Octave's parser.  For example,
+the lines
+
+@example
+@group
+x = long_variable_name ...
+    + longer_variable_name \
+    - 42
+@end group
+@end example
+
+@noindent
+form a single statement.  The backslash character on the second line
+above is interpreted a continuation character, @emph{not} as a division
+operator.
+
+For continuation lines that do not occur inside string constants,
+whitespace and comments may appear between the continuation marker and
+the newline character.  For example, the statement
+
+@example
+@group
+x = long_variable_name ...     # comment one
+    + longer_variable_name \   # comment two
+    - 42                       # last comment
+@end group
+@end example
+
+@noindent
+is equivalent to the one shown above.  Inside string constants, the
+continuation marker must appear at the end of the line just before the
+newline character.
+
+Input that occurs inside parentheses can be continued to the next line
+without having to use a continuation marker.  For example, it is
+possible to write statements like
+
+@example
+@group
+if (fine_dining_destination == on_a_boat
+    || fine_dining_destination == on_a_train)
+  suess (i, will, not, eat, them, sam, i, am, i,
+         will, not, eat, green, eggs, and, ham);
+endif
+@end group
+@end example
+
+@noindent
+without having to add to the clutter with continuation markers.