Thorsten <quintf...@googlemail.com> wrote: > Štěpán Němec <step...@gmail.com> writes: > > > On Thu, 27 Oct 2011 20:03:22 +0200 > > Thorsten wrote: > > > >> Hi List, doing some Elisp programming (in an orgmode context) > >> recently, the following question with regards to the 'accepted > >> programming style' for Elisp concerned me: > >> > >> How independent and self-sustained should helper functions be? > >> > >> I found some redundancy in elisp code, e.g. several (main and helper) > >> functions that do exactly the same thing to extract the same specific > >> args out of an argument list. My first reaction was, to factor out > >> this extraction into the main function, and then call the helper > >> functions from inside a (let ...) environment where the extracted > >> args are stored in a local variable. > >> > >> But then I recognised, that the helper functions cannot be called > >> independently anymore, but only make sense when called from this one > >> main function with its local bindings. > >> > >> Is there a kind of convention in a case like this? Like: "Make every > >> function, even a helper function, independent, and don't care about > >> redundancy"? Just being curious > > > > Too bad you didn't give any concrete examples. > > The problem can be described easily: > > problem-specific helper-funcions (some redundancy avoided) > ,----------------------------------------------------------- > | (defun main-function (args) > | (let ((var (assoc :key1 args))) ; extracting var once > | ... > | (helper-function1 ...) ; inside let using var > | (helper-function2 ...) ; inside let using var > | )) > | > | (defun helper-function1 () > | ... > | ) > | > | (defun helper-function2 () > | ... > | ) > `----------------------------------------------------------- >
You probably need let* though. > vs > > standalone helper-functions (but redundancy) > ,------------------------------------------------------------- > | (defun main-function (args) > | (let ((value (assoc :key1 args)) ; extracting var 1st time > | ... > | ) > | (helper-function1 ...) ; outside let > | (helper-function2 ...) ; outside let > | ) > | > | (defun helper-function1 (args) > | (let ((var (assoc :key1 args))) ; extracting var 2nd time > | ... > | )) > | > | (defun helper-function2 (args) > | (let ((var (assoc :key1 args))) ; extracting var 3rd time > | ... > | )) > `------------------------------------------------------------- > > > > In general, if the helper function is only used in a single place and > > isn't likely to be more generally useful, there might be no reason for > > it to be a standalone function at all (other than modular programming, > > which is always a good idea IMO). > > > > OTOH, if the helper function _is_ standalone and used in multiple > > places, then there is no "redundancy", so I'm really not sure what you > > mean. > > Is there a policy? Lets say, an org-library author thinks his helper > functions will be of no use for nobody else and designs them > non-standalone. A few years later somebody wants to write a similar > library and trys to reuse some of the old helper functions, to no avail. > No policy that I know of. It's very much a matter of taste, how complicated the functions are, whether they perform something generic or something really specific etc. > Would that be considered bad style from the original author, or is that > up to personal choice and not considered a problem? > Not a problem - you can't predict the future. You do the best you can with your current knowledge. You can always refactor in the future: that's one reason that having the source code around is important. When you refactor, you may be cursing the original author for the "bad" decicions, but c'est la vie: at least, you have chosen a system where *you* can do that and not depend on a third party: they might not even be alive, let alone willing to do what you want. Nick