www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Associative parameters

reply Chris Sauls <ibisbasenji gmail.com> writes:
Okay... I vaguely remember this getting mentioned, either by myself, or
Matthew, or some 
other D-ite with some Python experience, and then getting discussed briefly,
and 
more-or-less forgotten...  Well, recently I found myself randomly loving it
again, and 
decided to bring it up once more.  :)

In python, suppose a define a function, let's call it 'foo', and suppose it
takes three 
paramters, let's call them 'x', 'y', and 'z'.  Now, ordinarily one would just
call it in 
the usual way:

# foo( someX, someY, someZ )

But suppose, for some reason -- maybe the values look better this way, maybe it
suits the 
overall style of the coder writing the call, whatever -- someone decides they'd
like to 
pass them in a different order, or that they'd like to be explicit about what
each 
parameter is (I've felt this way often with the Win32 API, for example, and
usually go 
about it using comments).  In python, you would do something like this:

# foo (
#   x = someX ,
#   y = someY ,
#   z = someZ
#   )

Now isn't that just nifty?  So... given the following D function decleration:

# void myfunc (Cartesian grid, Point rectOrigin, Size rectSize, Translation
action) {
#   // do stuff
# }

Wouldn't it be nice to be able to do something like... this:

# myfunc(
#   action     : Translation.Move(5, 10)       ,
#   rectOrigin : Point(p_rect.x, p_rect.y)     ,
#   rectSize   : Size(p_rect.w, p_rect.h)      ,
#   grid       : g_grid                        ,
# );

Now... isn't that descriptive?  :)  Naturally there would have to be strict
rules.  Either 
A) make a given function call either associative or not, never both, or B)
require that 
any non-associative parameters come first and be in proper order (which if I
remember 
right, is what Python does).  Also it would, of course, have to be an error to
pass a 
parameter twice.

I know I'm probably blowing smoke, but its something I'm fond of.  (The
associative 
parameters, not the smoke.)

-- Chris Sauls
Jun 26 2005
next sibling parent reply Sefan Zobel <Sefan_member pathlink.com> writes:
In article <d9lnrr$26q3$1 digitaldaemon.com>, Chris Sauls says...
 In python, you would do something like this:

# foo (
#   x = someX ,
#   y = someY ,
#   z = someZ
#   )

Now isn't that just nifty?

This is also called "named parameters" in some languages (since parameters are resolved by name, not by position). And, yes, I like it too :) Best regards, Stefan
Jun 26 2005
parent reply "Walter" <newshound digitalmars.com> writes:
"Sefan Zobel" <Sefan_member pathlink.com> wrote in message
news:d9n5i9$aad$1 digitaldaemon.com...
 In article <d9lnrr$26q3$1 digitaldaemon.com>, Chris Sauls says...
 In python, you would do something like this:

# foo (
#   x = someX ,
#   y = someY ,
#   z = someZ
#   )

Now isn't that just nifty?

This is also called "named parameters" in some languages (since parameters are resolved by name, not by position). And, yes, I like it too :)

Named parameters are problematic when overloading is thrown into the mix.
Jun 26 2005
parent reply Greg <greg gmail.com> writes:
Walter Wrote:

 
 "Sefan Zobel" <Sefan_member pathlink.com> wrote in message
 news:d9n5i9$aad$1 digitaldaemon.com...
 In article <d9lnrr$26q3$1 digitaldaemon.com>, Chris Sauls says...
 In python, you would do something like this:

# foo (
#   x = someX ,
#   y = someY ,
#   z = someZ
#   )

Now isn't that just nifty?

This is also called "named parameters" in some languages (since parameters are resolved by name, not by position). And, yes, I like it too :)

Named parameters are problematic when overloading is thrown into the mix.

In addition to making the code easier to read, named parameters avoid the burden of creating "dummy" functions when some parameters are optional. I found nothing on the net telling that python's or ada's implementation of named parameters is problematic. Can someone confirm/infirm on this point?
Jul 10 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Greg wrote:
 Walter Wrote:
 
 "Sefan Zobel" <Sefan_member pathlink.com> wrote in message
 news:d9n5i9$aad$1 digitaldaemon.com...
 In article <d9lnrr$26q3$1 digitaldaemon.com>, Chris Sauls says...
 In python, you would do something like this:

 # foo (
 #   x = someX ,
 #   y = someY ,
 #   z = someZ
 #   )

 Now isn't that just nifty?

This is also called "named parameters" in some languages (since parameters are resolved by name, not by position). And, yes, I like it too :)


