On Wed, Dec 7, 2022 at 4:39 AM Brian Candler <b.cand...@pobox.com> wrote:

> On Tuesday, 6 December 2022 at 21:05:48 UTC dple...@google.com wrote:
>
>> I am trying to figure out if there's a good way to build a helper that
>> can be used against different sets of nested types that have a common
>> structure.
>>
>> So, for example, say there are two libraries, `lib1` and `lib2` and both
>> define types Foo, Bar, and Baz with:
>>
>> type Foo struct { ... }
>> type Bar struct { ... }
>> func (b *Bar) GetFoo() *Foo { ... }
>> type Baz struct { ... }
>> func (b *Baz) GetBar() *Bar { ... }
>>
>> But `lib1` and `lib2` both define different additional methods on some of
>> these structs, so I can't just merge them into a single library.
>>
>
> It seems to me that lib1.{Foo,Bar,Baz} and lib2.{Foo,Bar,Baz} are
> completely different types.  They just happen to have similar names.
>
> Hence I ask, what's the commonality that you're trying to expose?  If it's
> that both lib1.Baz and lib2.Baz have a GetBar() method, then that sounds
> like an interface - except if one returns a lib1.Bar and the other returns
> a lib2.Bar, then they are not the same interface at all, so you're back to
> "these are completely different types".  Is there something common in Foo ?
>
<snip>

Why not just have HelperFn1(lib1.Baz) and HelperFn2(lib2.Baz)?
>

My actual use case involves a code generator, where lib1 and lib2 (and
possibly dozens of additional libraries) are all outputs of the same
generator with slightly different arguments, generated by various different
teams and therefore entirely outside of my control.

The generator in question reads a schema file and outputs a library of Go
structs for all the data types defined by the schema. There are more than a
thousand such data types; they have getters and setters for their
attributes, and they're all nested in a giant tree, so e.g. code could call

root := &lib1.Root{}
root.GetFoo().GetBar().GetBaz().GetQux().GetFleem().SetName("hello")

The problem is that various users of the code generator have their own
schemas, which are generally made by taking a common standard schema and
adding extra fields needed by whatever specific project the users are
working on. So for example one project might add a .GetSpoo() method to the
Foo type, while another adds GetAlias to Fleem, etc.

What I really want to do is be able to write a helper like:

package examplehelper

func SetFleemName(root ???, name string) {
    root.GetFoo().GetBar().GetBaz().GetQux().GetFleem().SetName(name)
}

such that any project can have its own generated library and can call
`examplehelper.SetFleemName(root, "foo")` on a Root{} from their own
generated library, as long as the Root has GetFoo(), the Foo has GetBar(),
etc. down to the Fleem having a SetName(string).

This is technically possible with generics, but not practical, because it
requires writing e.g.:

x := lib1.Root{}
helper.SetFleemName[*lib1.Fleem, *lib1.Qux, *lib1.Baz, *lib1.Bar,
*lib1.Foo](x, "foo")

and in my real use case that list of type parameters would have more than a
thousand types in it.

Right now I'm experimenting with whether it's reasonable to use code
generation to solve this - a code generator could either just copy a helper
library and replace all the imports with a specific generated library, or
could build a generated-library-specific "bridge" library that defines a
bunch of

var SetFleemName = generichelper.SetFleemName[*lib1.Fleem, *lib1.Qux, ...<a
thousand more types>]

But there's a lot of overhead to having everything go through a generator,
and it makes the code harder to read, harder to debug, and harder to use in
IDEs. I am hoping that there's some Golang feature I'm just not aware of
that would allow me to do this in the language itself, but I haven't been
able to find one so far.

Thanks,
Dan

-- 
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+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAAViQtgco5qCX%3DLrTcaJ0q2VnuixwYBk-KcCuyoO5XPPSMpufQ%40mail.gmail.com.

Reply via email to