Default arguments

View: New views
20 Messages — Rating Filter:   Alert me  
< Prev | 1 - 2 | Next >

Default arguments

by Søren Hauberg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,
   I'd really like Octave to have some way of having default function
arguments. In C++ you can do

   void fn(int arg = 7) {}

I think R supports the same syntax. I don't think matlab has something
similar, so if Octave adds support for default it should be something
simple that won't break whatever syntax matlab decides to add in the
future that'll handle default arguments.

   So I suggest that Octave just adds some functions to make it easy to
work with default arguments, instead of changing the syntax of the
language. The C++ example above would then be written something like this

   function fn(arg)
     arg = default_value("arg", 7);
   endfunction

The function default_value should then expand (like a macro in C/C++)
into this code

     if (!exist(arg, "var")
       arg = val;
     endif

One thing that's missing from this idea, is a way to tell the function
to use the default argument. As an example, think of a function that
takes three arguments

   function fn2(arg1, arg2, arg3)
     ...
   endfunction

How does the user tell fn2 that he wants to set the value of arg1 and
arg3, but use the default value for arg2? I suggest adding a function
called "default" that returns an object of type "default". That way the
user can write

   fn2(arg1, default, arg3)

I don't know how to handle varargin, but I don't think there is much one
can do...


Søren

Re: Default arguments

by Andreas Romeyke-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi all,


Søren Hauberg wrote:
> I'd really like Octave to have some way of having default function
> arguments. In C++ you can do
>
- From maintenance point of view default arguments are a horrible
scenario. Because it hides semantics I would not agree with you that
Octave (or any language, too) should support this.

Bye Andreas

- --
Software Developer / Dipl. Inform. (FH)
Max Planck Institute for Human Cognitive and Brain Sciences
Department of Psychology
Stephanstr. 1a, 04103 Leipzig, Germany

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)

iD8DBQFFgRxMGBhgJGthyeERAkyDAKCkGg7hX/gh+2V/DLUOOQ/XY1rglgCfWMH2
gSsCXa6XXAw6YEFMOaJaoW8=
=/rq5
-----END PGP SIGNATURE-----


Re: Default arguments

by John W. Eaton :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 14-Dec-2006, Andreas Romeyke wrote:

| - From maintenance point of view default arguments are a horrible
| scenario. Because it hides semantics I would not agree with you that
| Octave (or any language, too) should support this.

We already have default values for arguments for many functions, so
it's a little late to say that the language should not support them.
Currently, you have to write something like

  function foo (arg)
    if (nargin < 1)
      arg = 42;
    end
    ...

which is somewhat verbose and easy to screw up.  Wouldn't it be better
to be able to write

  function foo (arg = 42)
    ...

instead?

jwe

Default arguments

by John W. Eaton :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 14-Dec-2006, Søren Hauberg wrote:

