From: Peter Seibel
Subject: Which style do you prefer?
Date: 
Message-ID: <m33c1aik12.fsf@javamonkey.com>
Unless I've dorked something up these two functions should be
functionally equivalent. Since this is comp.lang.lisp, I'm sure folks
have strong opinions about which style is more perspicuous. What's
your vote? Write-in candidates of your own devising also accepted.

  (defun select-single-column (db column &rest keys-and-values)
    "Select the distinct values of a single column from a set of
    rows matching the given keys."
    (let* ((selector         (apply #'selector db keys-and-values))
           (all-rows         (rows db))
           (selected-rows    (select selector all-rows))
           (selected-columns (columns selected-rows column))
           (distinct-rows    (distinct selected-columns))
           (ordered-rows     (order-by db distinct-rows column)))
      (column-values ordered-rows)))

  (defun select-single-column (db column &rest keys-and-values)
    "Select the distinct values of a single column from a set of
    rows matching the given keys."
    (column-values
     (order-by
      db 
      (distinct
       (columns
        (select (apply #'selector db keys-and-values) (rows db))
        column))
      column)))

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp

From: Duane Rettig
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <47jqmbby6.fsf@franz.com>
Peter Seibel <·····@javamonkey.com> writes:

> Unless I've dorked something up these two functions should be
> functionally equivalent. Since this is comp.lang.lisp, I'm sure folks
> have strong opinions about which style is more perspicuous. What's
> your vote? Write-in candidates of your own devising also accepted.
> 
>   (defun select-single-column (db column &rest keys-and-values)
>     "Select the distinct values of a single column from a set of
>     rows matching the given keys."
>     (let* ((selector         (apply #'selector db keys-and-values))
>            (all-rows         (rows db))
>            (selected-rows    (select selector all-rows))
>            (selected-columns (columns selected-rows column))
>            (distinct-rows    (distinct selected-columns))
>            (ordered-rows     (order-by db distinct-rows column)))
>       (column-values ordered-rows)))
> 
>   (defun select-single-column (db column &rest keys-and-values)
>     "Select the distinct values of a single column from a set of
>     rows matching the given keys."
>     (column-values
>      (order-by
>       db 
>       (distinct
>        (columns
>         (select (apply #'selector db keys-and-values) (rows db))
>         column))
>       column)))

The first style seems a little more readable to me as presented, BUT:

My "strong opinion" (especially since you are writing a book :-)
is that CL is such a fantastic language to allow so many writing
styles.  You've already gotten at least two more possible styles
in as many posts, and I suspect that given a large enough program,
you would find that no two CL programmers' styles are identical.
So many "style guides" for CL in the past have fallen on their face,
because they don't espouse good CL writing, but instead one or two
people's opinions of what good writing is.  The fierce independence
in me always says "don't fence me in".

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Toomas Altosaar
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <3ef90b62.0409221323.26a7998d@posting.google.com>
Have you taken into account aspects related to debugging?

When writing new methods my code looks like the first version with
intermediate variables all over the place. Why? So that when errors
occur I can readily see - using Backtrace - how far I got before my
luck ran out since only the processed forms are on the stack.

Once the code is stable and the bugs have migrated elsewhere do I
shorten the code into a more compact form as suggested by Bj�rn. But
hardly ever to the extreme shown in the latter version since one may
always want to place a (break) or (inspect ...) somewhere and do some
detective work.

So for me style is a function of code maturity, reliability and
perhaps most of all, the level of interesting things happening within
its scope.
From: Bulent Murtezaoglu
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <871xgu461i.fsf@p4.internal>
>>>>> "DR" == Duane Rettig <·····@franz.com> writes:
[...]
    DR> My "strong opinion" (especially since you are writing a book
    DR> :-) is that CL is such a fantastic language to allow so many
    DR> writing styles.  

It is my strong opinion too, but I am also glad I am not attempting to 
write book while holding this opinion.

    DR> ...  So many "style guides" for
    DR> CL in the past have fallen on their face, because they don't
    DR> espouse good CL writing, but instead one or two people's
    DR> opinions of what good writing is.  The fierce independence in
    DR> me always says "don't fence me in".

But there probably are clearly awful things to do.  Does "no fence" 
imply Greenblatt Code that is sometimes mentioned here is OK?  

I am not idly nitpicking, I may end up having to guide someone I got
interested in CL here, so I'd like hear more.

cheers,

BM
 
From: John Thingstad
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <opseql6bbdpqzri1@mjolner.upc.no>
On Wed, 22 Sep 2004 19:33:45 +0300, Bulent Murtezaoglu <··@acm.org> wrote:

>>>>>> "DR" == Duane Rettig <·····@franz.com> writes:
> [...]
>     DR> My "strong opinion" (especially since you are writing a book
>     DR> :-) is that CL is such a fantastic language to allow so many
>     DR> writing styles.
>
> It is my strong opinion too, but I am also glad I am not attempting to
> write book while holding this opinion.
>
>     DR> ...  So many "style guides" for
>     DR> CL in the past have fallen on their face, because they don't
>     DR> espouse good CL writing, but instead one or two people's
>     DR> opinions of what good writing is.  The fierce independence in
>     DR> me always says "don't fence me in".
>
> But there probably are clearly awful things to do.  Does "no fence"
> imply Greenblatt Code that is sometimes mentioned here is OK?
>
> I am not idly nitpicking, I may end up having to guide someone I got
> interested in CL here, so I'd like hear more.
>
> cheers,
>
> BM
>

Not sure I understand what you mean. CL is a multi paradigm language.
That does not mean you can't enforce programing using a given style.
For functional programming with macros and closures I recommend Paul  
Graham's book's.
For object oriented programming I recommend Peter Seibel's book.

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
From: Duane Rettig
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <4isa57mfa.fsf@franz.com>
Bulent Murtezaoglu <··@acm.org> writes:

> >>>>> "DR" == Duane Rettig <·····@franz.com> writes:
> [...]
>     DR> My "strong opinion" (especially since you are writing a book
>     DR> :-) is that CL is such a fantastic language to allow so many
>     DR> writing styles.  
> 
> It is my strong opinion too, but I am also glad I am not attempting to 
> write book while holding this opinion.
> 
>     DR> ...  So many "style guides" for
>     DR> CL in the past have fallen on their face, because they don't
>     DR> espouse good CL writing, but instead one or two people's
>     DR> opinions of what good writing is.  The fierce independence in
>     DR> me always says "don't fence me in".
> 
> But there probably are clearly awful things to do.  Does "no fence" 
> imply Greenblatt Code that is sometimes mentioned here is OK?  

I'd say no.  There is a difference between different ways of _implementing_
Common Lisp (possibly poorly) and different ways of _using_ Common Lisp.

> I am not idly nitpicking, I may end up having to guide someone I got
> interested in CL here, so I'd like hear more.

It really is a fine point, however.  There are many times when a newbie
will post some Greenblatt-ish code, and it almost immediately draws
fire with a "why didn't you just use ...".  It is because such code
is reimplementing what CL already provides, and I don't mind when that
kind of code is criticized.

However, one way to learn Lisp is to implement it, and as long as
nobody is launching rockets from the learning experience ...

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: David Steuber
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <87hdpp6ivj.fsf@david-steuber.com>
Duane Rettig <·····@franz.com> writes:

> However, one way to learn Lisp is to implement it, and as long as
> nobody is launching rockets from the learning experience ...

It's a good thing Werner Von Braun is not here to hear you say that
:-).

Another style question.  Actually it's more of a paradigm question.
Can one write CLOS code in a functional style?  Or is that too much of
a clash?

-- 
An ideal world is left as an excercise to the reader.
   --- Paul Graham, On Lisp 8.1
From: Joe Marshall
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <wtyk7vo9.fsf@ccs.neu.edu>
David Steuber <·····@david-steuber.com> writes:

> Duane Rettig <·····@franz.com> writes:
>
>> However, one way to learn Lisp is to implement it, and as long as
>> nobody is launching rockets from the learning experience ...
>
> It's a good thing Werner Von Braun is not here to hear you say that
> :-).
>
> Another style question.  Actually it's more of a paradigm question.
> Can one write CLOS code in a functional style?  

Sure.  I do it all the time.
From: Kenny Tilton
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <%JE4d.1438$mH1.1919035@twister.nyc.rr.com>
David Steuber wrote:

> Duane Rettig <·····@franz.com> writes:
> 
> 
>>However, one way to learn Lisp is to implement it, and as long as
>>nobody is launching rockets from the learning experience ...
> 
> 
> It's a good thing Werner Von Braun is not here to hear you say that
> :-).
> 
> Another style question.  Actually it's more of a paradigm question.
> Can one write CLOS code in a functional style? 

Cells! Declrative, too.

:)

kenny


-- 
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: Steven E. Harris
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <jk4llf2ut9n.fsf@W003275.na.alarismed.com>
Peter Seibel <·····@javamonkey.com> writes:

> What's your vote?

I prefer the second style because it alleviates the human reader (and
possibly the runtime) from having to wonder how many of those
intermediate variables need to coexist and how they relate to one
another.

If the second style is judged too compact and cryptic, I'd sooner
introduce small helper functions to label the sub-forms than use a
bunch of named temporary variables.

Less concrete and more subjective, the first style looks more like the
work of a novice, not yet able to juggle the intermediate values, not
yet ready to let go of the pedantry.

-- 
Steven E. Harris
From: Chris Riesbeck
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <criesbeck-6CFB83.13144622092004@individual.net>
In article <···············@W003275.na.alarismed.com>,
 "Steven E. Harris" <···@panix.com> wrote:

> Peter Seibel <·····@javamonkey.com> writes:
> 
> > What's your vote?
> 
> I prefer the second style because it alleviates the human reader (and
> possibly the runtime) from having to wonder how many of those
> intermediate variables need to coexist and how they relate to one
> another.

Same for me, quite strongly. The second form made
me feel like I knew exactly what results fed into what,
and that the programmer was in control of the
API. 


My personal quibble with readability would be with 
the names. columns is a function but column is data.
The only functions with action names are
order-by and select. But generating concise
but clear names for many closely related functions 
is really hard. I don't have a quick set of
alternatives to suggest.
From: Kenny Tilton
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <aRk4d.144999$4h7.23207160@twister.nyc.rr.com>
Chris Riesbeck wrote:
> In article <···············@W003275.na.alarismed.com>,
>  "Steven E. Harris" <···@panix.com> wrote:
> 
> 
>>Peter Seibel <·····@javamonkey.com> writes:
>>
>>
>>>What's your vote?
>>
>>I prefer the second style because it alleviates the human reader (and
>>possibly the runtime) from having to wonder how many of those
>>intermediate variables need to coexist and how they relate to one
>>another.

Amen.

> 
> 
> Same for me, quite strongly. The second form made
> me feel like I knew exactly what results fed into what,
> and that the programmer was in control of the
> API. 
> 
> 
> My personal quibble with readability would be with 
> the names.

Yep.

kenny

-- 
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: Will Hartung
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <2rdtvaF1902g5U1@uni-berlin.de>
"Peter Seibel" <·····@javamonkey.com> wrote in message
···················@javamonkey.com...
> Unless I've dorked something up these two functions should be
> functionally equivalent. Since this is comp.lang.lisp, I'm sure folks
> have strong opinions about which style is more perspicuous. What's
> your vote? Write-in candidates of your own devising also accepted.
>
>   (defun select-single-column (db column &rest keys-and-values)
>     "Select the distinct values of a single column from a set of
>     rows matching the given keys."
>     (let* ((selector         (apply #'selector db keys-and-values))
>            (all-rows         (rows db))
>            (selected-rows    (select selector all-rows))
>            (selected-columns (columns selected-rows column))
>            (distinct-rows    (distinct selected-columns))
>            (ordered-rows     (order-by db distinct-rows column)))
>       (column-values ordered-rows)))

I like this style as it helps factor out a complicated expression. As Bjorn
mentioned, maybe it's factored too much vs the other option where it isn't
factored at all.

But from a reability style, I like the first method as I can basically run
down the list more easily and make each piece as simple or complicated as I
desire without worrying about breaking the statement. And it's more readable
than a deeply nested structure as well.

Finally, if I'm having problems, I can simply wrap (print ...) around any of
these and narrow down my problem very quickly.

IMHO, of course.

Regards,

Will Hartung
(·····@msoft.com)
From: Bulent Murtezaoglu
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <87wtym2lnf.fsf@p4.internal>
>>>>> "WH" == Will Hartung <·····@msoft.com> writes:
[...]
    WH> But from a reability style, I like the first method as I can
    WH> basically run down the list more easily and make each piece as
    WH> simple or complicated as I desire without worrying about
    WH> breaking the statement. And it's more readable than a deeply
    WH> nested structure as well.

I do this too, but then after I spend some time on the code the long 
let* starts looking superfluous and becomes an eyesore.  I don't know 
how other lispers think, but I seem to like keeping things I understand 
compact.  Once the process is understood, barring typos and such, the 
deeply nested structure doesn't seem any harder to read.  But maybe one 
ought to think of others who'll read the code also.  

    WH> Finally, if I'm having problems, I can simply wrap (print ...) 
    WH> around any of these and narrow down my problem very quickly.

Unless _compute_ something internal and print it, I tend to do that kind 
of debugging with trace. 

    WH> IMHO, of course.

I'll raise you one V.  IMVHO

cheers,

BM
From: Thomas F. Burdick
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <xcv7jqmm5xp.fsf@conquest.OCF.Berkeley.EDU>
This function screams "local helpers!" to me:

  (defun select-single-column (db column &rest keys-and-values)
    (flet ((selected-rows ()
             (select (apply #'selector db keys-and-values)
                     (rows db)))
           (distinct (rows) (distinct (columns rows column)))
           (ordered (rows) (order-by db rows column)))
      (column-values
        (ordered
          (distinct
            (selected-rows))))))

When possible, I try to decompose a function into a composition of
calls to helper functions that take a single argument, getting the
other data from the top-level function's arguments.
From: Eric Daniel
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <10l4oqpkqsctp97@corp.supernews.com>
In article <···············@conquest.OCF.Berkeley.EDU>, Thomas F. Burdick wrote:
>  This function screams "local helpers!" to me:
>  
>    (defun select-single-column (db column &rest keys-and-values)
>      (flet ((selected-rows ()
>               (select (apply #'selector db keys-and-values)
>                       (rows db)))
>             (distinct (rows) (distinct (columns rows column)))
>             (ordered (rows) (order-by db rows column)))
>        (column-values
>          (ordered
>            (distinct
>              (selected-rows))))))
>  
>  When possible, I try to decompose a function into a composition of
>  calls to helper functions that take a single argument, getting the
>  other data from the top-level function's arguments.

This doesn't answer Peter's question, but I have to admit that every
solution proposed so far tends to blow my mental stack to some degree (the
ones that use intermediate names fare slightly better).

I would consider rewriting the interface so it doesn't require
so many nested functions, for example:

(column-values
  (select db :bindings keys-and-values
             :selector #'selector
             :columns (list column)
             :order-by (list column)
             :distinct (list column))

Again, maybe this won't fit Peter's purpose.

-- 
Eric Daniel
From: Christophe Turle
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <ciu4se$7tp$1@amma.irisa.fr>
Thomas F. Burdick wrote:
> This function screams "local helpers!" to me:
> 
>   (defun select-single-column (db column &rest keys-and-values)
>     (flet ((selected-rows ()
>              (select (apply #'selector db keys-and-values)
>                      (rows db)))
>            (distinct (rows) (distinct (columns rows column)))
>            (ordered (rows) (order-by db rows column)))
>       (column-values
>         (ordered
>           (distinct
>             (selected-rows))))))
> 
> When possible, I try to decompose a function into a composition of
> calls to helper functions that take a single argument, getting the
> other data from the top-level function's arguments.

I find your idea very good as the general one. Only one argument so that we can clearly read it functionnaly. You can then opt for this layout :

...
       (column-values (ordered (distinct (selected-rows))))
...

Which is the core of the function and is read very easily. When you read this function you may bypass the flet definitions but still understand it.

Kenny suggest to improve the name given. He's right. Names are very important. Always take care of them.

And third, Eric Daniel's suggestion (refactoring the select interface with new keywords) apply there. A more specific rule which makes you gain readabilty over your whole program.


Christophe Turle.
From: Matthew Danish
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <87ekku6usd.fsf@mapcar.org>
Peter Seibel <·····@javamonkey.com> writes:
> Unless I've dorked something up these two functions should be
> functionally equivalent. Since this is comp.lang.lisp, I'm sure folks
> have strong opinions about which style is more perspicuous. What's
> your vote? Write-in candidates of your own devising also accepted.

I generally prefer the first option (labelling intermediate results)
when computing the intermediate results is non-trivial, likely to be
extended, or in need of the documentation of variable names for
clarity.  Otherwise, nest away!

-- 
;; Matthew Danish -- user: mrd domain: cmu.edu
;; OpenPGP public key: C24B6010 on keyring.debian.org
From: szymon
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <cirs9b$de3$1@atlantis.news.tpi.pl>
Peter Seibel wrote:
> Unless I've dorked something up these two functions should be
> functionally equivalent. Since this is comp.lang.lisp, I'm sure folks
> have strong opinions about which style is more perspicuous. What's
> your vote? Write-in candidates of your own devising also accepted.
> 
>   (defun select-single-column (db column &rest keys-and-values)
>     "Select the distinct values of a single column from a set of
>     rows matching the given keys."
>     (let* ((selector         (apply #'selector db keys-and-values))
>            (all-rows         (rows db))
>            (selected-rows    (select selector all-rows))
>            (selected-columns (columns selected-rows column))
>            (distinct-rows    (distinct selected-columns))
>            (ordered-rows     (order-by db distinct-rows column)))
>       (column-values ordered-rows)))

Why not AUX ?

(defun select-single-column
   (db column
    &rest keys-and-values
    &aux (selector (apply #'selector db keys-and-values))
         (all-rows         (rows db))
         (selected-rows    (select selector all-rows))
         (selected-columns (columns selected-rows column))
         (distinct-rows    (distinct selected-columns))
         (ordered-rows     (order-by db distinct-rows column)))
   (column-values ordered-rows))

> 
>   (defun select-single-column (db column &rest keys-and-values)
>     "Select the distinct values of a single column from a set of
>     rows matching the given keys."
>     (column-values
>      (order-by
>       db 
>       (distinct
>        (columns
>         (select (apply #'selector db keys-and-values) (rows db))
>         column))
>       column)))
> 
> -Peter

IMHO this is better.

Regards, Szymon.
From: Björn Lindberg
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <hcsy8j2bg9f.fsf@my.nada.kth.se>
Peter Seibel <·····@javamonkey.com> writes:

> Unless I've dorked something up these two functions should be
> functionally equivalent. Since this is comp.lang.lisp, I'm sure folks
> have strong opinions about which style is more perspicuous. What's
> your vote? Write-in candidates of your own devising also accepted.
> 
>   (defun select-single-column (db column &rest keys-and-values)
>     "Select the distinct values of a single column from a set of
>     rows matching the given keys."
>     (let* ((selector         (apply #'selector db keys-and-values))
>            (all-rows         (rows db))
>            (selected-rows    (select selector all-rows))
>            (selected-columns (columns selected-rows column))
>            (distinct-rows    (distinct selected-columns))
>            (ordered-rows     (order-by db distinct-rows column)))
>       (column-values ordered-rows)))
> 
>   (defun select-single-column (db column &rest keys-and-values)
>     "Select the distinct values of a single column from a set of
>     rows matching the given keys."
>     (column-values
>      (order-by
>       db 
>       (distinct
>        (columns
>         (select (apply #'selector db keys-and-values) (rows db))
>         column))
>       column)))

I *think* I would prefer an aesthetic intermediate. :-) Perhaps
something like the following:

  (defun select-single-column (db column &rest keys-and-values)
    "Select the distinct values of a single column from a set of
     rows matching the given keys."
    (let* ((selector (apply #'selector db keys-and-values))
           (columns (columns (select selector (rows db)) column))
           (rows (order-by db (distinct columns) column)))
      (column-values rows)))

I would try to reserve naming the subexpressions that are of more
importance, instead of naming each and every one. If it still looks
too compact, you can align the arguments to one or more of the
functions in the LET* vertically.


Bj�rn
From: Vassil Nikolov
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <lzhdppyd80.fsf@janus.vassil.nikolov.names>
Peter Seibel <·····@javamonkey.com> writes:

> Unless I've dorked something up these two functions should be
> functionally equivalent. Since this is comp.lang.lisp, I'm sure folks
> have strong opinions about which style is more perspicuous. What's
> your vote? Write-in candidates of your own devising also accepted.
>
>   (defun select-single-column (db column &rest keys-and-values)
>     "Select the distinct values of a single column from a set of
>     rows matching the given keys."
>     (let* ((selector         (apply #'selector db keys-and-values))
>            (all-rows         (rows db))
>            (selected-rows    (select selector all-rows))
>            (selected-columns (columns selected-rows column))
>            (distinct-rows    (distinct selected-columns))
>            (ordered-rows     (order-by db distinct-rows column)))
>       (column-values ordered-rows)))
>
>   (defun select-single-column (db column &rest keys-and-values)
>     "Select the distinct values of a single column from a set of
>     rows matching the given keys."
>     (column-values
>      (order-by
>       db 
>       (distinct
>        (columns
>         (select (apply #'selector db keys-and-values) (rows db))
>         column))
>       column)))


  IM-SQ-O (Suitably Qualified), the latter style [1] is definitely
  better in allowing the human reader to see if the function is
  implemented correctly.  (Assuming, of course, that said reader knows
  about the functions involved, which I don't.)  With the former
  style, it is rather more difficult to see if all intermediate
  results are indeed at the right places.

  And yes, I believe it is important to be able to _see_ that a piece
  of code is written correctly (not just to run it and see what it
  produces).  Well, I hope I am preaching to the choir...

  As an aside, the issue of finding good names for such functions is
  very important, too.  Maybe it's just me, but---given the way
  DISTINCT and ORDER BY are used in SQL---I find it hard to perceive
  them as function names.  COLUMNS, too---maybe GET-COLUMNS (if that
  is what it does)?

  [1] Ignoring aspects of indentation style, of course, though they
  matter, too (how many people can reindent code mentally?  I don't
  claim to be very good at it).

  ---Vassil.


-- 
Vassil Nikolov <········@poboxes.com>

Hollerith's Law of Docstrings: Everything can be summarized in 72 bytes.
From: Peter Seibel
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <m3vfe5kacc.fsf@javamonkey.com>
Vassil Nikolov <········@poboxes.com> writes:

> Peter Seibel <·····@javamonkey.com> writes:
>
>> Unless I've dorked something up these two functions should be
>> functionally equivalent. Since this is comp.lang.lisp, I'm sure folks
>> have strong opinions about which style is more perspicuous. What's
>> your vote? Write-in candidates of your own devising also accepted.
>>
>>   (defun select-single-column (db column &rest keys-and-values)
>>     "Select the distinct values of a single column from a set of
>>     rows matching the given keys."
>>     (let* ((selector         (apply #'selector db keys-and-values))
>>            (all-rows         (rows db))
>>            (selected-rows    (select selector all-rows))
>>            (selected-columns (columns selected-rows column))
>>            (distinct-rows    (distinct selected-columns))
>>            (ordered-rows     (order-by db distinct-rows column)))
>>       (column-values ordered-rows)))
>>
>>   (defun select-single-column (db column &rest keys-and-values)
>>     "Select the distinct values of a single column from a set of
>>     rows matching the given keys."
>>     (column-values
>>      (order-by
>>       db 
>>       (distinct
>>        (columns
>>         (select (apply #'selector db keys-and-values) (rows db))
>>         column))
>>       column)))
>
>
>   IM-SQ-O (Suitably Qualified), the latter style [1] is definitely
>   better 

[snip]

>   [1] Ignoring aspects of indentation style, of course, though they
>   matter, too (how many people can reindent code mentally? I don't
>   claim to be very good at it).

Okay, so now I'm curios, how would you have indented it? Obviously I
chose the line breaks but the rest is just standard Emacs lisp-mode
indentation.

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Vassil Nikolov
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <lzd60dyaiq.fsf@janus.vassil.nikolov.names>
Peter Seibel <·····@javamonkey.com> writes:

> Vassil Nikolov <········@poboxes.com> writes:
>> [...]
>>   [1] Ignoring aspects of indentation style, of course, though they
>>   matter, too (how many people can reindent code mentally? I don't
>>   claim to be very good at it).
>
> Okay, so now I'm curios, how would you have indented it? Obviously I
> chose the line breaks but the rest is just standard Emacs lisp-mode
> indentation.


  Of course, I wrote the above note primarily because your question
  was not about indentation, _but_ at the same time it is hard (at
  least for me, but I suspect for many) to abstract oneself from it
  when evaluating other aspects of style.  Besides, neither do I Know
  How to Indent This Properly, nor is it a subject of little debate...

  That said, I would prefer more horizontal space and fewer newlines,
  like this:

(defun select-single-column (db column &rest keys-and-values)
  ;; keeping the first line of the docstring a self-contained summary:
  "Select the distinct values of a single column.
The values come from the set of rows matching the given keys."
  (column-values (order-by db
                           (distinct (columns (select (apply #'selector db keys-and-values)
                                                      (rows db))
                                              column))
                           column)))

  (Not using the Tab key.)

  One final note: indenting code that one has written oneself is
  rather different from indenting someone else's code in any case.

  ---Vassil.

-- 
Vassil Nikolov <········@poboxes.com>

Hollerith's Law of Docstrings: Everything can be summarized in 72 bytes.
From: Alan Shutko
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <87zn3hf1gh.fsf@wesley.springies.com>
Vassil Nikolov <········@poboxes.com> writes:

>   That said, I would prefer more horizontal space and fewer newlines,
>   like this:

As a contrarian, I really prefer to keep things under 80 columns.
Sure, screens are bigger than that these days... but it's more useful
to me to have two files/sections side-by-side than it is to have a
really wide window just so a couple sections can be wider than 80 chars.


-- 
Alan Shutko <···@acm.org> - I am the rocks.
ECL: Early Care Lace
From: Peter Seibel
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <m3d60ckhre.fsf@javamonkey.com>
Vassil Nikolov <········@poboxes.com> writes:

>   That said, I would prefer more horizontal space and fewer newlines,
>   like this:
>
> (defun select-single-column (db column &rest keys-and-values)
>   ;; keeping the first line of the docstring a self-contained summary:
>   "Select the distinct values of a single column.
> The values come from the set of rows matching the given keys."
>   (column-values (order-by db
>                            (distinct (columns (select (apply #'selector db keys-and-values)
>                                                       (rows db))
>                                               column))
>                            column)))

Wow. That kind of indentation makes me batty. I understand that it has
a perfectly consistent logic that reflects the structure of the code
and the virtue of being common practice. But I still have a very hard
time looking at it as I get lost in all the whitespace on the left. Am
I the only one?

Other problems I have with this style are:

 - The column each line starts in is a function of not only its
   nesting level but also the length of the names of the enclosing
   constructs. This may be a hold-over from my days as member of the
   curly-brace crowd but I like the way curly-brace code looks like an
   outline--each new level of indentation steps a consistent two (or
   four) spaces in.

 - Because things move so far to the right, you quickly end up having
   to put line breaks in even fairly short expressions unless you're
   willing to have lines well over 80 characters. (This is a
   particular problem for me while working on my book--I *have* to
   limit lines to 83 chars.)

That said, everytime I end up code that naturally gets indented the
way you did it I push it around breaking lines in various places and
am always disatisfied.

A particular thing that always bugs me is when I have something like this:

  (make-instance 'some-class
                 :some-longish-thing 10
                 :another-longish-thing 20
                 :and-one-last-arg 30)

The big block of empty space on the left bugs me. So I try the other
standard (i.e. Emacs-blessed) formatting:

  (make-instance
   'some-class
   :some-longish-thing 10
   :another-longish-thing 20
   :and-one-last-arg 30)

Now that takes too many lines just to make one object. What I always
find myself trying (and then giving up on because I refuse to fight
Emacs) is something like:

  (make-instance 'some-class
   :some-longish-thing 10 :another-longish-thing 20 :and-one-last-arg 30)

-Peter

P.S. Cue Kenny to beat me about the head and shoulders for using fake
names and to tell me that I wouldn't have any of these problems if I
had his perfect insight into how to choose names.

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Fred Gilham
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <u765647syq.fsf@snapdragon.csl.sri.com>
Peter Seibel <·····@javamonkey.com> writes:

> Vassil Nikolov <········@poboxes.com> writes:
> 
> >   That said, I would prefer more horizontal space and fewer newlines,
> >   like this:
> >
> > (defun select-single-column (db column &rest keys-and-values)
> >   ;; keeping the first line of the docstring a self-contained summary:
> >   "Select the distinct values of a single column.
> > The values come from the set of rows matching the given keys."
> >   (column-values (order-by db
> >                            (distinct (columns (select (apply #'selector db keys-and-values)
> >                                                       (rows db))
> >                                               column))
> >                            column)))
> 
> Wow. That kind of indentation makes me batty. I understand that it has
> a perfectly consistent logic that reflects the structure of the code
> and the virtue of being common practice. But I still have a very hard
> time looking at it as I get lost in all the whitespace on the left. Am
> I the only one?

I was just reading something about reading text being harder if the
text is too wide.  This seems to apply here.  You have to move your
eyes back and forth to take in the whole thing.

-- 
Fred Gilham                                         ······@csl.sri.com
It's not when people notice you're there that they pay attention; it's
when they notice you're *still* there.  --- Paul Graham
From: Joe Marshall
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <r7os7qn3.fsf@ccs.neu.edu>
Peter Seibel <·····@javamonkey.com> writes:

> A particular thing that always bugs me is when I have something like this:
>
>   (make-instance 'some-class
>                  :some-longish-thing 10
>                  :another-longish-thing 20
>                  :and-one-last-arg 30)
>
> The big block of empty space on the left bugs me. 

That doesn't bother me, but the ragged right does.  I often do this:

>   (make-instance 'some-class
>       :some-thing             10
>       :another-longish-thing  20
>       :short                  'foobar
>       :and-one-last-arg       30)
From: Peter Seibel
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <m36564kbzt.fsf@javamonkey.com>
Joe Marshall <···@ccs.neu.edu> writes:

> Peter Seibel <·····@javamonkey.com> writes:
>
>> A particular thing that always bugs me is when I have something like this:
>>
>>   (make-instance 'some-class
>>                  :some-longish-thing 10
>>                  :another-longish-thing 20
>>                  :and-one-last-arg 30)
>>
>> The big block of empty space on the left bugs me. 
>
> That doesn't bother me, but the ragged right does.  I often do this:
>
>>   (make-instance 'some-class
>>       :some-thing             10
>>       :another-longish-thing  20
>>       :short                  'foobar
>>       :and-one-last-arg       30)

Yeah, I often do that too.

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Marco Antoniotti
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <iFV4d.30$NQ1.10296@typhoon.nyu.edu>
Peter Seibel wrote:

> Joe Marshall <···@ccs.neu.edu> writes:
> 
> 
>>Peter Seibel <·····@javamonkey.com> writes:
>>
>>
>>>A particular thing that always bugs me is when I have something like this:
>>>
>>>  (make-instance 'some-class
>>>                 :some-longish-thing 10
>>>                 :another-longish-thing 20
>>>                 :and-one-last-arg 30)
>>>
>>>The big block of empty space on the left bugs me. 
>>
>>That doesn't bother me, but the ragged right does.  I often do this:
>>
>>
>>>  (make-instance 'some-class
>>>      :some-thing             10
>>>      :another-longish-thing  20
>>>      :short                  'foobar
>>>      :and-one-last-arg       30)
> 
> 
> Yeah, I often do that too.


Since we are at it, what really really, really bothers me is the lack of 
a good Emacs cl-indent-function handler for LOOP (I think I saw one 
around some time ago, but I forget where) E.g. I'd like

	(loop for x in l
	      when (oddp x)
	        collect x))

but with Emacs (and derivatives) you always get

	(loop for x in l
	      when (oddp x)
	      collect x)

Any taker?

Cheers
--
Marco
From: Arthur Lemmens
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <opset5rgyok6vmsw@news.xs4all.nl>
Marco Antoniotti <·······@cs.nyu.edu> wrote:

> I'd like
>
> 	(loop for x in l
> 	      when (oddp x)
> 	        collect x))
>
> but with Emacs (and derivatives) you always get
>
> 	(loop for x in l
> 	      when (oddp x)
> 	      collect x)
>
> Any taker?

Sure. Use Jonathan Amsterdam's ITERATE: clearer semantics,
more features, extendable, normal s-expr notation and indentation
for free. And it's similar enough to LOOP that you can start using
it immediately. (He should have called it LOOP++ ;-)

(I know, I know: that doesn't help you with existing code.
But people should at least seriously consider it for new programs.)

Arthur
From: Marco Antoniotti
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <wBV4d.29$NQ1.10928@typhoon.nyu.edu>
Peter Seibel wrote:
> Vassil Nikolov <········@poboxes.com> writes:
> 
> 
>>  That said, I would prefer more horizontal space and fewer newlines,
>>  like this:
>>
>>(defun select-single-column (db column &rest keys-and-values)
>>  ;; keeping the first line of the docstring a self-contained summary:
>>  "Select the distinct values of a single column.
>>The values come from the set of rows matching the given keys."
>>  (column-values (order-by db
>>                           (distinct (columns (select (apply #'selector db keys-and-values)
>>                                                      (rows db))
>>                                              column))
>>                           column)))
> 
> 
> Wow. That kind of indentation makes me batty. I understand that it has
> a perfectly consistent logic that reflects the structure of the code
> and the virtue of being common practice. But I still have a very hard
> time looking at it as I get lost in all the whitespace on the left. Am
> I the only one?

It bothers me as well, but it is the best you can do.  And I find it 
consistent.

> 
> Other problems I have with this style are:
> 
>  - The column each line starts in is a function of not only its
>    nesting level but also the length of the names of the enclosing
>    constructs. This may be a hold-over from my days as member of the
>    curly-brace crowd but I like the way curly-brace code looks like an
>    outline--each new level of indentation steps a consistent two (or
>    four) spaces in.

I think this is not completely correct.  E.g. I generally like the GNU C 
coding standards, but I have a few problems with it.  One of the 
problems I have is that it does not enforce my personal rule: if a 
function call cannot fit all its arguments in a line, then each argument 
(with the exception of key-value pairs) should be on a line of its own.

In essence, I would code the above in "curly bracket language" as:

Column
select_single_column(DB db, T column, KV_pairs keys_and_values)
{
     return column_values(order_by(db,
                                  distinct(columns(select(apply(selector,
                                                                db,
 
keys_and_values),
                                                          db.rows()),
                                           column)),
                                  column));
}


Not much different, as you can see.  Besides, that is the way you get 
you indentantion with Emacs and auto-fill-mode on.





> 
>  - Because things move so far to the right, you quickly end up having
>    to put line breaks in even fairly short expressions unless you're
>    willing to have lines well over 80 characters. (This is a
>    particular problem for me while working on my book--I *have* to
>    limit lines to 83 chars.)

Yes, you are right, but I see no easy way out.

> 
> That said, everytime I end up code that naturally gets indented the
> way you did it I push it around breaking lines in various places and
> am always disatisfied.
> 
> A particular thing that always bugs me is when I have something like this:
> 
>   (make-instance 'some-class
>                  :some-longish-thing 10
>                  :another-longish-thing 20
>                  :and-one-last-arg 30)
> 
> The big block of empty space on the left bugs me.

It does not bug me that much.

> So I try the other
> standard (i.e. Emacs-blessed) formatting:
> 
>   (make-instance
>    'some-class
>    :some-longish-thing 10
>    :another-longish-thing 20
>    :and-one-last-arg 30)

This I like.


> 
> Now that takes too many lines just to make one object. What I always
> find myself trying (and then giving up on because I refuse to fight
> Emacs) is something like:
> 
>   (make-instance 'some-class
>    :some-longish-thing 10 :another-longish-thing 20 :and-one-last-arg 30)

I think this is fine, as long as the kv pair line is less than the 
sacred 80 characters :)

Besides, fighting Emacs in the case above is just a case of adding a 
special formatting clause to cl-indent-function for make-instance.


Cheers
--
Marco
From: Gareth McCaughan
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <87wtyj1efs.fsf@g.mccaughan.ntlworld.com>
Peter Seibel <·····@javamonkey.com> writes:

> Vassil Nikolov <········@poboxes.com> writes:
...
> > (defun select-single-column (db column &rest keys-and-values)
> >   ;; keeping the first line of the docstring a self-contained summary:
> >   "Select the distinct values of a single column.
> > The values come from the set of rows matching the given keys."
> >   (column-values (order-by db
> >                            (distinct (columns (select (apply #'selector db keys-and-values)
> >                                                       (rows db))
> >                                               column))
> >                            column)))
> 
> Wow. That kind of indentation makes me batty. I understand that it has
> a perfectly consistent logic that reflects the structure of the code
> and the virtue of being common practice. But I still have a very hard
> time looking at it as I get lost in all the whitespace on the left. Am
> I the only one?

No.

-- 
Gareth McCaughan
.sig under construc
From: Pascal Bourguignon
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <87acviezso.fsf@thalassa.informatimago.com>
Peter Seibel <·····@javamonkey.com> writes:

> Unless I've dorked something up these two functions should be
> functionally equivalent. Since this is comp.lang.lisp, I'm sure folks
> have strong opinions about which style is more perspicuous. What's
> your vote? Write-in candidates of your own devising also accepted.
> 
>   (defun select-single-column (db column &rest keys-and-values)
>     "Select the distinct values of a single column from a set of
>     rows matching the given keys."
>     (let* ((selector         (apply #'selector db keys-and-values))
>            (all-rows         (rows db))
>            (selected-rows    (select selector all-rows))
>            (selected-columns (columns selected-rows column))
>            (distinct-rows    (distinct selected-columns))
>            (ordered-rows     (order-by db distinct-rows column)))
>       (column-values ordered-rows)))
> 
>   (defun select-single-column (db column &rest keys-and-values)
>     "Select the distinct values of a single column from a set of
>     rows matching the given keys."
>     (column-values
>      (order-by
>       db 
>       (distinct
>        (columns
>         (select (apply #'selector db keys-and-values) (rows db))
>         column))
>       column)))

Clearly, the later. Why do you want to introduce names when you then
use them only once?

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we.
From: Christophe Rhodes
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <sq7jqmaru6.fsf@cam.ac.uk>
Pascal Bourguignon <····@mouse-potato.com> writes:

> Peter Seibel <·····@javamonkey.com> writes:
>
>>     (let* ((selector         (apply #'selector db keys-and-values))
>>            (all-rows         (rows db))
>>            (selected-rows    (select selector all-rows))
>>            (selected-columns (columns selected-rows column))
>>            (distinct-rows    (distinct selected-columns))
>>            (ordered-rows     (order-by db distinct-rows column)))
>>       (column-values ordered-rows)))
>>
>>     (column-values
>>      (order-by
>>       db 
>>       (distinct
>>        (columns
>>         (select (apply #'selector db keys-and-values) (rows db))
>>         column))
>>       column)))
>
> Clearly, the later. Why do you want to introduce names when you then
> use them only once?

the of code your reader human might stack space infinite have not Because.

Christophe

(the form intermediate by some commentators posted I prefer)
From: Raffael Cavallaro
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <2004092221291616807%raffaelcavallaro@pasdespamsilvousplaitdotmaccom>
On 2004-09-22 17:59:25 -0400, Christophe Rhodes <·····@cam.ac.uk> said:

> the of code your reader human might stack space infinite have not Because.

Agreed. I'm inclined to think that the distaste for names is a sign of 
"real programmer[1]" machismo, and makes for painfully unreadable, 
unmaintainable code.

[1] see <http://www.jargon.net/jargonfile/t/TheStoryofMel.html> for 
"The Story of Mel, a Real Programmer."
From: Kenny Tilton
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <fPr4d.41290$Ot3.5006@twister.nyc.rr.com>
Raffael Cavallaro wrote:
> On 2004-09-22 17:59:25 -0400, Christophe Rhodes <·····@cam.ac.uk> said:
> 
>> the of code your reader human might stack space infinite have not 
>> Because.
> 
> 
> Agreed. I'm inclined to think that the distaste for names is a sign of 
> "real programmer[1]" machismo, and makes for painfully unreadable, 
> unmaintainable code.

Code complex enough to involve either a lengthy sequence of let* 
bindings or a hairy nested functional form is /never/ readable, so 
forget that angle: one will always have to work through it slowly and 
carefully.

Meanwhile, a good argument against names is that programmers usually 
cock them up badly:

   (defun select-single-column (db column &rest keys-and-values)
 >     "Select the distinct values of a single column from a set of
 >     rows matching the given keys."
 >     (let* ((selector         (apply #'selector db keys-and-values))
 >            (all-rows         (rows db))
 >            (selected-rows    (select selector all-rows))
 >            (selected-columns (columns selected-rows column))

Columns returns one column, not many. Its name is wrong, and its result 
should be bound to selected-column, again singular.

 >            (distinct-rows    (distinct selected-columns))

Distinct is working on one column. Its result should be bound to 
distinct-cells (or values or fields or somesuch). Let us go with 
distinct-values.

 >            (ordered-rows     (order-by db distinct-rows column)))

should be ordered-values.

 >       (column-values ordered-rows)))

No need for column-values now. :)

I am sure there are programmers besides moi who worry about the names 
they choose, I just have not met any. Then again, I do not get out much.

:)

kenny


-- 
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: Raffael Cavallaro
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <raffaelcavallaro-C2C237.00234223092004@netnews.comcast.net>
In article <····················@twister.nyc.rr.com>,
 Kenny Tilton <·······@nyc.rr.com> wrote:

> Meanwhile, a good argument against names is that programmers usually 
> cock them up badly:

This is an argument for good names. No name at all is *not* a good name. 
Take the time (as you apparently do) to come up with good names.


> I am sure there are programmers besides moi who worry about the names 
> they choose, I just have not met any.

Surely you aren't the only one Kenny...

>Then again, I do not get out much.

Ah, I knew there was an explanation...

> :)

ditto

Ralph
From: Alan Crowe
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <86k6uldudq.fsf@cawtech.freeserve.co.uk>
Kenny Tilton ironized
> Meanwhile, a good argument against names is that
> programmers usually cock them up badly:

In the particular case in question the names are essentially
comments.

  (defun select-single-column (db column &rest keys-and-values)
    "Select the distinct values of a single column from a set of
    rows matching the given keys."
    (let* ((selector         (apply #'selector db keys-and-values))
           (all-rows         (rows db))
           (selected-rows    (select selector all-rows))
           (selected-columns (columns selected-rows column))
           (distinct-rows    (distinct selected-columns))
           (ordered-rows     (order-by db distinct-rows column)))
      (column-values ordered-rows)))

is just a much better way of writing

  (defun select-single-column (db column &rest keys-and-values)
    "Select the distinct values of a single column from a set of
    rows matching the given keys."
    (let* ((t1 (apply #'selector db keys-and-values)) ;selector
           (t2 (rows db)) ;all-rows
           (t3 (select selector t2)) ;selected-rows
           (t4 (columns t3 column)) ;selected-columns
           (t5 (distinct t4)) ;distinct-rows
           (t6 (order-by db t5 column))) ;ordered-rows
      (column-values t6)))

Thus the let code is to be judged by the same criteria as one
applies to comments:

     Don't be formulaic about commenting, that just leads to
     writing too many comments, all of them feeble.

     Spend the time instead on writing a small number of
     carefully crafted comments.

So one might prefer

(defun select-single-column (db column &rest keys-and-values)
  "Select the distinct values of a single column from a set of
    rows matching the given keys."
  (let ((still-got-duplicates (select (apply #'selector
					 db
					 keys-and-values)
				  (rows db))))
    (column-values (order-by db 
			     (distinct (columns still-got-duplicates
						column))
			     column))))

Alan Crowe
Edinburgh
Scotland
From: Kenny Tilton
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <AmA4d.42328$Ot3.38288@twister.nyc.rr.com>
Alan Crowe wrote:

> Kenny Tilton ironized
> 
>>Meanwhile, a good argument against names is that
>>programmers usually cock them up badly:
> 
> 
> In the particular case in question the names are essentially
> comments.

ha-ha... I do not believe in comments, either. They never get 
maintained, and you do not need them if one uses (wait for it) good 
names! They are just a substitute for clear code.

I agree these names are comments, and like any comments they would not 
be needed if the function names were better. The poor OP wanted to ask a 
simple style question and did not go crazy over the sample names, but it 
just goes to show the interdependence of nature; the example must be 
real-world and as carefully written as production code before the style 
question even can be asked.

<discontinuity alert>

One thing missed in all this: the value of a good language-aware editor. 
These "comments" are redundant. A good Lisp editor will show the names 
of the parameters of a function. As for working out which form is an 
argument to which function, that is what auto-indentation and blinking 
matching parens is for.

kenny

-- 
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: Peter Seibel
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <m3isa5j7kq.fsf@javamonkey.com>
Kenny Tilton <·······@nyc.rr.com> writes:

> Alan Crowe wrote:
>
>> Kenny Tilton ironized
>> 
>>>Meanwhile, a good argument against names is that
>>>programmers usually cock them up badly:
>> In the particular case in question the names are essentially
>> comments.
>
> ha-ha... I do not believe in comments, either. They never get
> maintained, and you do not need them if one uses (wait for it) good
> names! They are just a substitute for clear code.
>
> I agree these names are comments, and like any comments they would not
> be needed if the function names were better. The poor OP wanted to ask
> a simple style question and did not go crazy over the sample names,
> but it just goes to show the interdependence of nature; the example
> must be real-world and as carefully written as production code before
> the style question even can be asked.

Actually, this is reasonably close to real-world code. I'd maintain
that the functions names that you dislike are actually reasonable in
the normal context where they are used. (I.e. several of them map
more-or-less to the morally equivalent parts of SQL which should help
make them understandable by analogy to anyone familiar with SQL.)

That said, maybe there's a better naming scheme that makes all these
problems go away. So here's the chalenge, if you're up for it: Here
are the current functions and their purpose. Rename or recombine as
you see fit in a way that makes this function and other uses of these
functions more clear. In all the functions a parameter `rows' is a
list of plists where each plist represents a database record, e.g.

  (defparameter *rows* 
    '((:first "Fred" :last "Flinstone" :age 30) 
      (:first "Barney" :last "Rubble" :age 29)
      (:first "Barney" :last "Miller" :age 40))

 (defun select (rows &rest names-and-values)
    "Return a subset of rows where the values match the
    values given in names-and-values.")

  E.g.

    (select *rows* :first "Barney") ==> 
       ((:first "Barney" :last "Rubble" :age 29)
        (:first "Barney" :last "Miller" :age 40))


  (defun columns (rows &rest columns)
    "Return a new set of rows containing only the specified columns.")

  E.g.

    (columns *rows* :first :last) ==>
       ((:first "Fred" :last "Flinstone") 
        (:first "Barney" :last "Rubble")
        (:first "Barney" :last "Miller"))

  (defun distinct (rows)
    "Return a subset of rows with only one occurence of each distinct row.")

  E.g.

    (distinct (columns *rows* :first)) ==>
       ((:first "Fred") (:first "Barney"))

  (defun order-by (rows &rest columns)
    "Return rows sorted by the given columns.")

  E.g. 

    (order-by *rows* :first :last)
      ((:first "Barney" :last "Miller" :age 40) 
       (:first "Barney" :last "Rubble" :age 29)
       (:first "Fred" :last "Flinstone" :age 30))


I though about using the relational weenie names, "restriction" and
"projection" instead of select and columns but given the number of
programmers conversant in relational terminology (I had to look them
up, anyway) that seemed a bit obscure.

So how would you solve this naming problem?


-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Chris Riesbeck
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <criesbeck-FD6EF4.14134923092004@individual.net>
In article <··············@javamonkey.com>,
 Peter Seibel <·····@javamonkey.com> wrote:
 
> That said, maybe there's a better naming scheme that makes all these
> problems go away. So here's the chalenge, if you're up for it: 

Well, there's up "for" it and up "to" it. I guess I can claim
the former.

> Here are the current functions and their purpose. Rename or recombine as
> you see fit in a way that makes this function and other uses of these
> functions more clear. In all the functions a parameter `rows' is a
> list of plists where each plist represents a database record, e.g.
> 
>   (defparameter *rows* 
>     '((:first "Fred" :last "Flinstone" :age 30) 
>       (:first "Barney" :last "Rubble" :age 29)
>       (:first "Barney" :last "Miller" :age 40))

Already I think I was misled by the term "row." I
would call this *records* because of the labelled fields.
"rows" suggests to me a straight tabular representation, e.g., 

  (("Fred" "Flinstone")
   ("Barney" "Rubble")
   ...)

In fact, why not use a tabular representation?
Is something like

   ((:first "Fred" :last "Flinstone" :age 30)
    (:age 29 :last "Rubble" :first "Barney")
    ...)

legal? If not, why double the space used by including labels?
I'd go for a list of labels, plus a tabular list of lists of
data values.

But I digress.

> 
>  (defun select (rows &rest names-and-values)
>     "Return a subset of rows where the values match the
>     values given in names-and-values.")
> 
>   E.g.
> 
>     (select *rows* :first "Barney") ==> 
>        ((:first "Barney" :last "Rubble" :age 29)
>         (:first "Barney" :last "Miller" :age 40))

This doesn't match the original example that started all this.
That had

>   (select (apply #'selector db keys-and-values) (rows db))

i.e., select took the result of a selector, whatever that
returned, and rows. I'll assume the new version, since
that makes more sense to me.
  
Assuming this operates on and returns rows, not columns, I'd
call it select-rows. And for generality, I'd have it take
a predicate. There are lots of things ways I might 
want to select rows, e.g., "select if address
is not null" and "select if start date is before 2000."


   (defun select-rows (rows predicate)
     "Returns those rows that satisfy the predicate")

   (defun value-test (&rest names-and-values)
     "Returns a predicate p(row) that is true if the
     values in row match the values in names-and-values")

E.g.,

   (select-rows *rows* (value-test :first "Barney"))

>   (defun columns (rows &rest columns)
>     "Return a new set of rows containing only the specified columns.")

Major name clash for me here. Columns takes a set of rows and
returns a set of rows. So why is it called columns?
select-columns would still suggest the wrong thing. If you
really don't want to introduce the projection concept, 
maybe select-fields?

   (defun select-fields (rows &rest names)
     "Return a list of rows with just the fields named")

>   (defun distinct (rows)
>     "Return a subset of rows with only one occurence of each distinct row.")
>
>   E.g.
> 
>     (distinct (columns *rows* :first)) ==>
>        ((:first "Fred") (:first "Barney"))

A true computer scientist. None of them can spell "occurrence."

remove-duplicate-rows would be the simplest and clearest,
albeit long.

E.g.,

  (remove-duplicate-rows (select-fields *rows* :first))

Given that these operations often go together, I'd change select-fields
to allow me to say no duplicates:

   (defun select-fields (rows names &key unique)
     "Return a list of rows with just the fields named.
     If unique is true, do not include duplicate rows.")
     
So the example would be

  (select-fields *rows* '(:first) :unique t)


>   (defun order-by (rows &rest columns)
>     "Return rows sorted by the given columns.")
>
>   E.g. 
> 
>     (order-by *rows* :first :last)
>       ((:first "Barney" :last "Miller" :age 40) 
>        (:first "Barney" :last "Rubble" :age 29)
>        (:first "Fred" :last "Flinstone" :age 30))

Is that list of labels what you meant? Normally you'd
list the primary key first, then the secondary, and
I assume from your example and normal usage 
you meant the last name to be the primary key.

Again, this doesn't seem to match the original example, 
which had a call like this:

    (order-by db distinct-rows column)

Again, I understand the new version better than the
original so I'll start with it.

As with select-rows, I'd name this by what it takes, does,
and returns, namely sort-rows. And again I'd change it
to take a predicate, for generality,

  (defun sort-rows (rows test)
    "Return rows sorted using the ordering predicate test.")

Then I'd add a row-sorting predicate maker. Just giving
column labels to sort by is a bit limiting. Even very
simple applications call for sorting different columns
different ways, e.g. ascending vs descending. So, I'd add

  (defun field-ordering (names-and-tests)
    "Return a row-ordering predicate, given a list of
    field-names or (field-name test) pairs.")

  (defun ascendingp (x y)
    "Returns true if x and y are numbers and (< x y) or
     x and y are strings and (string< x y).")

  (defun descendingp (x y)
    "Returns true if x and y are numbers and (> x y) or
     x and y are strings and (string> x y).")

E.g., your example would be

  (sort-rows *rows* (field-ordering :last :first))

but if we wanted to list the oldest people first, and
then sorted within that, we'd write

  (sort-rows *rows*
    (field-ordering (:age #'descendingp) :last :first))
    
You didn't mention column-values in your list of things to change.
I assume it's defined as

  (defun column-values (rows column)
    "Return the values that appear in rows in the given column.")
    
I would go for field-values, and add the ability to remove duplicates:

  (defun field-values (rows field &key unique))
    "Return the values that appear in rows in the field named.
    If unique is true, do not include duplicate values")

I'm not positive about column-values though because the
original example had

  (column-values ordered-rows)
  
But I don't see how that selects "the distinct values of a
single column" as documented.

Now, how does that original example that started all
this look? The original code was:

>   (defun select-single-column (db column &rest keys-and-values)
>     "Select the distinct values of a single column from a set of
>     rows matching the given keys."
>     (column-values
>      (order-by
>       db 
>       (distinct
>        (columns
>         (select (apply #'selector db keys-and-values) (rows db))
>         column))
>       column)))

The new code, if I'm understanding the old code correctly, and
I do have some confusion about order-by, would be

   (defun select-field-values (rows field &rest fields-and-values)
     (field-values
       (sort-rows
         (select-fields
           (select-rows rows (apply #'value-test fields-and-values))
           field
           :unique t)
         field)
       field))
       
I don't like that value-test -- one reason why I tend
to avoid &rest arguments until I know for sure that more
code looks cleaner with a &rest argument than with a normal
argument.

But name-wise, I'm not as unhappy as before.
From: Peter Lewerin
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <b72f3640.0409240603.dcf79d2@posting.google.com>
Peter Seibel <·····@javamonkey.com> wrote in message 

> So how would you solve this naming problem?

Since I am confused by the naming and unable to think of better names
right now, I'd possibly solve it by keeping the functions' names and
hiding them behind a macro:

    (select-dataset *rows* distinct
                    where :first = "Barney"
                    and :shoes = 'nike
                    order-by '(:last :age)
                    show '(:first :last :age :phone))

"distinct" causes the dataset to be purged by DISTINCT, "where" begins
assembling key-value pairs for SELECT, "and" appends a new pair to
that list, "order-by" arranges for a call to ORDER-BY, and "show" is a
front for COLUMNS.

---

Neo: I know Lisp!
Morpheus: *raising eyebrow* Show me.
From: Alan Crowe
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <86sm980xhc.fsf@cawtech.freeserve.co.uk>
Peter Seibel replied to Kenny Tilton
> I'd maintain that the functions names that you  dislike are
> actually reasonable in the normal context where they are
> used. (I.e. several of them map more-or-less to the
> morally equivalent parts of SQL which should help make
> them understandable by analogy to anyone familiar with
> SQL.)

If the function names map /exactly/ to the morally equivalent
parts of SQL, I would export them from a package named SQL,
but not import them. So usage would look like

(sql:select (sql:columns ...))

If the mapping is "more-or-less" rather than exact, then
those who are unfamiliar with SQL lose out because the names
have not been chosen for the particular application,
while those who are familiar with SQL lose out because they
trip over the differences.

> I though about using the relational weenie names,
> "restriction" and "projection" instead of select and
> columns but given the number of programmers conversant in
> relational terminology (I had to look them up, anyway)
> that seemed a bit obscure.

Avoiding technical terms usually goes horrible wrong. Look
at the decision of timber merchants to simplify "angiosperm"
to "hardwood", and "gymnosperm" to "softwood". This make balsa
a "hardwood".

The rows and the columns represent very different aspects of
the data. The are no concepts equivalent to "transpose" and
"symmetric" such as arise for a square matrix.  So the
corresponding concepts of select-rows and select-columns are
very different. 

"Rows and columns" is a spatial/architectural metaphor. The
data in a database doesn't have an intrinsic sense of one
record being above another, or of age being to the left of
occupation. One adopts a convent for the layout of database
tables on the page, and then layers a spatial/architectural
metaphor on top of that. Having a second order metaphor is a
real pain for newbies. It doesn't work smoothly until on has
absorbed the layout convention to the extent that it becomes
invisible. One already has records/fields and
tuples/components. There is little need for metaphorical
rows/columns.

On the other hand, names must be short. Building up compound
names by starting too generally with "select", understood
broadly, and then adding qualifications is not a happy
choice. Nor is bodging it horribly with
"select-rows"->"select" and "select-columns"="columns".

I'm not a relational weenie so I'm uncertain about the
terminology they use. If others have already faced the
problem of choosing distinct names for the two different
concepts and come up with "select" and "project" just
accept their choices.

Alan Crowe
East-Big-City
Scotland
From: Peter Seibel
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <m3mzzhj8d8.fsf@javamonkey.com>
Kenny Tilton <·······@nyc.rr.com> writes:

> Raffael Cavallaro wrote:
>> On 2004-09-22 17:59:25 -0400, Christophe Rhodes <·····@cam.ac.uk> said:
>> 
>>> the of code your reader human might stack space infinite have not
>>> Because.
>> Agreed. I'm inclined to think that the distaste for names is a sign
>> of "real programmer[1]" machismo, and makes for painfully
>> unreadable, unmaintainable code.
>
> Code complex enough to involve either a lengthy sequence of let*
> bindings or a hairy nested functional form is /never/ readable, so
> forget that angle: one will always have to work through it slowly and
> carefully.
>
> Meanwhile, a good argument against names is that programmers usually
> cock them up badly:
>
>    (defun select-single-column (db column &rest keys-and-values)
>  >     "Select the distinct values of a single column from a set of
>  >     rows matching the given keys."
>  >     (let* ((selector         (apply #'selector db keys-and-values))
>  >            (all-rows         (rows db))
>  >            (selected-rows    (select selector all-rows))
>  >            (selected-columns (columns selected-rows column))
>
> Columns returns one column, not many. Its name is wrong, and its
> result should be bound to selected-column, again singular.

Actually, no, columns, the function, in general returns as many
columns as it's asked for. In this case it happens only to have been
asked for one. So your point may apply to the variable name,
selected-columns but not to the function name.


>  >            (distinct-rows    (distinct selected-columns))
>
> Distinct is working on one column. Its result should be bound to
> distinct-cells (or values or fields or somesuch). Let us go with
> distinct-values.

But that's not quite right because the value of selected columns is
going to be something like

  '((:x 10) (:x 20) (:x 20))

which distinct will reduce to:

  '((:x 10) (:x 20))

But I'd expect distinct-values to be '(10 20)

>  >            (ordered-rows     (order-by db distinct-rows column)))
>
> should be ordered-values.

Again not quite for the same reason.

>  >       (column-values ordered-rows)))
>
> No need for column-values now. :)

What do you think it is, a no-op: that's what converts '((:x 10) (:x
20)) to (10 20)

> I am sure there are programmers besides moi who worry about the names
> they choose, I just have not met any. Then again, I do not get out
> much.

Hmmm. There's some kind of irony here; you assumed my names were
poorly choosen which lead you to misunderstand the code. Seems like
reading names is just as hard as choosing them.

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Kenny Tilton
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <JsF4d.1441$mH1.1929779@twister.nyc.rr.com>
Peter Seibel wrote:
> Kenny Tilton <·······@nyc.rr.com> writes:
> 
> 
>>Raffael Cavallaro wrote:
>>
>>>On 2004-09-22 17:59:25 -0400, Christophe Rhodes <·····@cam.ac.uk> said:
>>>
>>>
>>>>the of code your reader human might stack space infinite have not
>>>>Because.
>>>
>>>Agreed. I'm inclined to think that the distaste for names is a sign
>>>of "real programmer[1]" machismo, and makes for painfully
>>>unreadable, unmaintainable code.
>>
>>Code complex enough to involve either a lengthy sequence of let*
>>bindings or a hairy nested functional form is /never/ readable, so
>>forget that angle: one will always have to work through it slowly and
>>carefully.
>>
>>Meanwhile, a good argument against names is that programmers usually
>>cock them up badly:
>>
>>   (defun select-single-column (db column &rest keys-and-values)
>> >     "Select the distinct values of a single column from a set of
>> >     rows matching the given keys."
>> >     (let* ((selector         (apply #'selector db keys-and-values))
>> >            (all-rows         (rows db))
>> >            (selected-rows    (select selector all-rows))
>> >            (selected-columns (columns selected-rows column))
>>
>>Columns returns one column, not many. Its name is wrong, and its
>>result should be bound to selected-column, again singular.
> 
> 
> Actually, no, columns, the function, in general returns as many
> columns as it's asked for. 

I did consider that possibility, but the rest of the code led me to 
guess it only returned one. Bad guess.

> In this case it happens only to have been
> asked for one. So your point may apply to the variable name,
> selected-columns but not to the function name.

It does apply to the variable name. Look at the function name: 
select-single-column. And now that I have seen the definition of 
columns, egad!, it returns a list of rows!!

There is a reason Lisp has long function names. There is just no way 
around them to make things comprehensible. columns should be something 
like rows-columns-select or -filter or -prune or something. 
selected-columns should be just be "mini-me". :) the overall function 
starts with a db (that should be ds for dataset or tbl for table, yes?) 
and just returns a miniature version, still a dataset.

> 
> 
> 
>> >            (distinct-rows    (distinct selected-columns))
>>
>>Distinct is working on one column. Its result should be bound to
>>distinct-cells (or values or fields or somesuch). Let us go with
>>distinct-values.
> 
> 
> But that's not quite right because the value of selected columns is
> going to be something like
> 
>   '((:x 10) (:x 20) (:x 20))
> 
> which distinct will reduce to:
> 
>   '((:x 10) (:x 20))
> 
> But I'd expect distinct-values to be '(10 20)

I got lost on the row-column-speak, started imagining a grid. Your 
follow-up clarifies things nicely.

Actually, when I first looked at the code I was alarmed that progressive 
filtering had first produced columns from rows and then somehow rows 
from columns and kinda threw up my hands in despair. Now I see the 
problem: it is rows all the way down.

> 
> 
>> >            (ordered-rows     (order-by db distinct-rows column)))
>>
>>should be ordered-values.
> 
> 
> Again not quite for the same reason.
> 
> 
>> >       (column-values ordered-rows)))
>>
>>No need for column-values now. :)
> 
> 
> What do you think it is, a no-op: that's what converts '((:x 10) (:x
> 20)) to (10 20)
> 
> 
>>I am sure there are programmers besides moi who worry about the names
>>they choose, I just have not met any. Then again, I do not get out
>>much.
> 
> 
> Hmmm. There's some kind of irony here; you assumed my names were
> poorly choosen which lead you to misunderstand the code. Seems like
> reading names is just as hard as choosing them.

Nope. I did my level best to understand the code. Quality of naming is 
actually a digression in this thread, one I triggered only because the 
names struck me as off based on what the code honestly conveyed to me.

I do get a kick, however, out of the idea of assuming (for some reason 
not specified) that the names were bad, and then reading code by first 
assigning subtly different semantics to names and seeing what chaos 
results from a reading of the rest of the code. Anyone else old enough 
to remember Mad Libs?

The name selected-columns (or selected-column) works for a reader only 
if they know the actual semantics: "(selected rows with just one) 
selected-column". even they are mentally translating (or getting it 
wrong if the code is not fresh in their mind), never mind the confusion 
to those not in on the secret.

kenny

-- 
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: Peter Lewerin
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <b72f3640.0409230055.5cce225d@posting.google.com>
Peter Seibel <·····@javamonkey.com> wrote:

> have strong opinions about which style is more perspicuous. What's
> your vote? Write-in candidates of your own devising also accepted.

I suppose this isn't really acceptable:

  (defun select-single-column (db column &rest keys-and-values)
    "Select the distinct values of a single column from a set of
     rows matching the given keys."
    (let* ((x (apply #'selector db keys-and-values))
	   (x (columns (select x (rows db)) column))
	   (x (rows (order-by db (distinct x) column))))
    (column-values x))

The rationale, anyway, is that a single, short, meaningless name is
better than a handful of potentially confusing names (Your naming
*did* confuse me;  I *am* easily confused, but still).

I re-used Bj�rn Lindberg's formulation of the function, btw.
From: Adam Warner
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <pan.2004.09.23.11.56.07.782958@consulting.net.nz>
Hi Peter Lewerin,

> Peter Seibel <·····@javamonkey.com> wrote:
> 
>> have strong opinions about which style is more perspicuous. What's
>> your vote? Write-in candidates of your own devising also accepted.
> 
> I suppose this isn't really acceptable:
> 
> (defun select-single-column (db column &rest keys-and-values)
>   "Select the distinct values of a single column from a set of
>    rows matching the given keys."
>   (let* ((x (apply #'selector db keys-and-values))
>          (x (columns (select x (rows db)) column))
>          (x (rows (order-by db (distinct x) column))))
>   (column-values x))

Surprisingly compelling. Let's take it one step further:

  (defun select-single-column (db column &rest keys-and-values)
    "Select the distinct values of a single column from a set of
     rows matching the given keys."
    (_* ((apply #'selector db keys-and-values)
         (columns (select _ (rows db)) column)
         (rows (order-by db (distinct _) column)))
        (column-values _)))

> The rationale, anyway, is that a single, short, meaningless name is
> better than a handful of potentially confusing names (Your naming
> *did* confuse me;  I *am* easily confused, but still).

  (defmacro _* (stages &body body)
    `(let* (,@(loop for item in stages collect (list '_ item)))
      ,@body))

Regards,
Adam
From: szymon
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <ciun3k$62p$1@nemesis.news.tpi.pl>
Btw, Paul Graham wants 'tax' on LET* ("On Lisp" page 32).

Regards, Szymon.
From: Gareth McCaughan
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <87sm971d30.fsf@g.mccaughan.ntlworld.com>
Peter Seibel <·····@javamonkey.com> writes:

> Unless I've dorked something up these two functions should be
> functionally equivalent. Since this is comp.lang.lisp, I'm sure folks
> have strong opinions about which style is more perspicuous. What's
> your vote? Write-in candidates of your own devising also accepted.
> 
>   (defun select-single-column (db column &rest keys-and-values)
>     "Select the distinct values of a single column from a set of
>     rows matching the given keys."
>     (let* ((selector         (apply #'selector db keys-and-values))
>            (all-rows         (rows db))
>            (selected-rows    (select selector all-rows))
>            (selected-columns (columns selected-rows column))
>            (distinct-rows    (distinct selected-columns))
>            (ordered-rows     (order-by db distinct-rows column)))
>       (column-values ordered-rows)))
> 
>   (defun select-single-column (db column &rest keys-and-values)
>     "Select the distinct values of a single column from a set of
>     rows matching the given keys."
>     (column-values
>      (order-by
>       db 
>       (distinct
>        (columns
>         (select (apply #'selector db keys-and-values) (rows db))
>         column))
>       column)))

(defun select-rows (db keys-and-values)
  "The rows from DB matching the selector defined by KEYS-AND-VALUES."
  (select (apply #'selector db keys-and-values)
          (rows db)))

(defun sorted-unique-rows-by-column (db rows column)
  "Extract column COLUMN from ROWS; sort according to its
  value, and coalesce rows where it's equal."
  (order-by db
            (distinct (columns rows column))
            column))

(defun select-single-column (db column &rest keys-and-values)
  "Select the distinct values of a single column form a set
  of rows matching the given keys."
  (let ((rows           (select-rows db keys-and-values))
        (processed-rows (sorted-unique-rows-by-column db rows column)))
    (column-values processed-rows)))

I would (weakly) expect the two extracted functions
to be useful elsewhere.

                         *

By the way, Kenny was moaning about your variable and
function names, mostly unreasonably ... but I'm afraid
SELECT-SINGLE-COLUMN is a truly abominable name given
what it actually does. How about DISTINCT-VALUES-FROM-COLUMN
or something?

And there's at least one rather nasty thing in the
design of the functions you're assuming here. Anywhere
where you can use a row-set, it should be possible to
use a DB directly (meaning: all the rows). This is
evidently not possible for your SELECT.

Oh, and it seems to me that the function you've called
SELECT-SINGLE-COLUMN is doing two entirely separate
jobs which I don't see any justification for combining:
first it's selecting some rows, then it's extracting
distinct values from a column. That looks to me like
two separate functions: one for selecting the rows
(which, if you accept my principle that a DB should
always be able to stand in for the set of all its rows,
you can sometimes not bother calling) and one for
uniquifying and extracting the column.

    (distinct-column-values (select-rows my-db :wibble 123 :wobble 234)
                            column-1)

Sure, you can save a few characters by amalgamating
these two functions, and maybe you do it moderately
often. But it still doesn't look any more sensible
to me than

    (defun *+ (a b c) (+ (* a b) c))

which would also save typing moderately often ... but
would also cause confusion by combining two quite
separate operations.

-- 
Gareth McCaughan
.sig under construc
From: Kenny Tilton
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <DJ55d.145226$4h7.23968967@twister.nyc.rr.com>
Gareth McCaughan wrote:

> Peter Seibel <·····@javamonkey.com> writes:
> 
> 
>>Unless I've dorked something up these two functions should be
>>functionally equivalent. Since this is comp.lang.lisp, I'm sure folks
>>have strong opinions about which style is more perspicuous. What's
>>your vote? Write-in candidates of your own devising also accepted.
>>
>>  (defun select-single-column (db column &rest keys-and-values)
>>    "Select the distinct values of a single column from a set of
>>    rows matching the given keys."
>>    (let* ((selector         (apply #'selector db keys-and-values))
>>           (all-rows         (rows db))
>>           (selected-rows    (select selector all-rows))
>>           (selected-columns (columns selected-rows column))
>>           (distinct-rows    (distinct selected-columns))
>>           (ordered-rows     (order-by db distinct-rows column)))
>>      (column-values ordered-rows)))
>>
>>  (defun select-single-column (db column &rest keys-and-values)
>>    "Select the distinct values of a single column from a set of
>>    rows matching the given keys."
>>    (column-values
>>     (order-by
>>      db 
>>      (distinct
>>       (columns
>>        (select (apply #'selector db keys-and-values) (rows db))
>>        column))
>>      column)))
> 
> 
> (defun select-rows (db keys-and-values)
>   "The rows from DB matching the selector defined by KEYS-AND-VALUES."
>   (select (apply #'selector db keys-and-values)
>           (rows db)))
> 
> (defun sorted-unique-rows-by-column (db rows column)
>   "Extract column COLUMN from ROWS; sort according to its
>   value, and coalesce rows where it's equal."
>   (order-by db
>             (distinct (columns rows column))
>             column))
> 
> (defun select-single-column (db column &rest keys-and-values)
>   "Select the distinct values of a single column form a set
>   of rows matching the given keys."
>   (let ((rows           (select-rows db keys-and-values))
>         (processed-rows (sorted-unique-rows-by-column db rows column)))
>     (column-values processed-rows)))
> 
> I would (weakly) expect the two extracted functions
> to be useful elsewhere.
> 
>                          *
> 
> By the way, Kenny was moaning about your variable and
> function names, mostly unreasonably ... but I'm afraid
> SELECT-SINGLE-COLUMN is a truly abominable name given
> what it actually does. How about DISTINCT-VALUES-FROM-COLUMN
> or something?

Doesn't it just suck a big one when you have to agree publicly with 
Demon Kenny?

Next time make two posts, one just denouncing me, one just agreeing. 
Most people won't notice.

Two things:

(1) the longer one looks at the posted code, the more disastrous it 
gets. You found one glaring misnomer, possibly the worst. There were 
more. I had to abandon a post because it threatened to turn into a book 
on bad style.

(b) my code is no better! I retract the bit about me being the only one 
who worries about names. I mean, I really do and long have fretted 
furiously over names, but they do not reliably turn out better than 
peter's -- i cannot look at my code without rewriting it, often to fix 
names.

which happily brings us back to the original point: the functional style 
makes manifest the dataflow and obviates the needless proliferation of 
error-prone names for temporary variables.

Thomas Burdick's solution (for thems that recall it) offers the best of 
both worlds, but does require a little more coding. And with Lisp, that 
can be a death knell.

kt
From: Gareth McCaughan
Subject: Re: Which style do you prefer?
Date: 
Message-ID: <87lleyw2ar.fsf@g.mccaughan.ntlworld.com>
Kenny Tilton wrote:

> Doesn't it just suck a big one when you have to agree publicly with
> Demon Kenny?
> 
> Next time make two posts, one just denouncing me, one just
> agreeing. Most people won't notice.

Hey, cool idea. Will do.

> Two things:
> 
> (1) the longer one looks at the posted code, the more disastrous it
> gets. You found one glaring misnomer, possibly the worst. There were
> more. I had to abandon a post because it threatened to turn into a
> book on bad style.
> 
> (b) my code is no better! I retract the bit about me being the only
> one who worries about names. I mean, I really do and long have fretted
> furiously over names, but they do not reliably turn out better than
> peter's -- i cannot look at my code without rewriting it, often to fix
> names.

I think one problem here is that the underlying API
that this thing seems to assume is really rather nasty.
This remark doesn't constitute an offer to define a
better one; making relational databases coexist happily
with proper programming languages is harder than it
looks. :-)

-- 
Gareth McCaughan
.sig under construc