In addition to making the code easier to read, named parameters avoid the burden of creating "dummy" functions when some parameters are optional. I found nothing on the net telling that python's or ada's implementation of named parameters is problematic. Can someone confirm/infirm on this point?

I don't know about Ada, but Python doesn't have function overloading. A given module can only have one function called 'foo'. But I do recall reading an essay/rant somewhere talking about how sometimes just picking one way to do something makes life easier for everyone, and the handling of function overloading was mentioned. I think it mentioned Ada's way and Python's way specifically. Unfortunately I can't seem to find it now. --bb
Jul 10 2007
parent reply Pragma <ericanderton yahoo.removeme.com> writes:
Bill Baxter wrote:
 Greg wrote:
 Walter Wrote:

 "Sefan Zobel" <Sefan_member pathlink.com> wrote in message
 news:d9n5i9$aad$1 digitaldaemon.com...
 In article <d9lnrr$26q3$1 digitaldaemon.com>, Chris Sauls says...
 In python, you would do something like this:

 # foo (
 #   x = someX ,
 #   y = someY ,
 #   z = someZ
 #   )

 Now isn't that just nifty?

This is also called "named parameters" in some languages (since parameters are resolved by name, not by position). And, yes, I like it too :)

mix.

aware of any problems with it. In addition to making the code easier to read, named parameters avoid the burden of creating "dummy" functions when some parameters are optional. I found nothing on the net telling that python's or ada's implementation of named parameters is problematic. Can someone confirm/infirm on this point?

I don't know about Ada, but Python doesn't have function overloading. A given module can only have one function called 'foo'.

Just my $0.02 here: Lately I have been doing a lot more python programming and I've found it's named arguments to be a good substitute for overloading. It's not perfect replacement, but it does have its advantages. I have yet to find it problematic. I can't speak for Ada though. FWIW, ColdFusion script also offers named arguments, but it takes the all-or-nothing approach; if you name one arg, you must name all that you pass. IMO, the python strategy (positional followed by named arguments) is much more intuitive. But from what I can tell, named arguments are no more or less problematic than overloads mixed with default arguments. Right now, it's possible to create two or more overloads that can be called the same way, resulting in an ambiguity that is easily flagged by the compiler. Named arguments just provide another way to make the same kind of mistake, so the developer must be no more aware than before. void foobar(int d); void foobar(int a=0,int b=0,int c=0,int d=0); foobar(d=42); // which one? foobar(69); // which one?
 
 But I do recall reading an essay/rant somewhere talking about how 
 sometimes just picking one way to do something makes life easier for 
 everyone, and the handling of function overloading was mentioned.  I 
 think it mentioned Ada's way and Python's way specifically. 
 Unfortunately I can't seem to find it now.
 
 --bb

-- - EricAnderton at yahoo
Jul 10 2007
next sibling parent BCS <ao pathlink.com> writes:
Reply to Pragma,

 FWIW, ColdFusion script also offers named arguments, but it takes the
 all-or-nothing approach; if you name one arg, you must name all that
 you pass.  IMO, the python strategy (positional followed by named
 arguments) is much more intuitive.
 

if we get named parameters, then we should also be able to get a tuple of parameter names. maybe something like this: is(typeof(fn) args = function); is(fn argNames = names); args val; foreach(name; argNames) val[name] = typeof(val[name]).init; this would make my argument biding template(*) more robust. static int fnc(int that, char has, bool lots, int[] of, float args) // bind some args alias Args! (0,2,4).Become!(1,true,1e7).For!(fnc).Gives fn2; vs. alias Args! (that,lots,args).Become!(1,true,1e7).For!(fnc).Gives fn2; * http://www.dsource.org/projects/scrapple/browser/trunk/arg_bind/bind.d
Jul 10 2007
prev sibling parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Pragma wrote:
 Just my $0.02 here: Lately I have been doing a lot more python 
 programming and I've found it's named arguments to be a good substitute 
 for overloading.  It's not perfect replacement, but it does have its 
 advantages.  I have yet to find it
 problematic.