|    I'd really like Octave to have some way of having default function
| arguments. In C++ you can do
|
|    void fn(int arg = 7) {}
|
| I think R supports the same syntax. I don't think matlab has something
| similar, so if Octave adds support for default it should be something
| simple that won't break whatever syntax matlab decides to add in the
| future that'll handle default arguments.
|
|    So I suggest that Octave just adds some functions to make it easy to
| work with default arguments, instead of changing the syntax of the
| language. The C++ example above would then be written something like this
|
|    function fn(arg)
|      arg = default_value("arg", 7);
|    endfunction
|
| The function default_value should then expand (like a macro in C/C++)
| into this code
|
|      if (!exist(arg, "var")
|        arg = val;
|      endif

Wouldn't it be better to have the syntax

  function foo (arg = default_val)

?  The patch below (only very slightly tested) implements
this syntax.  It doesn't introduce any new conflicts in the parser, so
I think it should be OK.  With the patch, you can write things like
this:

  octave:1> function x = bar () persistent retval = 0; x = retval++; end
  octave:2> function y = foo (x = bar ()) y = x; end
  octave:3> foo ()
  ans = 0
  octave:4> foo (10)
  ans =  10
  octave:5> foo ()
  ans =  1

It also works for anonymous functions:

  octave:6> f = @(x=1) x
  f =

  @(x = 1) x

  octave:7> f ()
  ans =  1


As you note, there is the possiblity of a future incompatibility with
Matlab.  Is this feature worth the risk?  I think I would want to use
it in functions that are distributed with Octave to simplify code that
needs to set default values.

| One thing that's missing from this idea, is a way to tell the function
| to use the default argument. As an example, think of a function that
| takes three arguments
|
|    function fn2(arg1, arg2, arg3)
|      ...
|    endfunction
|
| How does the user tell fn2 that he wants to set the value of arg1 and
| arg3, but use the default value for arg2? I suggest adding a function
| called "default" that returns an object of type "default". That way the
| user can write
|
|    fn2(arg1, default, arg3)
|
| I don't know how to handle varargin, but I don't think there is much one
| can do...

My patch overloads ":" for this purpose:

  octave:1> function f (x = 1, y = 2, z = 3) x, y, z, end
  octave:2> f (10, :, 20)
  x =  10
  y =  2
  z =  20
  octave:3> function f (x = 1, y, z = 3) x, y, z, end
  octave:4> f (10, :, 20)
  error: no default value for argument 2

Is that reasonable?

Or, maybe what you really want is keyword arguments?  I think that
would be harder to add.

Although I've checked this patch in to the CVS archive, I consider it
to be quite experimental.  If any nontrivial problems show up that are
related to this change, I'll simply remove it.

jwe


src/ChangeLog:

2006-12-14  John W. Eaton  <jwe@...>

        * pt-decl.cc (tree_decl_elt::eval): New function.
        * pt-decl.h (tree_decl_elt::eval): Provide decl.
        (tree_decl_elt::is_defined, tree_decl_elt::lvalue_ok,
        tree_decl_elt::mark_as_formal_parameter, tree_decl_elt::rvalue,
        tree_decl_elt::lvalue): New functions.

        * pt-misc.h (class tree_parameter_list): Derive from
        octave_base_list<tree_decl_elt *> instead of
        octave_base_list<tree_identifier *>.
        (tree_parameter_list::tree_parameter_list (tree_identifier *)): Delete.
        (tree_parameter_list::tree_parameter_list (tree_decl_elt *)):
        New function.
        * pt-misc.cc (tree_parameter_list::mark_as_formal_parameters,
        tree_parameter_list::initialize_undefined_elements,
        tree_parameter_list::undefine, tree_parameter_list::dup,
        tree_parameter_list::convert_to_const_vector,
        tree_parameter_list::is_defined): Handle argument list elements
        as tree_decl_list objects instead of tree_identifier objects.
        (tree_parameter_list::define_from_arg_vector): Likewise.
        Always process entire list, setting default values if possible.
        Accept ":" to mean "use default argument".

        * parse.y (param_list2): Use decl2 to recognize
        "identifier '=' expression" in addition to "identifier".

        * parse.y (return_list1, make_anon_fcn_handle, finish_function):
        Adapt to new definition of tree_parameter_list.
        * pt-bp.cc (tree_breakpoint::visit_parameter_list): Likewise.
        * pt-check.cc (tree_checker::visit_parameter_list): Likewise.
        * pt-pr-code.cc (tree_print_code::visit_parameter_list): Likewise.


Index: src/parse.y
===================================================================
RCS file: /cvs/octave/src/parse.y,v
retrieving revision 1.268
diff -u -u -r1.268 parse.y
--- src/parse.y 29 Aug 2006 16:37:40 -0000 1.268
+++ src/parse.y 15 Dec 2006 03:22:23 -0000
@@ -1165,9 +1165,9 @@
   }
  ;
 
-param_list2 : identifier
+param_list2 : decl2
   { $$ = new tree_parameter_list ($1); }
- | param_list2 ',' identifier
+ | param_list2 ',' decl2
   {
     $1->append ($3);
     $$ = $1;
@@ -1214,10 +1214,10 @@
  ;
 
 return_list1 : identifier
-  { $$ = new tree_parameter_list ($1); }
+  { $$ = new tree_parameter_list (new tree_decl_elt ($1)); }
  | return_list1 ',' identifier
   {
-    $1->append ($3);
+    $1->append (new tree_decl_elt ($3));
     $$ = $1;
   }
  ;
@@ -1796,8 +1796,9 @@
       // created so we don't have to create a new statement at all.
 
       id = new tree_identifier (sr);
+      tree_decl_elt *elt = new tree_decl_elt (id);
 
-      ret_list = new tree_parameter_list (id);
+      ret_list = new tree_parameter_list (elt);
     }
 
   tree_statement_list *body = new tree_statement_list (stmt);
