changeset 6510:cbae86745c5b

[project @ 2007-04-09 23:15:47 by jwe]
author jwe
date Mon, 09 Apr 2007 23:15:47 +0000
parents 84f2d0253aea
children 73ce4e14d35d
files doc/ChangeLog doc/interpreter/func.txi scripts/ChangeLog scripts/plot/__go_draw_axes__.m
diffstat 4 files changed, 213 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/doc/ChangeLog	Mon Apr 09 19:12:10 2007 +0000
+++ b/doc/ChangeLog	Mon Apr 09 23:15:47 2007 +0000
@@ -1,3 +1,8 @@
+2007-04-09  Søren Hauberg  <hauberg@gmail.com>
+
+	* interpreter/func.txi: Document varargin, varargout, and default
+	argument values.
+
 2007-04-03  Rafael Laboissiere  <rafael@debian.org>
 
 	* interpreter/basics.txi: Clarified some limitations of the #!
--- a/doc/interpreter/func.txi	Mon Apr 09 19:12:10 2007 +0000
+++ b/doc/interpreter/func.txi	Mon Apr 09 23:15:47 2007 +0000
@@ -20,6 +20,7 @@
 * Variable-length Argument Lists::  
 * Variable-length Return Lists::  
 * Returning From a Function::   
+* Default Arguments::   
 * Function Files::              
 * Script Files::                
 * Dynamically Linked Functions::  
@@ -88,7 +89,7 @@
 be empty, in which case this form is equivalent to the one shown above.
 
 To print a message along with ringing the bell, you might modify the
-@code{beep} to look like this:
+@code{wakeup} to look like this:
 
 @example
 @group
@@ -321,11 +322,114 @@
 @section Variable-length Argument Lists
 @cindex variable-length argument lists
 @cindex @code{...}
+Sometimes the number of input arguments is not known when the function
+is defined.  As an example think of a function that returns the smallest
+of all its input arguments.  For example,
+
+@example
+a = smallest (1, 2, 3);
+b = smallest (1, 2, 3, 4);
+@end example
+
+@noindent
+In this example both @code{a} and @code{b} would be 1.  One way to write
+the @code{smallest} function is
+
+@example
+function val = smallest (arg1, arg2, arg3, arg4, arg5)
+  @var{body}
+endfunction
+@end example
+
+@noindent
+and then use the value of @code{nargin} to determine which of the input
+arguments should be considered. The problem with this approach is
+that it can only handle a limited number of input arguments.
+
+Octave supports the @code{varargin} keyword for handling a variable
+number of input arguments. Using @code{varargin} the function
+looks like this
+
+@example
+function val = smallest (varargin)
+  @var{body}
+endfunction
+@end example
+
+@noindent
+In the function body the input arguments can be accessed through the
+variable @code{varargin}. This variable is a cell array containing
+all the input arguments. @xref{Cell Arrays}, for details on working
+with cell arrays. The @code{smallest} function can now be defined
+like this
+
+@example
+function val = smallest (varargin)
+  val = min ([varargin@{:@}]);
+endfunction
+@end example
+
+@noindent
+This implementation handles any number of input arguments, but it's also
+a very simple solution to the problem.
+
+A slightly more complex example of @code{varargin} is a function 
+@code{print_arguments} that prints all input arguments.  Such a function
+can be defined like this
+
+@example
+function print_arguments (varargin)
+  for i = 1:length (varargin)
+    printf ("Input argument %d: ", i);
+    disp (varargin@{i@});
+  endfor
+endfunction
+@end example
+
+@noindent
+This function produces output like this
+
+@example
+@group
+print_arguments (1, "two", 3);
+     @print{} Input argument 1:  1
+     @print{} Input argument 2: two
+     @print{} Input argument 3:  3
+@end group
+@end example
 
 @node Variable-length Return Lists
 @section Variable-length Return Lists
 @cindex variable-length return lists
-@cindex @code{...}
+It is possible to return a variable number of output arguments from a
+function using a syntax that's similar to the one used with the
+@code{varargin} keyword.  To let a function return a variable number of
+output arguments the @code{varargout} keyword is used.  As with
+@code{varargin} @code{varargout} is a cell array that will contain the
+requested output arguments.
+
+As an example the following function sets the first output argument to
+1, the second to 2, and so on.
+
+@example
+function varargout = one_to_n ()
+  for i = 1:nargout
+    varargout@{i@} = i;
+  endfor
+endfunction
+@end example
+
+@noindent
+When called this function returns values like this
+
+@example
+@group
+[a, b, c] = one_to_n ()
+     @result{} a =  1
+     @result{} b =  2
+     @result{} c =  3
+@end group
+@end example
 
 @node Returning From a Function
 @section Returning From a Function
@@ -377,6 +481,61 @@
 
 @DOCSTRING(return_last_computed_value)
 
