On Thu, Mar 9, 2017 at 1:03 PM, Sam Duke <[email protected]> wrote:
> Thanks so much for the reply Kenton :) I've inlined as you've covered a lot > > On Thursday, 9 March 2017 20:49:49 UTC, Kenton Varda wrote: >> >> Hi Sam, >> >> Ross mostly covered this, but I'll give an official response as the >> author: >> >> Cap'n Proto has "presence", including hasX() accessors, for pointer types >> (structs, lists, text, data; anything that is variable-size) but not for >> primitives (integers, floats, bools). >> > Does this include arrays? (proto3 does not, so there is no workaround) > Yes, "list" and "array" are the same thing in Cap'n Proto. Note that protobuf actually never had a notion of presence for arrays (repeated fields) -- a zero-sized array was indistinguishable from an unset array. Cap'n Proto, OTOH, actually can distinguish between a null pointer an an empty array. I find that many cases where I at first think I need field presence >> actually make more sense as a union -- I find that, surprisingly often, >> it's not just that the field is optional, but that there are several >> different conceivable "modalities" of the struct, where the field only >> makes sense in one of them. It's nice to encode this explicitly, and Cap'n >> Proto can then reuse space in the struct for mutually-exclusive fields. >> > > As mentioned, I'm coming more from the angle of writing defensively. I > might not ever *want* to communicate an 'unset' case, I just want to detect > it and fail gracefully, early and safely. (i.e. I would want to union wrap > EVERY primitive field) > Hmm. If your intent is to "fail" if the field isn't set, then you've made a backwards-incompatible change to your protocol -- equivalent to defining a whole new protocol entirely. The right way to detect this is for the client to declare upfront what protocol (or protocol version) it is expecting and for the server to fail if the protocol isn't supported. (E.g. in HTTP you cat use the Content-Type and Accept headers for this sort of negotiation.) Assuming the client has claimed it is speaking the correct protocol, I would encourage you not to worry about whether the client has filled in every "required" field. This is unnecessary error detection. Keep in mind that a buggy client could just as easily fill in garbage values rather than omit the values, and thus pass your checks while still sending invalid data. So, *if* you are only checking presence so that you can fail if the fields aren't set, I'd say don't bother. Define default values and go with them. The only time you really need to detect presence is if omitting the field is NOT an error, and if the resulting behavior should be different than any default value might express. Finally, note that I would like to add a concept of "Maybe(T)" in the >> future, to explicitly state that the presence of absence of a field >> matters. I had intended to use this specifically for pointer types -- the >> effect would be that the `getX()` accessor would return a >> language-appropriate "Maybe" type (e.g. kj::Maybe<T> in C++), and then we >> could deprecate the `hasX()` accessors. I hadn't really thought about >> whether we should support Maybe(T) for primitives, which would require >> allocating an extra bit as described above (and would not be >> wire-compatible with the non-Maybe type, whereas for pointer types it would >> be; this might get confusing). >> > > The support of generics in Cap'n Proto looks like it would lend itself to > this well. A firm thumbs up from me for this (including primitives) :) > Note that generics in Cap'n Proto only allow you to parameterize pointer types, not integers, kind of like Java generics (and for much the same reasons). Also, note that boxing all your field values in their own structs would be very inefficient. -Kenton -- You received this message because you are subscribed to the Google Groups "Cap'n Proto" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. Visit this group at https://groups.google.com/group/capnproto.
