-
Notifications
You must be signed in to change notification settings - Fork 50
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
Introduce fluent.Reflect convenience functions. #81
Conversation
I haven't filled out the reflect switch completely for all scalar types yet, but that's a SMOP. The recursive bits appear to all be in place and working correctly. The bigger question is: do we actually want to carry something like this? Does it belong in this package? Etc. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is useful, and we should use it for quick demos. We would end up with three ways for Go devs to build nodes:
- fluent's Reflect, which is easy and intuitive, but pretty expensive.
- fluent's Build*, which is a bit more verbose but more powerful.
- ignoring fluent and using ipld straight away. the most low level, so the most verbose but also the most efficient.
Ideally we'd eventually keep only 2 ways to build nodes, one high-level and one low-level. But for now, I think three is reasonable given that the first two are in the fluent package. |
There has also been the idea of having a whole "bind.Node" package which could handle more complex and configurable relationships to go native types using reflection. (Perhaps using something like refmt's atlases for configuration, or perhaps using tagging conventions.) That's probably a different beast, though, simply because it's a significantly bigger endeavor than this. |
I'll leave it to you to merge, by the way. |
5ac3fde
to
9dbb1ed
Compare
I still need to give this another pass and make sure all the switches covers all the cases for |
I've added more cases for all the other primitives that are reasonable to convert, which makes this about ready to merge. @mvdan, are you familiar with the reflection rules about exported fields? I was going to make a test for pointers, but got an odd error from it; something like ->
... caused me to receive the panic "reflect.Value.Interface: cannot return value obtained from unexported field or method", which... doesn't really make any sense to me. The same setup without the |
9dbb1ed
to
cbd37f8
Compare
Also raises the question of what we should do on unexported fields. I think the panic may actually be fine, given that this is supposed to be a rough and scrappy rapid-prototyping/kludge function. Thoughts? (Needs documentation, either way.) |
I have no idea how you got that pointer error, sorry. If you can provide a reproducer, I can dig into it later today. I agree that panicking on a bad type is fine. Those should be static, so it should either always or never panic. Plus, like you say, this is a shortcut func. |
The full hunk of tests that gives me the error is: t.Run("Pointer", func(t *testing.T) {
type Zoo string
type Zar struct {
Z *Zoo
}
foo := Zoo("foo")
n, err := fluent.Reflect(basicnode.Prototype.Any, Zar{&foo})
Wish(t, err, ShouldEqual, nil)
Wish(t, n.ReprKind(), ShouldEqual, ipld.ReprKind_Map)
Wish(t, must.String(must.Node(n.LookupByString("Z"))), ShouldEqual, "foo")
}) and it's panicking from the line that's launching recursion into struct fields and attempting to unwrap with a call of The first couple things I thought might be sources of oddness were the use of a "_test" package declaration, and the declaration of types that aren't package scoped, but I tried removing both of those from play and still got the panic. At this point I'm just confused because I'm pretty sure "Z" is a capital letter (but I'm sure I'll headdesk as soon as we spot the issue...). (Also, yeah, this could be rewritten to be more efficient: flipping the |
I've also just added a bunch of docs to these methods; PTAL at that also real quick :D (I'd like to add some usage examples, too, but... I've filed #88 for what's stopping me there, and I think I am going to attack that yak-shave directly because it's come up somewhat recurringly. So examples for this feature probably won't come in this PR, but a subsequent one instead.) |
... I think this is solid enough now, actually. If there's stuff to fix, we can do fixup commits. I'm gonna merge this now. (In part also because I want to have the prettyprinter gadget I just made come downstream of this, and use the addition of examples for this feature as part of the prettyprinter PR's proof-of-concept. :)) |
This diff introduces new convenience functions into the fluent package which create Nodes by looking at data in golang native structures and flipping them into IPLD data model.
These are probably not fast, but they might be handy in debugging, putting together quick hacks, or simply for demos.