keyword= support for function calls

139 views
Skip to first unread message

Jon Perryman

unread,
Aug 17, 2023, 1:04:13 AM8/17/23
to golang-nuts
Do you feel your GOLANG API implementations allows your API's and functions to evolve and grow? Personally, positional args has pissed me off for years when a proven simple solution has never been adopted by most Unix programming languages (except Javascript). Most notably, it's missing from GOLANG.  

Everyone here understands and uses os.open from the os package.  For argument's sake, let's say os.open() is your responsibility to integrate nosql, memory files, compression, encryption, btree, key indexed files and more. How do you modify os.open( ) to integrate these file related features? This was solved years ago in languages not used in Unix using keyword arguments that also included positional. For example:

func os.open(name string, memoryfile= bool, compress= bool, btree{ btree_optons string }, encrypt{ key= string }, nosql{ nosql_options string } ) (*File, error)
os.open('myfile.txt', encrypt{ key='abc' }, compress=true)

The os.open args 1, 3 and 5 would be set from the specified arguments.

 Is this something that others need and I should pursue or should I just forget it? Proposal https://github.com/golang/go/issues/62078 was closed with "I don't see anything concrete being proposed here.". If I should pursue this, should I reword it or reduce it to this Email?

Thanks, Jon.

Kurtis Rader

unread,
Aug 17, 2023, 1:14:39 AM8/17/23
to Jon Perryman, golang-nuts
Personally, and I say this as a happy user of Python, I dislike keyword parameters. Note that in Python keyword parameters are (or should be) seldom used for anything other than optional arguments. And if your API has so many parameters that they need names the API probably needs refactoring. Alternatively, pass a struct whose contents can be initialized using the struct member names.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAByJhJnkuai27VNiE6PraU9-5hoO85Hm__0UQJrT75a7KqD8uw%40mail.gmail.com.


--
Kurtis Rader
Caretaker of the exceptional canines Junior and Hank

Jon Perryman

unread,
Aug 17, 2023, 1:44:47 AM8/17/23
to Kurtis Rader, golang-nuts
Struct does not solve the basic problem. In what way are you suggesting to solve the described os.open() changes? Should each API be seperate from os.open where it must be used with every read/write? 

Axel Wagner

unread,
Aug 17, 2023, 4:15:24 AM8/17/23
to Jon Perryman, Kurtis Rader, golang-nuts
Have a look at net.Dialer. It is essentially a struct that adds optional, keyword arguments to net.Dial.

Kurtis Rader

unread,
Aug 17, 2023, 5:17:26 AM8/17/23
to Jon Perryman, golang-nuts
On Wed, Aug 16, 2023 at 6:44 PM Jon Perryman <jon.pe...@gmail.com> wrote:
Struct does not solve the basic problem. In what way are you suggesting to solve the described os.open() changes? Should each API be seperate from os.open where it must be used with every read/write? 

I guess I don't understand what you are proposing since the `os.open()` API cannot be changed without breaking the Go backward compatibility guarantee. If you are proposing a replacement to `os.open()` that is more flexible that has optional arguments then I would argue a struct argument is the way to go (pun intended). You seem to be arguing, imprecisely, for the Go language to support changes to a public API that allows introducing new behavior without breaking backward compatibility. Adding keyword arguments does not solve that problem and your example of extending `os.open()` is nonsensical.

Jon Perryman

unread,
Aug 17, 2023, 5:32:46 AM8/17/23
to Axel Wagner, Kurtis Rader, golang-nuts
The net.dialer solution you mention uses a struct which does not simplify. How does this get programmers out of the add another function mentality? GOLANG and C/C++ programmers have the same solution because it's not convenient to use a struct. Compare charts in C++ versus JavaScript. C++ solution chose to implement 1,000 functions instead of using the struct as you suggest. JavaScript looked to the future and implemented it using the method that I'm proposing for GOLANG. The method I'm suggesting is so easy and convenient that people use it as seen with chartjs.

Ask yourself why os.open() has remained unchanged since the beginning instead of expanding to include new features. Adding new features is extremely inconvenient. Using a struct is inconvenient.  Let's just add more functions.

Axel Wagner

unread,
Aug 17, 2023, 7:35:41 AM8/17/23
to Jon Perryman, Kurtis Rader, golang-nuts
The reason `os.Open` has not changed is because it doesn't have to change. None of the features you mention really make sense for what it does. At least that would be my interpretation. If you want to support your interpretation, I would suggest digging up proposals to add those features which got rejected because we didn't want to add more functions. That would show that a lack of keyword arguments is to blame for a lack of `os.Open` evolution, instead of a lack of need for evolution.

