2 ms·
I've re-read everything you've written so far, and I think we're just in violent agreement. It would have helped if you provided some explanatory code, but the
by kbolino 2y ago
I've re-read everything you've written so far, and I think we're just in violent agreement. It would have helped if you provided some explanatory code, but the word "middleware" in your original post (which may have been edited in? if not, sorry, that's on me) clarifies a lot for me.
If you do need to == or type-assert the options, then don't make them functional. That seems to be what you were saying with `type thearg string` earlier. However, I think my original example with an interface illustrated another/better way to solve the same problem: make the options self-describing.
- Groxx 2y agoSort of. My issue with using closures as your functional option implementation type (i.e. "functional options" is "call this function to get an opaque arg" which does not imply that you need to use a closure, it's just a common implementation strategy) is that when a library does it, it prevents anyone from writing middleware that is interested in argument equality. Among other useful desires. That's quite common in my experience, and working around it on the library-user side is rather painful, as it often requires reimplementing roughly the entire API so it can be controlled. The alternative is to have your return type be an opaque interface, which can have any implementation (including closures): type Option { apply(...) // privately implementable only // or just have an empty `private()` or something } type someoption string func (s someoption) apply(...) { // whatever is needed, it can be changed any time } func SomeOption(val string) Option { return someoption(val) } wrap(thing, SomeOption("arg")) ^ in this, the wrapper can check if options include `SomeOption("arg")` if that becomes useful for some reason. Quite often that reason is "tests", but I do keep running into other scenarios where it'd be useful too. I've helped multiple people work around it by reflecting on the function's signature, constructing the private arg type, calling the func, and comparing the mutated private apply-arg-type to a known value, but this isn't always possible and those cases are stuck either not doing the thing they wanted, or writing tons of code to wrap the types completely. Using a more concrete type also logs/prints/debugs usefully by default in most cases, giving you `someoption{"arg"}` instead of `(fntype)(&0x3768dh893)`. As a library author you generally cannot predict this kind of need, and using function closures is by far the least flexible and least-user-friendly option for your users. So I recommend not doing that.