@@ -2585,7 +2586,9 @@
 finish_function (tree_identifier *id, octave_user_function *fcn,
  octave_comment_list *lc)
 {
-  tree_parameter_list *tpl = new tree_parameter_list (id);
+  tree_decl_elt *tmp = new tree_decl_elt (id);
+
+  tree_parameter_list *tpl = new tree_parameter_list (tmp);
 
   tpl->mark_as_formal_parameters ();
 
Index: src/pt-bp.cc
===================================================================
RCS file: /cvs/octave/src/pt-bp.cc,v
retrieving revision 1.22
diff -u -u -r1.22 pt-bp.cc
--- src/pt-bp.cc 16 Jun 2006 05:09:41 -0000 1.22
+++ src/pt-bp.cc 15 Dec 2006 03:22:23 -0000
@@ -470,7 +470,7 @@
 
   while (p != lst.end ())
     {
-      tree_identifier *elt = *p++;
+      tree_decl_elt *elt = *p++;
 
       if (elt)
  elt->accept (*this);
Index: src/pt-check.cc
===================================================================
RCS file: /cvs/octave/src/pt-check.cc,v
retrieving revision 1.18
diff -u -u -r1.18 pt-check.cc
--- src/pt-check.cc 16 Jun 2006 05:09:41 -0000 1.18
+++ src/pt-check.cc 15 Dec 2006 03:22:23 -0000
@@ -327,7 +327,7 @@
 
   while (p != lst.end ())
     {
-      tree_identifier *elt = *p++;
+      tree_decl_elt *elt = *p++;
 
       if (elt)
  elt->accept (*this);
Index: src/pt-decl.cc
===================================================================
RCS file: /cvs/octave/src/pt-decl.cc,v
retrieving revision 1.23
diff -u -u -r1.23 pt-decl.cc
--- src/pt-decl.cc 16 Jun 2006 05:09:42 -0000 1.23
+++ src/pt-decl.cc 15 Dec 2006 03:22:23 -0000
@@ -45,6 +45,28 @@
   delete expr;
 }
 
+bool
+tree_decl_elt::eval (void)
+{
+  bool retval = false;
+
+  if (id && expr)
+    {
+      octave_lvalue ult = id->lvalue ();
+
+      octave_value init_val = expr->rvalue ();
+
+      if (! error_state)
+ {
+  ult.assign (octave_value::op_asn_eq, init_val);
+
+  retval = true;
+ }
+    }
+
+  return retval;
+}
+
 tree_decl_elt *
 tree_decl_elt::dup (symbol_table *sym_tab)
 {
Index: src/pt-decl.h
===================================================================
RCS file: /cvs/octave/src/pt-decl.h,v
retrieving revision 1.12
diff -u -u -r1.12 pt-decl.h
--- src/pt-decl.h 16 Jun 2006 05:09:42 -0000 1.12
+++ src/pt-decl.h 15 Dec 2006 03:22:23 -0000
@@ -32,7 +32,9 @@
 #include <string>
 
 #include "base-list.h"
+#include "oct-lvalue.h"
 #include "pt-cmd.h"
+#include "pt-id.h"
 
 // List of expressions that make up a declaration statement.
 
@@ -48,7 +50,26 @@
 
   ~tree_decl_elt (void);
 
-  void eval (void);
+  bool eval (void);
+
+  bool is_defined (void) { return id ? id->is_defined () : false; }
+
+  void mark_as_formal_parameter (void)
+  {
+    if (id)
+      id->mark_as_formal_parameter ();
+  }
+
+  bool lvalue_ok (void) { return id ? id->lvalue_ok () : false; }
+
+  octave_value rvalue (void) { return id ? id->rvalue () : octave_value (); }
+
+  octave_value_list rvalue (int nargout)
+  {
+    return id ? id->rvalue (nargout) : octave_value_list ();
+  }
+
+  octave_lvalue lvalue (void) { return id ? id->lvalue () : octave_lvalue (); }
 
   tree_identifier *ident (void) { return id; }
 
Index: src/pt-misc.cc
===================================================================
RCS file: /cvs/octave/src/pt-misc.cc,v
retrieving revision 1.68
diff -u -u -r1.68 pt-misc.cc
--- src/pt-misc.cc 16 Jun 2006 05:09:42 -0000 1.68
+++ src/pt-misc.cc 15 Dec 2006 03:22:23 -0000
@@ -54,7 +54,7 @@
 {
   for (iterator p = begin (); p != end (); p++)
     {
-      tree_identifier *elt = *p;
+      tree_decl_elt *elt = *p;
       elt->mark_as_formal_parameter ();
     }
 }
@@ -73,7 +73,7 @@
       if (++count > nargout)
  break;
 
-      tree_identifier *elt = *p;
+      tree_decl_elt *elt = *p;
 
       if (! elt->is_defined ())
  {
@@ -99,16 +99,13 @@
 {
   int nargin = args.length ();
 
-  if (nargin <= 0)
-    return;
-
   int expected_nargin = length ();
 
   iterator p = begin ();
 
   for (int i = 0; i < expected_nargin; i++)
     {
-      tree_identifier *elt = *p++;
+      tree_decl_elt *elt = *p++;
 
       octave_lvalue ref = elt->lvalue ();
 
@@ -116,14 +113,17 @@
  {
   if (args(i).is_defined () && args(i).is_magic_colon ())
     {
-      ::error ("invalid use of colon in function argument list");
-      return;
+      if (! elt->eval ())
+ {
+  ::error ("no default value for argument %d\n", i+1);
+  return;
+ }
     }
-
-  ref.assign (octave_value::op_asn_eq, args(i));
+  else
+    ref.assign (octave_value::op_asn_eq, args(i));
  }
       else
- ref.assign (octave_value::op_asn_eq, octave_value ());
+ elt->eval ();
     }
 }
 
@@ -136,7 +136,7 @@
 
   for (int i = 0; i < len; i++)
     {
-      tree_identifier *elt = *p++;
+      tree_decl_elt *elt = *p++;
 
       octave_lvalue ref = elt->lvalue ();
 
@@ -157,7 +157,7 @@
 
   for (iterator p = begin (); p != end (); p++)
     {
-      tree_identifier *elt = *p;
+      tree_decl_elt *elt = *p;
 
       retval(i++) = elt->is_defined () ? elt->rvalue () : octave_value ();
     }
@@ -175,7 +175,7 @@
 
   for (iterator p = begin (); p != end (); p++)
     {
-      tree_identifier *elt = *p;
+      tree_decl_elt *elt = *p;
 
       if (! elt->is_defined ())
  {
@@ -197,7 +197,7 @@
 
   for (iterator p = begin (); p != end (); p++)
     {
-      tree_identifier *elt = *p;
+      tree_decl_elt *elt = *p;
 
       new_list->append (elt->dup (sym_tab));
     }
Index: src/pt-misc.h
===================================================================
RCS file: /cvs/octave/src/pt-misc.h,v
retrieving revision 1.47
diff -u -u -r1.47 pt-misc.h
--- src/pt-misc.h 16 Jun 2006 05:09:42 -0000 1.47
+++ src/pt-misc.h 15 Dec 2006 03:22:23 -0000
@@ -36,20 +36,21 @@
 class tree_walker;
 
 #include "base-list.h"
+#include "pt-decl.h"
 
 // Parameter lists.  Used to hold the list of input and output
 // parameters in a function definition.  Elements are identifiers
 // only.
 
 class
-tree_parameter_list : public octave_base_list<tree_identifier *>
+tree_parameter_list : public octave_base_list<tree_decl_elt *>
 {
 public:
 
   tree_parameter_list (void)
     : marked_for_varargs (0) { }
 
-  tree_parameter_list (tree_identifier *t)
+  tree_parameter_list (tree_decl_elt *t)
     : marked_for_varargs (0) { append (t); }
 
   ~tree_parameter_list (void);
Index: src/pt-pr-code.cc
===================================================================
RCS file: /cvs/octave/src/pt-pr-code.cc,v
retrieving revision 1.51
diff -u -u -r1.51 pt-pr-code.cc
--- src/pt-pr-code.cc 16 Jun 2006 05:09:42 -0000 1.51
+++ src/pt-pr-code.cc 15 Dec 2006 03:22:23 -0000
@@ -721,7 +721,7 @@
 
   while (p != lst.end ())
     {
-      tree_identifier *elt = *p++;
+      tree_decl_elt *elt = *p++;
 
       if (elt)
  {

Re: Default arguments

by Tom Holroyd (NIH/NIMH) [E]-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Thu, 14 Dec 2006, John W. Eaton wrote:

> Wouldn't it be better to have the syntax
>  function foo (arg = default_val)

yes, much

> As you note, there is the possiblity of a future incompatibility with
> Matlab.  Is this feature worth the risk?

they will very likely copy this syntax. if they do not, they will
be screwing themselves; if they don't implement it, fine

Re: Default arguments

by Andreas Romeyke-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi John,


> We already have default values for arguments for many functions, so
> it's a little late to say that the language should not support them.
> Currently, you have to write something like
>
>   function foo (arg)
>     if (nargin < 1)
>       arg = 42;
>     end
>     ...
>
> which is somewhat verbose and easy to screw up.  Wouldn't it be better
> to be able to write
>
>   function foo (arg = 42)
>     ...
>
> instead?

Sure. But default arguments will  be crap. There is no real reason to
use them I think. It is mostly a sign of smelling code and bad
interface design. In your example you deny compiler hints, because if
you unintentional call foo() without arguments.

Do you have a good example where defaults really useful?

- From a functional point of view the right way to rewrite your example
above is:

function foo(arg)
...

function bar()
    foo(42)
...

This avoids complexity too, isolates code, is more readable and has a
clear interface. You will also be warned from Octave if you have
forgotten to call foo() with arguments.

Therefore I would say, if anyone use defaults it should be punished by
extra code lines. :)

Bye Andreas

- --
Software Developer / Dipl. Inform. (FH)
Max Planck Institute for Human Cognitive and Brain Sciences
Department of Psychology
Stephanstr. 1a, 04103 Leipzig, Germany

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)

iD8DBQFFglcKGBhgJGthyeERAo0WAKC/NpcWmHQqxfvXAED/QmHIxGru6QCfTvto
AXOUV3qFUUzeSCQY3AFV8zQ=
=RxsI
-----END PGP SIGNATURE-----


Re: Default arguments

by Søren Hauberg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

John W. Eaton skrev:
> Wouldn't it be better to have the syntax
>
>   function foo (arg = default_val)
Oh yes, very much! I just figured it would be harder to add such a change...

> As you note, there is the possiblity of a future incompatibility with
> Matlab.  Is this feature worth the risk?  I think I would want to use
> it in functions that are distributed with Octave to simplify code that
> needs to set default values.
As Tom noted, matlab will probably use the same syntax in the future (it
is the defacto standard), so I think it's okay.

> | One thing that's missing from this idea, is a way to tell the function
> | to use the default argument.
> My patch overloads ":" for this purpose:
> Is that reasonable?
I'm not sure. I think ":" is the obvious choice, but I do have one
issue. Since matlab has decided to use "( )" to embreace function
arguments AND index matrices it is hard to tell functions and matrices
apart. One can think of functions as generalized matrices, so to some
extend this choice is okay (I'm not a fan though). However, if we allow
":" as an argument to a function it might be even harder to tell
matrices and functions apart.

> Or, maybe what you really want is keyword arguments?  I think that
> would be harder to add.
Well, those would be nicer so you can avoid writing
   my_function(:,:,:,:,:,:, my_value)
which can be hard to read and instead write
   my_function(my_arg = my_value)
My original proposal was to just do something that was easy to
implement, so I think it would be okay to not have keyword arguments.
Also, I don't think the ":" operator conflicts with keyword arguments,
so that could be added later on.

> Although I've checked this patch in to the CVS archive, I consider it
> to be quite experimental.  If any nontrivial problems show up that are
> related to this change, I'll simply remove it.
I can't really test this until sometime next week (I have a hard
deadline on monday), but then I'll report back...

Thanks,
Søren

P.S. Sometimes your abilities as a coding-ninja really impresses me...

Re: Default arguments

by Søren Hauberg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Andreas Romeyke skrev:
> Do you have a good example where defaults really useful?
In the "imshow" function your can specify a viewing range (i.e. tell the
function that a pixel value of 0 equals to black, and 100 equals white).

The default is to let 0 equal black, and 255 white, but at times you
want to change this. If "imshow" didn't have default arguments, I would
have to write
   imshow(im, [0, 255])
a lot of times, which would make me go insane (some might argue, that
it's too late...). Since imshow supports default arguments I just write
   imshow(im)
which is a lot easier to read (IMHO).

Søren

Re: Default arguments

by shaiay :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

While I agree with you in principle, I think we all need some quick
and dirty ways to quickly code what we want. While it is good to have
features in octave to enable the building of large applications in a
structured and maintainable way, (functions, containers, classes in
the future), it is also the case that a lot of octave users aren't
into producing large applications but rather small m-files to automate
repetitive tasks, and for them the quick yet bad in CS terms methods
are very helpful.

As pointed out, many (maybe even most) built-in m-files use default
arguments in a way which lets you use the most "generic" arguments w/o
having to specify them, so command line usage of octave is less
tedious.

Shai

On 12/15/06, Andreas Romeyke <romeyke@...> wrote:

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Hi John,
>
>
> > We already have default values for arguments for many functions, so
> > it's a little late to say that the language should not support them.
> > Currently, you have to write something like
> >
> >   function foo (arg)
> >     if (nargin < 1)
> >       arg = 42;
> >     end
> >     ...
> >
> > which is somewhat verbose and easy to screw up.  Wouldn't it be better
> > to be able to write
> >
> >   function foo (arg = 42)
> >     ...
> >
> > instead?
>
> Sure. But default arguments will  be crap. There is no real reason to
> use them I think. It is mostly a sign of smelling code and bad
> interface design. In your example you deny compiler hints, because if
> you unintentional call foo() without arguments.
>
> Do you have a good example where defaults really useful?
>
> - From a functional point of view the right way to rewrite your example
> above is:
>
> function foo(arg)
> ...
>
> function bar()
>     foo(42)
> ...
>
> This avoids complexity too, isolates code, is more readable and has a
> clear interface. You will also be warned from Octave if you have
> forgotten to call foo() with arguments.
>
> Therefore I would say, if anyone use defaults it should be punished by
> extra code lines. :)
>
> Bye Andreas
>
> - --
> Software Developer / Dipl. Inform. (FH)
> Max Planck Institute for Human Cognitive and Brain Sciences
> Department of Psychology
> Stephanstr. 1a, 04103 Leipzig, Germany
>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.5 (GNU/Linux)
>
> iD8DBQFFglcKGBhgJGthyeERAo0WAKC/NpcWmHQqxfvXAED/QmHIxGru6QCfTvto
> AXOUV3qFUUzeSCQY3AFV8zQ=
> =RxsI
> -----END PGP SIGNATURE-----
>
>

Re: Default arguments

by Andreas Romeyke-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi,

Søren Hauberg wrote:

>> Do you have a good example where defaults really useful?
> In the "imshow" function your can specify a viewing range (i.e.
> tell the function that a pixel value of 0 equals to black, and 100
> equals white).
>
> The default is to let 0 equal black, and 255 white, but at times
> you want to change this. If "imshow" didn't have default arguments,
> I would have to write imshow(im, [0, 255]) a lot of times, which
> would make me go insane (some might argue, that it's too late...).
> Since imshow supports default arguments I just write imshow(im)
> which is a lot easier to read (IMHO).
>
I disagree. The right way should be to use a specialized function.

Use "imshow_fullrange(im)" which calls "imshow(im, [0,255])". This
does not hide information. Remember that code is written once, but
read many times. It also makes it easier to change projects, if your
data-range is changed.

For example if imshow() or a caller function will support HDR-pictures
in the near future. It is easier to adopt "imshow_fullrange()" spread
to HDR as to break "imshow()" of your example, because some functions
will call it in HDR- and other in normal  semantics.

Bye Andreas

- --
Software Developer / Dipl. Inform. (FH)
Max Planck Institute for Human Cognitive and Brain Sciences
Department of Psychology
Stephanstr. 1a, 04103 Leipzig, Germany

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)

iD8DBQFFgqOCGBhgJGthyeERAkndAKCQymQdnkQ9TuWTv+n169vD2NzxSQCfRbGb
LegfKe3eQhr2waJzCeT2yTg=
=slK5
-----END PGP SIGNATURE-----


Re: Default arguments

by Søren Hauberg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Andreas Romeyke skrev:
> I disagree. The right way should be to use a specialized function.
Let's just say that we agree to disagree :-)

Søren

Re: Default arguments

by Sean O'Rourke :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

"John W. Eaton" <jwe@...> writes:
> Wouldn't it be better to be able to write
>
>   function foo (arg = 42)
>     ...
>
> instead?

It would also be better to be able to call foo like

    foo(arg = 42)

i.e. to have keyword arguments.  I've often found the following
idiom useful

    function blah(x, varargin)
        o = struct({ 'default', 1, 'values', 2, 'here', 3,
                     varargin{:} }{:});

    ...
    blah(x, 'here', 4);

but a bit of syntactic sugar around that would help.  If others
feel this is a good idea, I can probably implement it based on
John Eaton previous patch.

/s


Re: Default arguments

by Tom Holroyd (NIH/NIMH) [E] :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


> It would also be better to be able to call foo like
>
>     foo(arg = 42)

That could break existing code, though, because that's valid syntax now (set the local variable arg).


--
Tom Holroyd, Ph.D.
We experience the world not as it is, but as we expect it to be.

Re: Default arguments

by Sean O'Rourke :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

"Tom Holroyd (NIH/NIMH) [E]" <holroydt@...> writes:

>> It would also be better to be able to call foo like
>>
>>     foo(arg = 42)
>
> That could break existing code, though, because that's valid
> syntax now (set the local variable arg).

Right, but we can easily conjure some new syntax, e.g.

    foo(arg: 42)
    foo(arg => 42)
    foo(:arg 42)

/s


Re: Default arguments

by John W. Eaton :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 15-Dec-2006, Tom Holroyd (NIH/NIMH) [E] wrote:

|
| > It would also be better to be able to call foo like
| >
| >     foo(arg = 42)
|
| That could break existing code, though, because that's valid syntax now (set the local variable arg).

Yes, it would definitely cause trouble for Octave, though we could
consider a new operator, like

  foo (arg := 42)

But in Matlab assignment is not an expression, so the syntax you
quoted does not presently work.  So if they want to, I think they
could make it have the keyword argument meaning as a special case in
this context.

One problem I have with keyword arguments is that if they are allowed
for any function argument, then you have to carefully choose the names
of all function parameters, and once you've selected them, you can't
change them without the potential for breaking a lot of code.  There
would also be problems with the way variable arguments are overloaded
in some Matlab functions.  For example, being able to call a function
like this:

  axis (limits);

or

  axis (h, limits);

(sorry if some, or at least one, of you think this is "crap", but this
is the way many functions in Matlab already work, so we don't get a
choice here).

When you define this function, you have to write something like

  function axis (h, limits)
    if (nargin == 1)
      handle = gca ();
      limits = h;
    else if (nargin == 2)
      handle = h
    else
      print_usage ();
    endif
    ...

So given the way that many functions in Matlab are defined, I don't
think there is much possibility to handle keyword arguments in any
reasonable way based simply on the names that are used in the function
parameter list.  It just seems to me like it would be a mess.

In any case, Matlab already seems to be wedded to keyword-value pairs
written this way:

  set (h, 'key1', val1, 'key2', val2

so I doubt that Matlab will change to some other way of doing this.
OTOH, I could be wrong.

jwe

Re: Default arguments

by John W. Eaton :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 15-Dec-2006, Andreas Romeyke wrote:

| Sure. But default arguments will  be crap. There is no real reason to
| use them I think. It is mostly a sign of smelling code and bad
| interface design.

Please, tell us how you really feel.

In any case, Matlab is full of this kind of thing, and since Octave
implicitly aims to be compatible, it is also full of "crap".  It may
surprise you, but people really want compatibility; it seems to be one
of Octave's most cherished features.

|In your example you deny compiler hints, because if
| you unintentional call foo() without arguments.
|
| Do you have a good example where defaults really useful?

Yes, default arguments are necessary to implement many functions found
in Matlab, therefore they are useful to have in Octave.  As I said,
you can already implement default argument values by looking at
nargin, but I think the new syntax makes it clearer.  I know I would
prefer to read

  function foo (x, y, z = 13)
    ...

instead of

   function foo (x, y, z)
     if (nargin < 3)
       z = 13;
     endif
     ...

| - From a functional point of view the right way to rewrite your example
| above is:

Although I suppose there are some elements of functional programming
in the "Matlab language" (or whatever it is called), I don't think it
has any delusions about trying to be a pure and beautiful functional
language, so if you are looking for that, I think you've come to the
wrong place.

| function foo(arg)
| ...
|
| function bar()
|     foo(42)
| ...
|
| This avoids complexity too,

Really?  It seems to me it trades the complexity of default arguments
for a larger set of functions in the library, which itself is an
increase in complexity.

| Therefore I would say, if anyone use defaults it should be punished by
| extra code lines. :)

Why?  It seems to me that default arguments can make things more
concise.  So are you saying we should be punished for being concise?

Anyway, if you want to complain about the design of the "Matlab
language", maybe you should complain to the MathWorks?

jwe

Re: Default arguments

by Sean O'Rourke :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

My bad.

/s

-----------------------------------------------------------------

Please reply on the list so the discussion is kept archived and public
for others to comment.

Thanks,

jwe

On 15-Dec-2006, Sean O'Rourke wrote:

| "John W. Eaton" <jwe@...> writes:
| > One problem I have with keyword arguments is that if they are
| > allowed for any function argument, then you have to carefully
| > choose the names of all function parameters, and once you've
| > selected them, you can't change them without the potential for
| > breaking a lot of code.
|
| This is a significant constraint on library code (octave and
| octave-forge), but within your own code it seems manageable, and
| these kinds of interface decisions should be finalized before
| code is widely distributed.  I haven't had much trouble either
| with Lisp or with the current "'key', value" approach in Octave.
|
| > There would also be problems with the way variable arguments
| > are overloaded in some Matlab functions.
|
| I would propose that only arguments with default values can be
| passed using keywords, since non-optional keyword arguments are
| just strange.  That way there's no impact on existing functions.
|
| /s


Re: Default arguments

by Dmitri A. Sergatskov :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 12/15/06, Sean O'Rourke <sorourke@...> wrote:

> My bad.
>
> /s
>
> -----------------------------------------------------------------
>
> Please reply on the list so the discussion is kept archived and public
> for others to comment.
>
> Thanks,
>
> jwe
>
> On 15-Dec-2006, Sean O'Rourke wrote:
>
> | "John W. Eaton" <jwe@...> writes:
> | > One problem I have with keyword arguments is that if they are
> | > allowed for any function argument, then you have to carefully
> | > choose the names of all function parameters, and once you've
> | > selected them, you can't change them without the potential for
> | > breaking a lot of code.
> |
> | This is a significant constraint on library code (octave and
> | octave-forge), but within your own code it seems manageable, and
> | these kinds of interface decisions should be finalized before
> | code is widely distributed.  I haven't had much trouble either
> | with Lisp or with the current "'key', value" approach in Octave.
> |
> | > There would also be problems with the way variable arguments
> | > are overloaded in some Matlab functions.
> |
> | I would propose that only arguments with default values can be
> | passed using keywords, since non-optional keyword arguments are
> | just strange.  That way there's no impact on existing functions.
> |
> | /s
>
>

This all starting to remind me IDL, that has both positional and keyword
parameters for functions and procedures. Here is a snip from its manual:

<<<<
The correspondence between the actual parameters of the caller and the
formal parameters of the called procedure is established by position
or by keyword.

Positional Parameters (Arguments)

A positional parameter, or plain argument, is a parameter without a
keyword. Just as its name implies, the position of a positional
parameter establishes the correspondence—the n-th formal positional
parameter is matched with the n-th actual positional parameter.

Keyword Parameters

A keyword parameter, which can be either actual or formal, is an
expression or variable name preceded by a keyword and an equal sign
("=") that identifies which parameter is being passed.
When calling a routine with a keyword parameter, you can abbreviate
the keyword to its shortest, unambiguous abbreviation. Keyword
parameters can also be specified by the caller with the syntax
/KEYWORD, which is equivalent to setting the keyword parameter to 1
(e.g., KEYWORD = 1). The syntax /KEYWORD is often referred to, in the
rest of this documentation, as setting the keyword.
For example, a procedure is defined with a keyword parameter named TEST.
PRO XYZ, A, B, TEST = T
The caller can supply a value for the formal (keyword) parameter T
with the following calls:
; Supply only the value of T. A and B are undefined inside the
; procedure.
XYZ, TEST = A

; The value of A is copied to formal parameter T (note the
; abbreviation for TEST), Q to A, and R to B.
XYZ, TE = A, Q, R

; Variable Q is copied to formal parameter A. B and T are undefined
; inside the procedure.
XYZ, Q
result = FUNCTION(Arg1, Arg2, KEYWORD = value)

>>>>

FYI

Dmitri.
--


Re: Default arguments

by Tom Holroyd (NIH/NIMH) [E] :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



John W. Eaton wrote:

> On 15-Dec-2006, Tom Holroyd (NIH/NIMH) [E] wrote:
>
> |
> | > It would also be better to be able to call foo like
> | >
> | >     foo(arg = 42)
> |
> | That could break existing code, though, because that's valid syntax now (set the local variable arg).
>
> Yes, it would definitely cause trouble for Octave, though we could
> consider a new operator, like
>
>   foo (arg := 42)
>
> But in Matlab assignment is not an expression, so the syntax you
> quoted does not presently work.

But it does work in Octave! (That's what's important. :-)

I think a new operator would be a good way to go.

--
Tom Holroyd, Ph.D.
We experience the world not as it is, but as we expect it to be.

Re: Default arguments

by John W. Eaton :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 15-Dec-2006, Sean O'Rourke wrote:

| I would propose that only arguments with default values can be
| passed using keywords, since non-optional keyword arguments are
| just strange.  That way there's no impact on existing functions.

OK, this makes sense.  I don't know why I was thinking that it would
be meaningful to have keyword arguments without default values, since
keyword arguments are of course intended to be optional.  In any case,
I do agree that the maximum mixture of varargin, default values, and
keyword arguments could make a real mess.  But these features are
already used in some way or another.  So I don't see that we are
adding complexity here.  Really, we are just making it more manageable
because you currently have to do extra work to handle default values
and keyword arguments.  Whatever.  If you want to take a shot at
implmenting keyword arguments, please do so.  I'd consider a patch.
Please use ':=' as the new operator for the function call.

jwe
< Prev | 1 - 2 | Next >