On the other hand, `net.Dial` empirically shows that it *is* possible to use this approach to not add more functions, while expanding functionality. Pre Go 1.0 there was only net.Dial. For Go 1.0, we determined that we would want to be able to specify timeouts, so we added net.DialTimeout. Then, for Go 1.1, we also wanted to specify a local address to use. However, it became clear that it is not sustainable to add more and more versions of a `Dial` function, so net.Dialer was added in Go 1.1. Since then, we have added many more options to it. As adding fields to a struct is backwards-compatible, we can add as many options as we like, while still maintaining compatibility and not adding new package-scoped API surface or functions.

The actual history of `net.Dial` strongly implies that if we *wanted* to evolve `os.Open`, then what we would do is add a new struct type `os.Opener`, with fields for all these optional features, which would then have an `func (*Opener) Open(name string) (*File, error)` method. It's not a perfect mechanism, but so far, it seems to have sufficed.

To be clear, if you feel strongly that we should support keyword arguments, you can write and file a proposal to that effect. All I can say is that in the past, this has come up repeatedly, but obviously has not been accepted. So your case should better be strong - and in particular, it should acknowledge the evidence and history we've built in over a decade. And you might ultimately save yourself some frustration by instead adopting the imperfect solutions we do have.

Peter Herth

unread,
Aug 17, 2023, 9:34:57 AM8/17/23
to Jon Perryman, golang-nuts
I think the omission of keyword parameters in Go is a weakness. In many cases, keyword parameters are a simple way of creating APIs, which depend on a lot of possible parameters, of which most are not necessarily specified. Their omission is especially ironic, as there is a strong push to initialize structs only via using the keyword parameter syntax. And the reasons for that are very good. So when we have a nice system - which essentially is just syntactic sugar at the call site - for structs, why can't we have the same system for functions? Like with structs, it should be mostly a syntax for calling functions. They should probably be able to specify which parameters are positional and which can be specified by keyword parameters. 
Of course you can do the common "trick" via generating a struct which allows the keyword syntax for creation, but I think it would be a good addition to not need that indirection.



--

Dan Kortschak

unread,
Aug 17, 2023, 10:13:55 AM8/17/23
to golan...@googlegroups.com
On Thu, 2023-08-17 at 11:34 +0200, Peter Herth wrote:
> I think the omission of keyword parameters in Go is a weakness. In
> many cases, keyword parameters are a simple way of creating APIs,
> which depend on a lot of possible parameters, of which most are not
> necessarily specified. Their omission is especially ironic, as there
> is a strong push to initialize structs only via using the keyword
> parameter syntax. And the reasons for that are very good. So when we
> have a nice system - which essentially is just syntactic sugar at the
> call site - for structs, why can't we have the same system for
> functions? Like with structs, it should be mostly a syntax for
> calling functions. They should probably be able to specify which
> parameters are positional and which can be specified by keyword
> parameters. 
> Of course you can do the common "trick" via generating a struct which
> allows the keyword syntax for creation, but I think it would be a
> good addition to not need that indirection.

A significant problem with additions like this is that people would use
it. kwargs-rich functions enable overly complex APIs. I'm very glad Go
doesn't have them.

Jason Phillips

unread,
Aug 17, 2023, 3:32:20 PM8/17/23
to golang-nuts
Even if we assume that the addition of keyword arguments would be a positive for the Go language and ecosystem, it wouldn't be a backward compatible change to add a keyword argument unless we make additional changes to the language to support implicit conversions between function-with-keyword types. For example, a completely valid way to use os.Open today would be to pass it into a function as an argument:

  func DoThing(open func(string) (*os.File, error)) {
    f, err := open("foo.json")
    // etc
  }
  ...
  DoThing(os.Open)

How does the above code work after adding a new keyword argument to os.Open? If a new non-keyword argument was added, this would clearly be a backward incompatible change today. How would I implement DoThing such that I _can_ use new keyword arguments?

Any real language change needs to precisely define what happens in the above cases, and more. So, if you're serious about such a proposal, you need to state the exact changes you're proposing to the language specification, the expected impact on the language implementation(s), and have some evidence that the proposed changes are worth the effort and are better than the alternatives.
Reply all
Reply to author
Forward
0 new messages