why is there no function call with named parameters?

7,155 views
Skip to first unread message

Peter Kleiweg

unread,
Jul 6, 2011, 4:34:02 PM7/6/11
to golan...@googlegroups.com

You can initialize a complex variable with just parts specified,
but you can't call a function this way. Why not? Very useful for
functions with a lot of parameters that specify optional
arguments.

Now, if the order of parameters of a function changes, or if it
gains a parameter, I have to change all function calls. Or I can
call a function with parameters in the wrong order, if they have
the same type, and get untraceable errors.

package main

import "fmt"

type t struct { a, b, c int }

func f(a, b, c int) int {

return a + 2 * b + 3 * c

}

func main() {

fmt.Printf("%+v\n", t{b:5}) // prints: {a:0 b:3 c:0}

// fmt.Printnl(f(b:10)) // won't compile

}

--
Peter Kleiweg
http://pkleiweg.home.xs4all.nl/

peter

unread,
Jul 6, 2011, 4:50:52 PM7/6/11
to golang-nuts
On 6 jul, 22:34, Peter Kleiweg <pklei...@xs4all.nl> wrote:
> You can initialize a complex variable with just parts specified,
> but you can't call a function this way. Why not? Very useful for
> functions with a lot of parameters that specify optional
> arguments.

I can do this, but it's ugly, even more if I want to have non-zero
defaults:

type fArgs struct {a, b, c int}
func f(a *fArgs) int {
return a.a + 2 * a.b + 3 * a.c
}

