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: text/template: add nil literal #57773

Closed
willfaught opened this issue Jan 13, 2023 · 5 comments
Closed

proposal: text/template: add nil literal #57773

willfaught opened this issue Jan 13, 2023 · 5 comments
Labels
Milestone

Comments

@willfaught
Copy link
Contributor

It's counterintuitive to initialize variables that will eventually hold a map or slice value with false or an empty string.

For example:

{{ $map := false }} // Looks like an error
{{ if .foo }}
  {{ $map = .foo.configMap }}
  {{ $map.baz }}

More intuitive:

{{ $map := nil }} // Looks correct
{{ if .foo }}
  {{ $map = .foo.configMap }}
  {{ $map.baz }}

A nil literal would also enable testing for zero values exactly instead of falsey values more broadly:

{{ if $foo }} // If any truthy value
{{ if ne $foo nil }} // If not nil

I couldn't find a previous proposal for this, open or closed.

@gopherbot gopherbot added this to the Proposal milestone Jan 13, 2023
@ianlancetaylor
Copy link
Contributor

CC @robpike

@robpike
Copy link
Contributor

robpike commented May 11, 2023

There is a difficult technical problem here, perhaps best explained by comparing how constants work in templates and the Go language itself. In Go, there is the notion of an "untyped constant", which is promoted to an actual type only when assigned to a variable. This is a powerful idea and one I think is underappreciated. When building the template library, I tried to reproduce this but it's nigh on impossible as there is no actual type system yet things must immediately go into a data structure upon parsing. Templates can go only as far as the syntax allows: 0 becomes an int, 0.0 becomes a float64, and so on. Often but not always one can adjust the type to for instance promote 0 to float64 or MyInt as an argument to a function, but that's about it. In the first example above, the apparently untyped constant "true" is immediately coerced to a bool, because that's what a "true" value is, just as 0 is an integer. In short, the assignment that determines the type of a constant happens immediately; it cannot be deferred as we need to store it somewhere.

For nil it's harder, because nil can be essentially any non-value type. To put a nil into a data structure, one must know the type it has, but there is no type information or, as with numbers or true/false, any syntax to guide you. There may well be a way to do this, but it would require someone to redesign the whole balance of parser and execution engine, and that's not going to happen.

Closing as infeasible.

@willfaught
Copy link
Contributor Author

@robpike Why not use the type interface{}? That's how I assumed it would work.

@rsc
Copy link
Contributor

rsc commented May 17, 2023

This proposal has been declined as infeasible.
— rsc for the proposal review group

@timdadd
Copy link

timdadd commented Apr 21, 2024

As far as I can see anything can change type in a template. There is no type checking, so really you can point it to any nil pointer and it would work. This code is valid, but $pl is either string or struct so later test is complex.
{{- $pl := ""}}{{- with $.processLibrary}}{{if eq x y}}{{$pl = .}}{{end}}{{end}}

So it's a slightly weak argument to worry about the type as the templates seem more interpretive than GO compiled

I use a simple template function null that just returns nil and it's the same result
func null() interface{} { return nil }

This solution is better than above as a test can be made to see if the variable is set. You can't easily do this if $pl is a string and then a struct
{{- $pl := null}}{{- with $.processLibrary}}{{if eq x y}}{{$pl = .}}{{end}}{{end}}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Declined
Development

No branches or pull requests

6 participants