I think there's not much other way you could implement overloading in a language like Python where there are no declared types. def foo(x): # do one thing def foo(y): # do another thing How's the interpreter supposed to decide which one you mean? You could overload on the number of arguments I suppose, but by doing that you'd mostly just lose the ability to unambiguously refer to functions by name (which bites us even today in D2.0 -- callback=&foo; ... but which foo?). Variable numbers of arguments can be reasonably implemented using defaults. But when you do have type info that you can overload on, it's a whole different thing.
 But from what I can tell, named arguments are no more or less 
 problematic than overloads mixed with default arguments. Right now, it's 
 possible to create two or more overloads that can be called the same 
 way, resulting in an ambiguity that is easily flagged by the compiler.
 Named arguments just provide another way to make the same kind of 
 mistake, so the developer must be no more aware than before.
 
 void foobar(int d);
 void foobar(int a=0,int b=0,int c=0,int d=0);
 foobar(d=42); // which one?
 foobar(69);   // which one?

I like the idea of named parameters too, but the contrarian's argument is that even if the compiler can catch all the errors, it still adds a lot of complexity to the language. Especially since there are already 3 ways to overload functions (by arg types, by number of args, and with defaults). To make it feasible I think we're first going to have to introduce a special syntax for keyword arguments. Any D code that exists today should continue to behave the same as it does now. Suddenly giving meaning to all parameter names would be a catastrophe. In Lisp, for example, all keyword arguments follow a &key sigil: http://www.gigamonkeys.com/book/functions.html (defun foo (bar &key (a 0) b c) (list bar a b c)) (foo) ==> ERROR missing required argument 'bar' (foo 99) ==> (99 0 NIL NIL) (foo 99 :a 1) ==> (99 1 NIL NIL) (foo 99 :b 1) ==> (99 0 1 NIL) Something like that could probably be made to work for D. I think Lisp also requires you to supply the keyword when you call it. I.e. (foo 3 2 1 0) doesn't work. You have to name the keyword arguments. Even if that's not Lisp's rule, it makes sense for D, since it would cut down a lot on overload ambiguity issues. In D you'd also be required to supply default values for all keyword args. Be So for D we could do something like: void foo(int bar, :key: int a=0, int b=0, int c=0) { writefln("%s %s %s %s", bar,a,b,c}; } The ":key:" token is just an example. Could be any other unambiguous token. --bb
Jul 10 2007
prev sibling parent David Medlock <noone nowhere.com> writes:
Chris Sauls wrote:

 Okay... I vaguely remember this getting mentioned, either by myself, or 
 Matthew, or some other D-ite with some Python experience, and then 
 getting discussed briefly, and more-or-less forgotten...  Well, recently 
 I found myself randomly loving it again, and decided to bring it up once 
 more.  :)
 
 In python, suppose a define a function, let's call it 'foo', and suppose 
 it takes three paramters, let's call them 'x', 'y', and 'z'.  Now, 
 ordinarily one would just call it in the usual way:
 
 # foo( someX, someY, someZ )
 
 But suppose, for some reason -- maybe the values look better this way, 
 maybe it suits the overall style of the coder writing the call, whatever 
 -- someone decides they'd like to pass them in a different order, or 
 that they'd like to be explicit about what each parameter is (I've felt 
 this way often with the Win32 API, for example, and usually go about it 
 using comments).  In python, you would do something like this:
 
 # foo (
 #   x = someX ,
 #   y = someY ,
 #   z = someZ
 #   )
 
 Now isn't that just nifty?  So... given the following D function 
 decleration:
 
 # void myfunc (Cartesian grid, Point rectOrigin, Size rectSize, 
 Translation action) {
 #   // do stuff
 # }
 
 Wouldn't it be nice to be able to do something like... this:
 
 # myfunc(
 #   action     : Translation.Move(5, 10)       ,
 #   rectOrigin : Point(p_rect.x, p_rect.y)     ,
 #   rectSize   : Size(p_rect.w, p_rect.h)      ,
 #   grid       : g_grid                        ,
 # );
 
 Now... isn't that descriptive?  :)  Naturally there would have to be 
 strict rules.  Either A) make a given function call either associative 
 or not, never both, or B) require that any non-associative parameters 
 come first and be in proper order (which if I remember right, is what 
 Python does).  Also it would, of course, have to be an error to pass a 
 parameter twice.
 
 I know I'm probably blowing smoke, but its something I'm fond of.  (The 
 associative parameters, not the smoke.)
 
 -- Chris Sauls

// Closest hack I can think of: import std.stdio; template myfunc() { int x=0, y=0, z=0; void call( int xx = x, int yy=y, int zz = z ) { writefln( "X %s, Y %s, Z %s", xx, yy, zz ); } } void main( char[][] arg ) { with( myfunc!() ) { x = 100; y = 200; z = -20; call(); } }
Jun 27 2005