On Nov 1, 2010, at 11:32 AM, Eric MSP Veith wrote: >> >> I expect Ruby to be about the same: DWIM. > > As far as I am concerned, at least the Ruby bindings will be so not DWIM. > I.e., I don't plan on creating RPM::solve_my_problem(). This is for pure > egoistic reasons: I don't want to be held responsible if/when something > breaks silently with the bindings involved because there was no exception > thrown. >
I wasn't so much referring to RPM::solve_my_problem() as DWIM, but rather trying to point out that, say, rubyists have certain innate expectations, perhaps the most important being that type coercion is _ALWAYS_ performed. As a C programmer, I _EXPECT_ my program to segfault when I pass a NULL pointer, or pass an int where a long or long long should have been used. DWIM == "Have it your own way!" and implicit type coercion's and Just Works are the tyranny of writing bindings (in C) for all the widdle interpreters. >>> What about either adding an rpmRC* error to the method signatures of >>> doDefine & Co, or changing their signatures to return the rpmRC, and >>> making the parse address one parameter? >> >> And here the issue is API/ABI: If the library API/ABI changes >> in any way at all, then all that happens is lusers start chanting >> RPM has no stable API/ABI! > > I'd happily add wrapper functions/defines to address backwards compatibility > and plaster them also quite appily with big @deprecated warnings all over > the place. ;-) > @deprecated isn't all that useful: there are places that RPM has marked something as @deprecated for *years* that _STILL_ need to be carried around exactly as always for various reasons. rpmArchScore() instantly comes to mind. RPM itself has _NEVER_ used that functionality, and carrying around the method assumes that architecture compatibility can actually be mapped into integers meaningfully in the "real world". (aside) The mapping is feasible. The flaw is that "arch" is an open ended set: add a new architecture (or rename an architecture) and the mapping instantly breaks. ymmv, good luck! >> Meanwhile, rpmExpand et al have almost nothing important to do with >> "package management". > > Sure, but I'd like to get the small things right nontheless. I.e., signal a > Rubyist that 'f' isn't a valid name for a macro. > Well you don't _HAVE_ to rely on the error code. You could just pre-process the arguments for "sanity", the rules for macro names are dirt simple ... ... and because of implicit type coercion and unwrapping you almost certainly have to pre-process the inputs anyways. Validating a couple more rules just isn't as hard as retrofitting error returns and exception handling in rpmlib _EVERYWHERE_. >> Meanwhile the important issue is _NOT_ what rpmlib returns, but rather >> ensuring that the design of the ruby bindings is architecturally correct. >> >> In C, its a very common paradigm to do: >> if (someRoutine(..)) >> fprintf(stderr, "Danger Will Robinson! Error! Error! Error!\n); >> That C paradigm just doesn't fit into most bindings, which (if >> intelligently designed) usually return "self" or "this" so that methods >> can be recursively nested like >> >> fooClose( fooRead( fooOpen("/some/file", ...) ...) ...) >> >> Focus on the ruby binding design, exceptions (or mappings to NIL or NULL >> or EMPTY) can be arranged whenever you are sure that you have a >> tasteful/intuitive/aesthetic ruby binding paradigm. > > That's why I was asking for return codes. E.g., defining a macro with a name > that's less than 3 characters long should throw an exception. Currently, the > bindings code has no way to catch that error since the RC of the > corresponding macro C function is either not there (i.e., void) or always 0. > RPM tends to use these return code values (in the rpmRC enum, not completely back-ported but usually used in new development if at all possible): -1 "can't happen" conditions 0 success 1 not found 2 failure (aside) There are a few other rpmRC codes, all related to pubkey security ritual fetishisms, that should _NOT_ have been added to the rpmRC enum: the RFE came in at the last possible moment just before going "gold" in RHL 8.0 (iirc) and nothing else could be done because of "No time!". The real flaw is/was "No design!" and organically grown "weeds" in the code base. Oh well ... And most definitely what should NOT be done is to re-create a huge pointless mapping of error codes/names/messages that has to be maintained. In fact RPM had that mapping originally, utterly useless, took years to carefully pull out the uselessness and get back to the simplicty of RPMRC_OK RPMRC_NOTFOUND RPMRC_FAIL Strings, not Yet More stoopid enumerations, are what is needed, with some simple rules on how the string should be constructed like syslog(3), are simplest for passing to applications/bindings. >> That's one approach. There are others. But returning rpmRC for macros in >> ruby is gonna have a ripple effect everywhere that is quite costly to >> stabilize. > > Nay, only in the Ruby bindings *C* code. I.e., translate the return code of > e.g. rpmDefineMacro into something that is to be expected in that language > (be it an exception or something else). The rest of the code can continue to > do (void)rpmDefineMacro(...) as it's done now. The API already has the > return code in the function signature, it just isn't used right now (at > least in the macro code). > You are correct that a consistent approach to bindings is absolutely needed. However return codes just ain't the hard part. These days, objects and iterators and yield and sets and getting implicit type coercion in place and ... are where the real need is. But absolutely consistent paradigms makes binding development easier, and leads to maintainable bindings. Return codes are just the beginning of the binding puzzle(s) ______________________________________________________________________ RPM Package Manager http://rpm5.org Developer Communication List rpm-devel@rpm5.org