From mboxrd@z Thu Jan 1 00:00:00 1970 From: Nick Dokos Subject: Re: Elisp programming style Date: Fri, 28 Oct 2011 10:31:26 -0400 Message-ID: <18647.1319812286@alphaville.dokosmarshall.org> References: <86obx2gvmd.fsf@googlemail.com> <8762j94dz0.fsf@gmail.com> <86obx1qkcc.fsf@googlemail.com> Reply-To: nicholas.dokos@hp.com Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Return-path: Received: from eggs.gnu.org ([140.186.70.92]:43941) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RJnT1-0005qx-4d for emacs-orgmode@gnu.org; Fri, 28 Oct 2011 10:31:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RJnSz-0004zm-I5 for emacs-orgmode@gnu.org; Fri, 28 Oct 2011 10:31:31 -0400 Received: from g5t0008.atlanta.hp.com ([15.192.0.45]:20492) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RJnSz-0004zf-BJ for emacs-orgmode@gnu.org; Fri, 28 Oct 2011 10:31:29 -0400 In-Reply-To: Message from Thorsten of "Fri\, 28 Oct 2011 16\:09\:07 +0200." <86obx1qkcc.fsf@googlemail.com> List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: Thorsten Cc: nicholas.dokos@hp.com, emacs-orgmode@gnu.org Thorsten wrote: > =C5=A0t=C4=9Bp=C3=A1n N=C4=9Bmec writes: >=20 > > 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. >=20 > The problem can be described easily:=20 >=20 > problem-specific helper-funcions (some redundancy avoided) > ,----------------------------------------------------------- > | (defun main-function (args)=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20 > | (let ((var (assoc :key1 args))) ; extracting var once > | ...=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20 > | (helper-function1 ...) ; inside let using var=20=20=20=20=20=20=20=20= =20=20=20=20=20 > | (helper-function2 ...) ; inside let using var=20=20=20=20=20=20=20=20= =20=20=20=20=20 > | ))=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20 > |=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20 > | (defun helper-function1 ()=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20 > | ...=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20 > | )=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20 > |=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20 > | (defun helper-function2 ()=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20 > | ...=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20 > | )=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20 > `----------------------------------------------------------- >=20 You probably need let* though. > vs >=20 > standalone helper-functions (but redundancy) > ,------------------------------------------------------------- > | (defun main-function (args)=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20 > | (let ((value (assoc :key1 args)) ; extracting var 1st time > | ...=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20 > | )=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20 > | (helper-function1 ...) ; outside let=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20 > | (helper-function2 ...) ; outside let=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20 > | )=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20 > |=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20 > | (defun helper-function1 (args)=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20 > | (let ((var (assoc :key1 args))) ; extracting var 2nd time=20=20 > | ...=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20 > | ))=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20 > |=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20 > | (defun helper-function2 (args)=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20 > | (let ((var (assoc :key1 args))) ; extracting var 3rd time=20=20 > | ...=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20 > | ))=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20 > `------------------------------------------------------------- >=20 >=20 > > 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. >=20 > 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.= =20 > 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 real= ly specific etc. > Would that be considered bad style from the original author, or is that > up to personal choice and not considered a problem? >=20 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