func main() {
fmt.Println(f(&fArgs{b:5}))

Kyle Lemons

unread,
Jul 6, 2011, 5:42:29 PM7/6/11
to peter, golang-nuts
I find that most of the time an options structure or something similar is appropriate when you have "large numbers of optional parameters" and such.  Also, to simplify your example, you can make it more legible by e.g.

package main

import "fmt"

type f struct {
a,b,c int
}

func (x f) add() int {
return x.a + x.b + x.c
}

func main() {
fmt.Println(f{a:1, c:4}.add())

Ostsol

unread,
Jul 6, 2011, 9:12:52 PM7/6/11
to golan...@googlegroups.com
I think it's a readability issue.  When reading code, you always know what all the values of a function call's parameters are, without having to look deep into the function/method spec to see what it's defaulting to.

There's also the belief that if one has a common use case where only a few parameters are really necessary, a separate function should be created.  A recent thread discussed strings.Split(), and how often one does not want to specify the number of sub-strings to look for.  In tip, Split is now SplitN and the new Split looks for all sub-strings.  A similar action was taken to split os.Open into three distinct functions: one for each of the most common use cases.

-Daniel

tiny_dust

unread,
Jul 7, 2011, 12:26:04 AM7/7/11
to golang-nuts
read function spec is the must before you use it.

combine named parameters with default value can improve readability
that is to say,any parameter with default value should use name to
specify different value

for example in os package:

func (f *File)Readdir(n int)([]*FileInfo ,err Error){....}

i think the new declaration is better:

const NOT_LIMIT=-1
func (f*File)ReadDir(limit=NOT_LIMITED int)(infos []*FileInfo, e Error)
{....}

usage:

(1) afile.ReadDir()
(2) afile.ReadDir(limit=600)
(3) afile.ReadDir(600) // error!


without this ,we will surely see these f**kers:
CreateWnd(...),
CreateWndEx(...)
CreateWndExEx(...)

in fact, the issues about "strings.Split" and " os.Open" show us
that even skilled programmers in go teams can not do the right
thing at the fist time.

Ruslan Mezentsev

unread,
Jul 7, 2011, 1:18:30 AM7/7/11
to golang-nuts
Hi, what's the advantage of showing an error without a name, than
realized it did not show (as in C++ or Python).

tiny_dust

unread,
Jul 7, 2011, 6:48:18 AM7/7/11
to golang-nuts
for clarity.

i think it is a good idiom to make the difference explicitly. it is
a hint for "optional" parameters, and can introduce more meanings.
the function with default value parameter usually have long parameter
list, the situation will benefit much from it
it is natural for people to not care about the sequence of optional
parameters.

example
(1)
const NOT_LIMIT=-1
func Split(s ,sep string, limit=NOT_LIMIT){....}

Split("fffffffffksssss","k",limit=12)
VS
Split("ffffffksssss","k",12) //bad
(2)
Connect(addr string,usr="root" ,pass="",port=3306 ,timeout=30){....}

Connect("localhost",usr="ddd",pass="go",port=3307,timeout=3300)
VS
Connect("localhost","ddd","go",3307,3300) //bad

note: it is not function oveload!!

chris dollin

unread,
Jul 7, 2011, 6:59:06 AM7/7/11
to tiny_dust, golang-nuts
On 7 July 2011 11:48, tiny_dust <ustc....@gmail.com> wrote:
> for clarity.
>
> i think it is a good idiom to make the difference  explicitly.  it is
> a hint for "optional" parameters, and can introduce more meanings.
> the function with default value parameter usually have long parameter
> list, the situation will benefit much from it
> it is natural for people  to not care about the sequence of optional
> parameters.
>
> example
> (1)
> const NOT_LIMIT=-1
> func Split(s ,sep string, limit=NOT_LIMIT){....}
>
> Split("fffffffffksssss","k",limit=12)
> VS
> Split("ffffffksssss","k",12)  //bad
> (2)
> Connect(addr string,usr="root" ,pass="",port=3306 ,timeout=30){....}
>
> Connect("localhost",usr="ddd",pass="go",port=3307,timeout=3300)
> VS
> Connect("localhost","ddd","go",3307,3300)    //bad
>
> note: it is not function oveload!!

Use a struct literal:

Connect( "localhost", Options{usr: "ddd", pass: "", port: 3306})

with a suitable declaration for Options. Now the "optional parameters"
are values and can be passed around, copied,
etc and co.

(I'm not convinced that named-argument and default-argument
machinery is worth the investment. Amonst other things, it makes
it easier to end up with ridiculously long parameter lists because
"you only write what you need". The function still needs to /make
sense/ with all those arguments. You also need to make sure that
you can write types for these kinds of functions.)

Chris

--
Chris "allusive" Dollin

John Arbash Meinel

unread,
Jul 7, 2011, 7:10:11 AM7/7/11
to chris dollin, tiny_dust, golang-nuts
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


...


> with a suitable declaration for Options. Now the "optional parameters"
> are values and can be passed around, copied,
> etc and co.
>
> (I'm not convinced that named-argument and default-argument
> machinery is worth the investment. Amonst other things, it makes
> it easier to end up with ridiculously long parameter lists because
> "you only write what you need". The function still needs to /make
> sense/ with all those arguments. You also need to make sure that
> you can write types for these kinds of functions.)
>
> Chris
>

I'll note that Javascript doesn't have named arguments, so it is a very
common idiom to make the last parameter a map/dict/... so that you can
supply named parameters. So you get

CallFoo(12, 13, {"a": b, "c": d})

While that works, it has the feeling of not being really supported by
the language. And it is a bit more verbose in Go:
map[string][string]{"a": b, "c": d}
Or you define an Options for each function that wants them, and somehow
avoid name collisions, etc. But then you get:
CallFoo(12, 13, CallFooOptions{a: b, c: d})
I suppose you get to avoid the quotes this way.

It still feels like the long-way-around for a language that already has
named parameters (just only at certain times).

John
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk4VlBMACgkQJdeBCYSNAAMHmQCfbpGru1MrJQ8zlWepUspX+kyx
vRkAoJPcTgz4YeeAZ1+gOAvbsB7hg+gH
=UDfs
-----END PGP SIGNATURE-----

chris dollin

unread,
Jul 7, 2011, 7:21:24 AM7/7/11
to John Arbash Meinel, tiny_dust, golang-nuts
On 7 July 2011 12:10, John Arbash Meinel <jo...@arbash-meinel.com> wrote:

> I'll note that Javascript doesn't have named arguments, so it is a very
> common idiom to make the last parameter a map/dict/... so that you can
> supply named parameters.

And Ruby has special syntactic sugar for this (maps as last arguments
to functions).

> And it is a bit more verbose in Go:
>  map[string][string]{"a": b, "c": d}
> Or you define an Options for each function that wants them,

Yes; then you get type-checking and the ability to treat
those Options as values in their own right.

> and somehow avoid name collisions, etc.

In the usual way, I imagine.

> But then you get:
>  CallFoo(12, 13, CallFooOptions{a: b, c: d})
> I suppose you get to avoid the quotes this way.

One would not call it CallFooOptions, and probably not FooOptions
either.

John Arbash Meinel

unread,
Jul 7, 2011, 7:31:22 AM7/7/11
to chris dollin, tiny_dust, golang-nuts
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


...


>> But then you get:
>> CallFoo(12, 13, CallFooOptions{a: b, c: d})
>> I suppose you get to avoid the quotes this way.
>
> One would not call it CallFooOptions, and probably not FooOptions
> either.
>
> Chris
>

Perhaps. But doesn't that restrict you to having only 1
"named-parameter" struct per package, rather than 1 per
function-that-wants-named-parameters?

John
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk4VmQoACgkQJdeBCYSNAAN0jgCfTw0yh+8rvl+sE068Rxt1lOBs
LEcAoJDhaeiM2ZHNgk5YIsGCVb3SJCwU
=AUyz
-----END PGP SIGNATURE-----

David Roundy

unread,
Jul 7, 2011, 9:23:22 AM7/7/11
to John Arbash Meinel, chris dollin, tiny_dust, golang-nuts
On Thu, Jul 7, 2011 at 12:31 PM, John Arbash Meinel
<jo...@arbash-meinel.com> wrote:
>> One would not call it CallFooOptions, and probably not FooOptions
>> either.
>
> Perhaps. But doesn't that restrict you to having only 1
> "named-parameter" struct per package, rather than 1 per
> function-that-wants-named-parameters?

When you've got so many function parameters that you feel a need to
give them names and default values, start thinking about whether they
might be reused in some ways, and how you'd group them such that they
*can* be reused.

The recent rewrite of the exec package is a nice example. There was a
function with an ever-increasing number of inputs and outputs, most of
which were usually unused. Now it's a struct, with a single helper
function to generate it in the most common case. But it's also no
longer an argument to a function, since you can now treat it as a
first-class data object, and can make copies of it and modify it to
your heart's content. A classic case where named arguments might have
been desired, where we got something better and more powerful instead.
--
David Roundy

Ostsol

unread,
Jul 7, 2011, 9:58:43 PM7/7/11
to golan...@googlegroups.com
I don't necessarily speak of using a function.  For that, of course one should read the spec.  Just imagine how much fewer trivial questions would appear on this list if everyone did that. ;)

My post was written from the perspective of one who decided to port some C++ code to Go and was irritated by things such as function overloading and default parameters.  These features of C++ certainly are convenient from the perspective of the one defining those functions, but reading such code is a hassle.  It is not always obvious what the function is doing simply by looking at the number of parameters input and their types.  Named parameters do help, but requiring a name is not so much different from simply having a different function entirely.

1. f.ReadDir()
2. f.ReadDirLimit(600)

Also, David Roundy brings up a great example where a function with a great deal of optional parameters can be reworked in a very nice way indeed.

-Daniel

crazy 2be

unread,
Jul 8, 2011, 9:54:18 PM7/8/11
to golan...@googlegroups.com, John Arbash Meinel, chris dollin, tiny_dust

When you've got so many function parameters that you feel a need to give them names and default values, start thinking about whether they might be reused in some ways, and how you'd group them such that they *can* be reused.

This. Initially I thought named parameters would be a great addition to the go language. However, they often encourage all-encompassing functions that do far too much. Have a look at python's argparse module or subprocess module and let me know if you still think named parameters are a good idea. In argparse's case, that one monolithic function would be much better split into several different functions, much like how go does things in it's flag package. As for subprocess, it's technique doesn't work nearly as well as the one used in go's exec package. Initially, it seems great, but it doesn't scale. When calling a function with more than ~5 arguments, it is nearly impossible to keep track of what each argument means. Named arguments help on a small scale, but don't make the code that much more readable. Not only that, but it makes it impossible to call the same function several times but with slight variations on the long list of parameters. Besides, once you get to the point where named arguments might be useful to keep track of what the parameters mean, a struct has very little code overhead to create.

Just my opinion.
-crazy2be

Joscha Bach

unread,
Jul 11, 2011, 6:09:42 PM7/11/11
to golang-nuts

There are cases where long, convoluted parameter lists are legitimate.
This is usually whenever you wrap an API that already has these, and/
or when you define GUIs. It does not make sense to define different
calls for opening a dialog with a closing icon, without a closing
icon, with ok button, with cancel buttons or any combination thereof.
It is also awkward to pass a lot of flags and empty strings. A
predefined struct might act as an ugly workaround (namespaces! I do
not want to invent a new type for each call, and I want to have
different UI elements in the same package), but proper named
parameters with sensible defaults strike me as the best way to go.
(See tiny_dust's example.)

Kyle Lemons

unread,
Jul 11, 2011, 6:18:16 PM7/11/11
to Joscha Bach, golang-nuts
If you are wrapping a library and not changing its interface, you cannot expect the code to be clean because it was designed for a language very different from Go.  If you redesign the library to have a few basic types that have the methods on them, then you can have some very simple, concise things like:

&Dialog{
   Closeable: true,
   Title: "Your Go installation is awesome",
   Buttons: []string{"ok", "thanks"},
}.Show()

~K
}

Russ Cox

unread,
Jul 11, 2011, 6:55:07 PM7/11/11
to Joscha Bach, golang-nuts
> There are cases where long, convoluted parameter lists are legitimate.

There are cases where X is legitimate for just about every
feature anyone has ever proposed. That doesn't mean we
have to put every feature anyone has ever proposed into Go.

Russ

Jan Mercl

unread,
Jul 12, 2011, 5:27:35 AM7/12/11
to golan...@googlegroups.com
On Tuesday, July 12, 2011 12:18:16 AM UTC+2, Kyle Lemons wrote:
If you are wrapping a library and not changing its interface, you cannot expect the code to be clean because it was designed for a language very different from Go.  If you redesign the library to have a few basic types that have the methods on them, then you can have some very simple, concise things like:

&Dialog{
   Closeable: true,
   Title: "Your Go installation is awesome",
   Buttons: []string{"ok", "thanks"},
}.Show()

"cannot call pointer method on struct literal" 

chris dollin

unread,
Jul 12, 2011, 5:40:02 AM7/12/11
to golan...@googlegroups.com

Looks like this is a syntactic infelicity; it seems that
it is parsing as &(Dialog{...}).Show() rather than
(&Dialog{...}).Show(). I can see why, but it's a shame.

Jan Mercl

unread,
Jul 12, 2011, 5:47:32 AM7/12/11
to golan...@googlegroups.com
On Tuesday, July 12, 2011 11:40:02 AM UTC+2, chris dollin wrote:

Looks like this is a syntactic infelicity; it seems that
it is parsing as &(Dialog{...}).Show() rather than
(&Dialog{...}).Show(). I can see why, but it's a shame.

I guess Go as usual tries not to be "smart" (i.e. surprising, sometimes/potentially in a bad way). One has to be explicit, it's easy

Joscha Bach

unread,
Jul 12, 2011, 7:07:28 AM7/12/11
to golang-nuts

Thanks Kyle!
Message has been deleted

Namegduf

unread,
Jul 12, 2011, 8:23:31 AM7/12/11
to golan...@googlegroups.com
On Tue, 12 Jul 2011 04:24:16 -0700 (PDT)
Joscha Bach <josch...@gmail.com> wrote:

>
>
> > There are cases where X is legitimate for just about every
> > feature anyone has ever proposed.  That doesn't mean we
> > have to put every feature anyone has ever proposed into Go.
>

> No need for that, I remember the famously unfriendly FAQ #14 :-)
> Nobody suggests that you should do that.
>
> I bet that you get the same questions over and over: Generics,
> overloading, tail calls, anonymous function recursions, boolean
> evaluation of all terms, named function arguments. But people do not
> bug you because they do not like the language, or because they do not
> read what you wrote earlier. For some of these decisions, they do not
> see a convincing argument (i.e., not something like "overloading could
> slow down the compiler", or "generics are only a convenience to the
> programmer").
>
> It would be great if you could set aside a corner where people can
> discuss features and possible extensions, and actual arguments are
> exchanged. Ideally, there might even be a defined process for that, so
> people like me can look up the ticket and see the current state of
> your decisions and reasoning.

My 0.02, IMHO and whatnot:

This mailing list seems to serve for discusssing "features and possible
extensions". Actual arguments are awesome. They're rarely accepted,
though, and in a language which is designed to be simple that's
probably a good thing. I doubt changing the venue would alter that.

I don't think I remember the position explained by the language devs
on this mailing list for any of those feature requests varying since
the language was released. Some kind of FAQ for common feature
requests might be useful just to discourage reviving discussions
without having new ideas regularly. Google Groups archives, so it could
readily link to previous discussions if they were felt to contribute.

I don't think conflating public discussion with dev reasoning is
accurate or wise, though.

Ian Lance Taylor

unread,
Jul 12, 2011, 10:33:34 AM7/12/11
to Joscha Bach, golang-nuts
Joscha Bach <josch...@gmail.com> writes:

> It would be great if you could set aside a corner where people can
> discuss features and possible extensions, and actual arguments are
> exchanged. Ideally, there might even be a defined process for that, so
> people like me can look up the ticket and see the current state of
> your decisions and reasoning.

I think we can use the wiki for that.

http://code.google.com/p/go-wiki/

Ian

Russ Cox

unread,
Jul 12, 2011, 12:23:27 PM7/12/11
to Joscha Bach, golang-nuts
> No need for that, I remember the famously unfriendly FAQ #14 :-)

I assume you are referring to
http://golang.org/doc/go_faq.html#Why_doesnt_Go_have_feature_X
I can't see what is unfriendly about that.

Russ

Message has been deleted

Andrew Gerrand

unread,
Jul 12, 2011, 8:15:53 PM7/12/11
to golan...@googlegroups.com


On Wednesday, 13 July 2011 03:17:43 UTC+10, Joscha Bach wrote:
#14 simply dismisses all these ideas out of hand, treating them as not
warranting any further discussion. It is always unfriendly to crush
peoples hopes and dreams without giving the appearance of even
listening.

It says "Your favorite feature may be missing because..." That's not an out-of-hand dismissal, but it is true we have hashed out most of these discussions in public on this very list. Do some searching around and you'll find them.
 
It might very well be that all of your design decisions are indeed for
the best.

They aren't always. We have changed the language several times based on the experiences of Go programmers.

In principle I agree with you. It would be nice to have these discussions summarized somewhere, and the go-wiki is probably a good place for it. But people ALWAYS have something else to say about it, and - to be quite frank - we are a small team with a lot on our plate. We don't have the time to reassure people that they have been listened to. I, personally, would rather spend my time educating people how to use the Go we have, rather than speculate about the Go we might have.

Andrew

Joscha Bach

unread,
Jul 13, 2011, 8:30:06 AM7/13/11
to golang-nuts
> In principle I agree with you. It would be nice to have these discussions
> summarized somewhere, and the go-wiki is probably a good place for it.

Thank you for this! In principle, I agree with you, too. Some people
are always going to misunderstand you ideas, or have second thoughts
about it, and it is you who should make the decisions, and get actual
work done.

> people ALWAYS have something else to say about it

That is the drawback of a Wiki. In a ticketing system, you can close
discussions formally (but of course, you can finalize Wiki
discussions, too).
Design by committee does not work, but you will want to have a smart
and motivated and happy community of early adopters: stubborn and
smart and skeptical people like yourself, and every now and then,
someone will come up with a brillant point.
People are going to adopt Go if they are convinced that your decisions
are for the best, so please tell them why. And once an issue is
settled to you, just say so (and why), so people do not have to bring
it up again.

> I, personally, would rather
> spend my time educating people how to use the Go we have, rather than
> speculate about the Go we might have.

Fortunately, you can do both! Go is still young and pliable. Its
future seems to be entirely open. Decisions that you make now will
define whether Go is going to take Java's place for server apps, or
may replace ObjectiveC/C# as a desktop app language, or Python as a
toolbox for weekend projects, or if it stays at the level of an
extended tech demo (gotta love the Goroutines!).

My feeling is that a lot of people are convinced that Java has taught
us all it can do, on how NOT to design a C-oid language, and the time
is ripe for taking the lessons and doing it all over. Your team can
probably be any size you find convenient, because a number of
companies might be willing to throw money or time on it.

Russ Cox

unread,
Jul 13, 2011, 1:21:22 PM7/13/11
to Joscha Bach, golang-nuts
>> I, personally, would rather
>> spend my time educating people how to use the Go we have, rather than
>> speculate about the Go we might have.
>
> Fortunately, you can do both!

You have failed to understand the essence of time management.

Message has been deleted

Andrew Gerrand

unread,
Jul 13, 2011, 6:40:49 PM7/13/11
to golan...@googlegroups.com
On Thursday, 14 July 2011 04:14:56 UTC+10, Joscha Bach wrote:

> You have failed to understand the essence of time management.

Russ, thank you for the kind advice. I will check back into this
discussion next time I need feedback on how I fail or what I should
know about time management.

I think what Russ means is that the essence of time management is choosing what not to do.

We have so many ideas for things we could do, but we have to choose carefully. Unfortunately, I can't magically have all my thoughts about Go translated to well-written articles. Writing takes time (more than anything else, it seems), and for it to be worth reading it needs to be fueled by experience (ie, not writing) and deep thought.

Andrew
Reply all
Reply to author
Forward
0 new messages