Hacker News new | ask | show | jobs
by hactually 2375 days ago
Do you have an example where that's the case?
2 comments

One easy example is map functions.

In typescript, if I have a bunch of "User" objects where each user has an "name" and "age" field, and I want to print a comma separated list of all those names formatted as "name -- age", it's simple. I write:

    let userNamesList = let userNames = users.map(u => `${u.name} -- ${u.age}`).join(", ")
    console.log(userNamesList).
This is possible in no small part because map is generic.

In go, to get the same level of expressiveness, I'd have to write the following stuff around it:

    func mapUsersToStrings(f func(u User) string, users []User) []string {
        result := make([]string, len(users))
        for i := 0; i < len(users); i++ {
            result = append(result, f(users[i]))
        }
    }
And after writing that boilerplate, I can finally write:

    userNamesList := strings.Join(mapUsersToStrings(func(u User) string { return fmt.Sprintf("%s -- %d", u.name, u.age) }), ", ")
That boilerplate, of having to write a specialized map/filter/etc function with a for loop for every combination of types you transform between (mapUsersToStrings, mapUsersToAddresses, mapUsersToAges) is really annoying.

It's harder to point to many other cases because, simply enough, people don't write such cases. The fact of the matter is just that go libraries make very sparing use of first-class functions because the lack of generics prevents it from working well, and so we end up with an entire language ecosystem where code is harder to read and with fewer simple abstractions reused across it.

You can still write any code without good generics or first-class functions, you'll just have more programmers writing more code with less clean abstractions.

map, filter, fold, etc.