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

strings: add First function? #14423

Closed
abbgrade opened this issue Feb 20, 2016 · 4 comments
Closed

strings: add First function? #14423

abbgrade opened this issue Feb 20, 2016 · 4 comments

Comments

@abbgrade
Copy link

Hi,

i would like to have a string.coalesce function, that returns the first not empty string.
I think, it's an clean solution for realizing default values.

It exists in T-SQL for example.

// returns the first not empty string of certain strings
func coalesce(values ...string) string {
    for _, value := range values {
        if value != "" {
            return value
        }
    }
    return ""
}

What do you think?

Best regards,
Steffen

@minux
Copy link
Member

minux commented Feb 20, 2016 via email

@bradfitz
Copy link
Contributor

I agree with Minux. Any addition to the std library would need to be supported with data showing that it'd help a large number of programs, including the standard library itself, and lead to more legible programs.

But I do think there are a number of funcs in various places in the standard library that would use something like a strings.First(...string) string call, so you could go search and get some data.

Here are at least two:

bradfitz@laptop go$ git grep -A 5 "func valueOrDefault"
src/net/http/httputil/dump.go:func valueOrDefault(value, def string) string {
src/net/http/httputil/dump.go-  if value != "" {
src/net/http/httputil/dump.go-          return value
src/net/http/httputil/dump.go-  }
src/net/http/httputil/dump.go-  return def
src/net/http/httputil/dump.go-}
--
src/net/http/request.go:func valueOrDefault(value, def string) string {
src/net/http/request.go-        if value != "" {
src/net/http/request.go-                return value
src/net/http/request.go-        }
src/net/http/request.go-        return def
src/net/http/request.go-}

@bradfitz bradfitz added this to the Unplanned milestone Feb 21, 2016
@bradfitz bradfitz changed the title New function string.coalesce strings: add First function? Feb 21, 2016
@abbgrade
Copy link
Author

Hi,

thanks for your feedback. I searched go/src for == "" and the first 10% of the result set contained some possible applications.

src/cmd/asm/internal/asm/endtoend_test.go:210

if codeHex == "" {
    codeHex = "empty"
}

src/cmd/cgo/out.go:316

c := t.Typedef
if c == "" {
    c = t.C.String()
}

src/cmd/cgo/out.go:631

c := t.Typedef
if c == "" {
    c = t.C.String()
}

src/cmd/cgo/out.go:1072

pkg := *importPath
if pkg == "" {
    pkg = p.PackagePath
}

src/cmd/cgo/out.go:1106

prefix := strings.Map(clean, *gccgoprefix)
if prefix == "" {
    prefix = "go"
}

src/cmd/dist/build.go:99

goroot_final = os.Getenv("GOROOT_FINAL")
if goroot_final == "" {
    goroot_final = goroot
}

src/cmd/dist/build.go:104

b := os.Getenv("GOBIN")
if b == "" {
    b = goroot + slash + "bin"
}

src/cmd/dist/build.go:110

b = os.Getenv("GOOS")
if b == "" {
    b = gohostos
}

src/cmd/dist/build.go:119

b = os.Getenv("GOARM")
if b == "" {
    b = xgetgoarm()
}

src/cmd/dist/build.go:151

b = os.Getenv("GOARCH")
if b == "" {
    b = gohostarch
}

Best regards,
Steffen

@griesemer
Copy link
Contributor

This is not an issue, this is a feature request. Please discuss this first on one of the popular Go forums (mailing list, etc.).

I agree with @minux and @bradfitz that this doesn't belong into the strings package: It's trivial to write if needed. Moreover, the examples you found are clearer as is, than with an extra function call. For instance:

b = os.Getenv("GOARM")
if b == "" {
    b = xgetgoarm()
}

would become

strings.Coalesce(os.Getenv("GOARM"), xgetgoarm())

Now a reader has to learn what Coalesce means (and it doesn't seem a very good name for the functionality either). Also, the 2nd argument always has to be evaluated (and in this case called) even if not needed (possibly an expensive operation). Finally, invoking a variadic function (...) requires allocation and population of a slice. If the pattern

s = a
if s == "" {
   s = b
}

is very common in a package it's trivial to define

func nonempty(a, b string) string {
   if a != "" {
      return a
   }
   return b
}

which doesn't allocate a slice. It's also easy to see locally what it does.

The functionality is simply too simple to warrant inclusion in strings. Or, looking from the other perspective: If we add this to strings, where do we say no?

Closing.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants