Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: Go 2: default values for named return parameters #44396

Closed
qexk opened this issue Feb 18, 2021 · 3 comments
Closed

proposal: Go 2: default values for named return parameters #44396

qexk opened this issue Feb 18, 2021 · 3 comments
Labels
Milestone

Comments

@qexk
Copy link

qexk commented Feb 18, 2021

Would you consider yourself a novice, intermediate, or experienced Go programmer?

Experienced.

What other languages do you have experience with?

Many functional programming languages, C, Perl, JS/TS, and lots of others.

Would this change make Go easier or harder to learn, and why?

This would add a bit of complexity, but it wouldn’t make Go any harder to learn because novice developers don’t use named return parameters that often.

Has this idea, or one like it, been proposed before?

I didn’t find anything.

Who does this proposal help, and why?

It helps developers and reviewers understand what value will be returned by a function most of the time.

What is the proposed change?

Go has the ability to give names to return parameters. It is a great feature, as it gives some kind of documentation to the reader, and allows developers to better clarify their intent if they’re writing a long function.

However, named return parameters are always zero initialised. Although this is great for consistency, I feel like an explicit default value can help in readability.

func Function() (state int := 2, err error) {
	...
}

Think of it as the default case of a switch. It could also represent a contract with a default value if the function succeeds, and that contract can be understood just by reading the function’s prototype.

Other syntax proposals:

  • the parameter’s type could be inferred, but I find it harder to read
    func Function() (state := 2, err error) {
    	...
    }
  • the operator used could be a simple =, like a const definition:
    func Function() (state int = 2, err error) {
    	...
    }

There should be restrictions on the type of expression you can write. This shouldn’t be allowed IMO:

func Function() (state int := func() int {
	return 12
}(), err error) {
	...
}

Maybe allow only const expressions or a single variable name?

Is this change backward compatible?

This change is backward compatible.

Show example code before and after the change.

Here’s the piece of code that gave me the idea for this proposal (this function represents a state of a parser):

func pRaw(p *parser) (nextState stateFn, err error) {
	switch p.item.Typ {
	case lexer.ItemRaw:
		p.raw.WriteString(p.item.Val)
		nextState = pRaw

	case lexer.ItemSep:
		p.pushRawIfAny()
		p.pushSeparator()
		nextState = pRaw

	case lexer.ItemLacc:
		p.pushRawIfAny()
		nextState = pExprBegin

	case lexer.ItemEOF:
		p.pushRawIfAny()
		nextState = nil

	default:
		err = UnimplementedError{p.item, "pRaw"}
	}
	return
}

This function could be rewritten as:

func pRaw(p *parser) (nextState stateFn := pRaw, err error) {
	switch p.item.Typ {
	case lexer.ItemRaw:
		p.raw.WriteString(p.item.Val)

	case lexer.ItemSep:
		p.pushRawIfAny()
		p.pushSeparator()

	case lexer.ItemLacc:
		p.pushRawIfAny()
		nextState = pExprBegin

	case lexer.ItemEOF:
		p.pushRawIfAny()
		nextState = nil

	default:
		err = UnimplementedError{p.item, "pRaw"}
	}
	return
}

Here, I understand that the next state of the parser is likely going to be pRaw.

What is the cost of this proposal? (Every language change has a cost).

This proposal would affect a lot of tools, but the implementation cost isn’t big.

The compile time cost should be negligible.

No runtime cost.

Can you describe a possible implementation?

I made a quick & dirty proof of concept here.

How would the language spec change?

The Signature section of the language spec should be the only one affected by this proposal.

Orthogonality: how does this change interact or overlap with existing features?

This extends the named return parameter feature.


Thank you for reading this proposal. This can seem useless, as one could just assign to the return parameter on the first line, but I think the readability is worth it.

@gopherbot gopherbot added this to the Proposal milestone Feb 18, 2021
@seankhliao seankhliao added v2 A language change or incompatible library change LanguageChange labels Feb 18, 2021
@ianlancetaylor
Copy link
Contributor

It seems hard to explain why result parameters can have default values but ordinary parameters can't.

Why not just make the first statements of the function assignments to the result parameters?

@ianlancetaylor
Copy link
Contributor

Based on the (lack of) discussion above, and the emoji voting, this is a likely decline. Leaving open for four weeks for final comments.

@ianlancetaylor
Copy link
Contributor

No further comments.

@golang golang locked and limited conversation to collaborators May 4, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

4 participants