+@node Default Arguments
+@section Default Arguments
+@cindex default arguments
+
+Since Octave supports variable number of input arguments, it is very useful
+to assign default values to some input arguments. When an input argument
+is declared in the argument list it is possible to assign a default
+value to the argument like this
+
+@example
+function @var{name} (@var{arg1} = @var{val1}, @dots{})
+  @var{body}
+endfunction
+@end example
+
+@noindent
+If no value is assigned to @var{arg1} by the user, it will have the
+value @var{val1}.
+
+As an example, the following function implements a variant of the classic
+``Hello, World'' program.
+@example
+function hello (who = "World")
+  printf ("Hello, %s!\n", who);
+endfunction
+@end example
+
+@noindent
+When called without an input argument the function prints the following
+@example
+@group
+hello ();
+     @print{} Hello, World!
+@end group
+@end example
+
+@noindent
+and when it's called with an input argument it prints the following
+@example
+@group
+hello ("Beautiful World of Free Software");
+     @print{} Hello, Beautiful World of Free Software!
+@end group
+@end example
+
+Sometimes it is useful to explicitly tell Octave to use the default value
+of an input argument.  This can be done writing a @samp{:} as the value
+of the input argument when calling the function.
+@example
+@group
+hello (:);
+     @print{} Hello, World!
+@end group
+@end example
+
 @node Function Files
 @section Function Files
 @cindex function file
@@ -581,8 +740,6 @@
 
 Here is the complete text of @file{oregonator.cc}:
 
-just
-
 @example
 @group
 #include <octave/oct.h>
--- a/scripts/ChangeLog	Mon Apr 09 19:12:10 2007 +0000
+++ b/scripts/ChangeLog	Mon Apr 09 23:15:47 2007 +0000
@@ -1,3 +1,8 @@
+2007-04-09  John W. Eaton  <jwe@octave.org>
+
+	* plot/__go_draw_axes__.m (__gnuplot_write_data__): New function.
+	(__go_draw_axes__): Use it to write data to plot stream.
+
 2007-04-09  Daniel J Sebald  <daniel.sebald@ieee.org>
 
 	* plot/stem.m: Fix typos in doc string.  Fix typo in call to
--- a/scripts/plot/__go_draw_axes__.m	Mon Apr 09 19:12:10 2007 +0000
+++ b/scripts/plot/__go_draw_axes__.m	Mon Apr 09 23:15:47 2007 +0000
@@ -663,23 +663,7 @@
 	if (is_image_data(i))
 	  fwrite (plot_stream, data{i}, "float32");
 	else
-	  if (nd == 2)
-	    fprintf (plot_stream,
-		     strcat (repmat ("%g ", 1, rows (data{i})), "\n"),
-		     data{i});
-	  else
-	    if (parametric(i))
-	      fprintf (plot_stream, "%g %g %g\n", data{i});
-	    else
-	      tmp = data{i};
-	      nc = columns (tmp);
-	      for j = 1:3:nc
-		fprintf (plot_stream, "%g %g %g\n", tmp(:,j:j+2)');
-		fputs (plot_stream, "\n");
-	      endfor
-	    endif
-	  endif
-	  fputs (plot_stream, "e\n");
+	  __gnuplot_write_data__ (plot_stream, data{i}, nd, parametric(i));
 	endif
       endfor
     else
@@ -896,3 +880,44 @@
   fputs (plot_stream, ";\n");
 
 endfunction
+
+function __gnuplot_write_data__ (plot_stream, data, nd, parametric)
+  
+  ## DATA is already transposed.
+
+  ## FIXME -- this may need to be converted to C++ for speed.
+
+  if (nd == 2)
+    nan_elts = find (sum (isnan (data)));
+    fmt = strcat (repmat ("%g ", 1, rows (data)), "\n");
+    if (isempty (nan_elts))
+      fprintf (plot_stream, fmt, data);
+    else
+      n = columns (data);
+      have_nans = true;
+      num_nan_elts = numel (nan_elts);
+      k = 1;
+      for i = 1:n
+	if (have_nans && i == nan_elts(k))
+	  fputs (plot_stream, "\n");
+	  have_nans = ++k <= num_nan_elts;
+	else
+	  fprintf (plot_stream, fmt, data(:,i));
+	endif
+      endfor
+    endif
+  else
+    ## FIXME -- handle NaNs here too?
+    if (parametric)
+      fprintf (plot_stream, "%g %g %g\n", data);
+    else
+      nc = columns (data);
+      for j = 1:3:nc
+	fprintf (plot_stream, "%g %g %g\n", data(:,j:j+2)');
+	fputs (plot_stream, "\n");
+      endfor
+    endif
+  endif
+  fputs (plot_stream, "e\n");
+
+endfunction