From: Christopher Browne
Subject: Re: Lisp Data Structure: Looking for an alternative
Date: 
Message-ID: <aj4qga$18p67s$2@ID-125932.news.dfncis.de>
Oops! Marco Antoniotti <·······@cs.nyu.edu> was seen spray-painting on a wall:
> Christopher Browne <········@acm.org> writes:
>
>> In an attempt to throw the authorities off his trail, ······@ryanschram.com (Ryan Schram) transmitted:
>> > I am writing to get input on how to conceptualize a problem in Lisp**.
>> > I am working on a small script which takes a CSV* file and parses it
>> > into a Lisp data structure.
>> >
>> > (
>> >   ("field-1" "field-2" ... "field-n")     ; Row 1
>> >   ("field-1" "field-2" ... "field-n")     ; Row 2
>> >   ...
>> >   ("field-1" "field-2" ... "field-n")     ; Row n
>> > )
>> >
>> > I must now iterate over the list essentially like so.
>> >
>> > (let ((i 0) (max (length list)))
>> >   (while (< i max)
>> >     (princ (format "Field %d" (nth 0 (nth i list)) )
>> >   )
>> > )
>> >
>> > I have about 24 hours of Lisp experience now, so even this simplified
>> > form is giving me a headache; more complex iterations are highly
>> > error-prone. So, i'm looking for an easier, cleaner alternative, if
>> > one exists.
>> >
>> > Questions: 
>> >    Is there a better way to represent this kind of data? 
>> >    Where can I go to learn about this?
>> >
>> > Thanks, 
>> > Ryan Schram
>> >
>> > * Not a real CSV. I'm not trying to anticipate quoted entries. 
>> > ** Emacs Lisp, but this is a very basic issue.
>> 
>> Actually, the Emacs Lisp part is an important point.  
>> 
>> If you _hadn't_ said that, I'd have immediately suggested you look at
>> DEFSTRUCT or DEFCLASS, and consider making the data into some form of
>> "record" or "structure" with named elements.
>
> Well.  The correct suggestion is to fire up Emacs, open up `~/.emacs' and stick
>
>         (require 'cl)
>
> in it.
>
> After that you have DEFSTRUCT and most of CL at your fingertips.

True, but not necessarily important.

Based on what is being done with the data structure at this point,
there doesn't appear to be a need for any of that, whether named
random access, via DEFSTRUCT, or numbered random access, via
#(vectors).

It seems to suffice to use a couple of nested DOLISTs to solve the
problem at hand.  

Nothing thus far suggests that there is a _real_ need to resort to
more sophisticated data types, though it's good that (require 'cl) can
get at them, if need be...
-- 
(concatenate 'string "cbbrowne" ·@acm.org")
http://www.ntlug.org/~cbbrowne/rdbms.html
"Moebius strippers only show you their back side." -- Unknown

From: Ryan Schram
Subject: Re: Lisp Data Structure: Looking for an alternative
Date: 
Message-ID: <1b25eec7.0208111103.8328c33@posting.google.com>
Christopher Browne <········@acm.org> wrote in message news:<···············@ID-125932.news.dfncis.de>...
> Oops! Marco Antoniotti <·······@cs.nyu.edu> was seen spray-painting on a wall:
> > Christopher Browne <········@acm.org> writes:
> >
> >> In an attempt to throw the authorities off his trail, ······@ryanschram.com (Ryan Schram) transmitted:
> >> > I am writing to get input on how to conceptualize a problem in Lisp**.
> >> > I am working on a small script which takes a CSV* file and parses it
> >> > into a Lisp data structure.
> >> Actually, the Emacs Lisp part is an important point.  
> >> 
> >> If you _hadn't_ said that, I'd have immediately suggested you look at
> >> DEFSTRUCT or DEFCLASS, and consider making the data into some form of
> >> "record" or "structure" with named elements.
> >
> > Well.  The correct suggestion is to fire up Emacs, open up `~/.emacs' and stick
> >
> >         (require 'cl)
> >
> > in it.
> >
> > After that you have DEFSTRUCT and most of CL at your fingertips.
> 
> True, but not necessarily important.
> 
> Based on what is being done with the data structure at this point,
> there doesn't appear to be a need for any of that, whether named
> random access, via DEFSTRUCT, or numbered random access, via
> #(vectors).
> 

Thanks to everyone who responded. The advice was very helpful. 

Here's some background: My interest in Lisp is to solve a Perlish
problem - take a datafile, transform it into a data structure that
preserves some of the order of original data file, and traverse that
data structure to produce a series of reports. CSV into HTML pages, to
be precise.

I think defstruct is too complicated for this data - diary entries.
Vectors appear to be more useful than lists.

> It seems to suffice to use a couple of nested DOLISTs to solve the
> problem at hand.  
> 
> Nothing thus far suggests that there is a _real_ need to resort to
> more sophisticated data types, though it's good that (require 'cl) can
> get at them, if need be...

Since the same operation is performed on every sublist, DOLIST is very
helpful. A second, nested DOLIST (as I understand their syntax) won't
work, because each field in the record will get a different format
when it is printed. It would be nice to do this:

(dolist (record table)
  (dolist ((i j k) record)
    (insert 
      (concat 
          "<h3>" i "</h3>"
          "<p>" j "</p">
          "<p>" k "</p>"
      )
    )
  )
)

But you can't, can you?
From: Eduardo Muñoz
Subject: Re: Lisp Data Structure: Looking for an alternative
Date: 
Message-ID: <uy9bdp378.fsf@jet.es>
······@ryanschram.com (Ryan Schram) writes:
> [...] It would be nice to do this:
> 
> (dolist (record table)
>   (dolist ((i j k) record)
>     (insert 
>       (concat 
>           "<h3>" i "</h3>"
>           "<p>" j "</p">
>           "<p>" k "</p>"
>       )
>     )
>   )
> )
> 
> But you can't, can you?

Sure :)

ELISP> (require 'cl)
cl
ELISP> (setf table '(("foo" "bar" "baz") ("oof" "rab" "zab")))
(("foo" "bar" "baz")
 ("oof" "rab" "zab"))

ELISP> (dolist (record table)
         (destructuring-bind (i j k) record
           (print (concat "<h3>" i "</h3>"
                          "<p>"  j "</p>"
                          "<p>"  k "</p>"))))
nil
ELISP> 

This prints (in the minibuffer):


"<h3>foo</h3><p>bar</p><p>baz</p>"

"<h3>oof</h3><p>rab</p><p>zab</p>"


-- 

Eduardo Mu�oz
From: Kaz Kylheku
Subject: Re: Lisp Data Structure: Looking for an alternative
Date: 
Message-ID: <aj6o89$jpj$1@luna.vcn.bc.ca>
In article <···························@posting.google.com>, Ryan Schram wrote:
> when it is printed. It would be nice to do this:
> 
> (dolist (record table)
>   (dolist ((i j k) record)
>     (insert 
>       (concat 
>           "<h3>" i "</h3>"
>           "<p>" j "</p">
>           "<p>" k "</p>"
>       )
>     )
>   )
> )

Incidentally, you should learn to clump closing parentheses:

            "<p>" k "</p>"))))

Otherwise you will drive yourself crazy, and others.

> But you can't, can you?

Of course you can:

  (dolist (item record)
    (destructuring-bind (i j k) item
      ... do stuff with i j k ...))

This assumes that ``item'' is a list. If it's a vector
you can hack your own binding construct:

  (defmacro vector-bind (vars vec &rest forms)
    (do ((i 0 (1+ i))
         (var vars (rest var))
         (list))
        ((null var) `(let ,(nreverse list) ,@forms))
      (push `(,(first var) (aref ,vec ,i)) list)))

  ;; elsewhere ...

       (vector-bind (i j k) item ...)

If item is a struct or class with slots named i j and k, you can pull it apart
using with-slots:

  (with-slots (i j k) item ...)

And of course if you really want, you can combine the destructuring with the
dolist iteration, to make some convenient little macro like:

  (dolist-destructured ((i j k) list)
    ...)

How would we write this language feature?

  (defmacro dolist-destructured ((destructuring-lambda-list 
                                  list &optional result-form)
                                 &rest body)
    (let ((list-item-sym (gensym "LIST-ITEM-")))
      `(dolist (,list-item-sym ,list ,result-form)
        (destructuring-bind ,destructuring-lambda-list ,list-item-sym
          ,@body))))

  (defvar *list* '((1 2) (3 4))

  (dolist-destructured ((i j) *list*) 
    (format t "~a - ~a~%" i j))

  Output:
  1 - 2
  3 - 4

Note that result-form does not see the bound variables in its scope.
From: Erik Naggum
Subject: Re: Lisp Data Structure: Looking for an alternative
Date: 
Message-ID: <3238121081222111@naggum.no>
* Kaz Kylheku
| Of course you can:
| 
|   (dolist (item record)
|     (destructuring-bind (i j k) item
|       ... do stuff with i j k ...))

(loop for (i j k) in items ...)

-- 
Erik Naggum, Oslo, Norway

Act from reason, and failure makes you rethink and study harder.
Act from faith, and failure makes you blame someone and push harder.
From: Thomas F. Burdick
Subject: Re: Lisp Data Structure: Looking for an alternative
Date: 
Message-ID: <xcvbs88f7tz.fsf@apocalypse.OCF.Berkeley.EDU>
Erik Naggum <····@naggum.no> writes:

> * Kaz Kylheku
> | Of course you can:
> | 
> |   (dolist (item record)
> |     (destructuring-bind (i j k) item
> |       ... do stuff with i j k ...))
> 
> (loop for (i j k) in items ...)

A purely historical question: was it ever proposed to allow loop
var-specs to be full destructuring-bind lambda lists?  If not, it's
pretty obvious why they're not -- but if it was proposed, I'd be
curious why they aren't.  Don't get me wrong, I know how to write:

  (loop for item in items
        for (i j k) = (destructuring-bind (&key i j k) item (list i j k))
        ...)

But it does seem like something that would've gone quite nicely in the
LOOP mini-language.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Kaz Kylheku
Subject: Re: Lisp Data Structure: Looking for an alternative
Date: 
Message-ID: <aj9mt7$g7u$1@luna.vcn.bc.ca>
In article <················@naggum.no>, Erik Naggum wrote:
> * Kaz Kylheku
>| Of course you can:
>| 
>|   (dolist (item record)
>|     (destructuring-bind (i j k) item
>|       ... do stuff with i j k ...))
> 
> (loop for (i j k) in items ...)

Sigh; I yet have to master the nuances of loop. 
From: Christopher Browne
Subject: Re: Lisp Data Structure: Looking for an alternative
Date: 
Message-ID: <aj921d$19f9rf$3@ID-125932.news.dfncis.de>
In an attempt to throw the authorities off his trail, ······@ryanschram.com (Ryan Schram) transmitted:
> Christopher Browne <········@acm.org> wrote in message news:<···············@ID-125932.news.dfncis.de>...
>> Oops! Marco Antoniotti <·······@cs.nyu.edu> was seen spray-painting on a wall:
>> > Christopher Browne <········@acm.org> writes:
>> >
>> >> In an attempt to throw the authorities off his trail, ······@ryanschram.com (Ryan Schram) transmitted:
>> >> > I am writing to get input on how to conceptualize a problem in Lisp**.
>> >> > I am working on a small script which takes a CSV* file and parses it
>> >> > into a Lisp data structure.
>> >> Actually, the Emacs Lisp part is an important point.  
>> >> 
>> >> If you _hadn't_ said that, I'd have immediately suggested you look at
>> >> DEFSTRUCT or DEFCLASS, and consider making the data into some form of
>> >> "record" or "structure" with named elements.
>> >
>> > Well.  The correct suggestion is to fire up Emacs, open up `~/.emacs' and stick
>> >
>> >         (require 'cl)
>> >
>> > in it.
>> >
>> > After that you have DEFSTRUCT and most of CL at your fingertips.
>> 
>> True, but not necessarily important.
>> 
>> Based on what is being done with the data structure at this point,
>> there doesn't appear to be a need for any of that, whether named
>> random access, via DEFSTRUCT, or numbered random access, via
>> #(vectors).
>> 
>
> Thanks to everyone who responded. The advice was very helpful. 
>
> Here's some background: My interest in Lisp is to solve a Perlish
> problem - take a datafile, transform it into a data structure that
> preserves some of the order of original data file, and traverse that
> data structure to produce a series of reports. CSV into HTML pages, to
> be precise.
>
> I think defstruct is too complicated for this data - diary entries.
> Vectors appear to be more useful than lists.

Sounds like it's overkill.

>> It seems to suffice to use a couple of nested DOLISTs to solve the
>> problem at hand.  
>> 
>> Nothing thus far suggests that there is a _real_ need to resort to
>> more sophisticated data types, though it's good that (require 'cl) can
>> get at them, if need be...
>
> Since the same operation is performed on every sublist, DOLIST is very
> helpful. A second, nested DOLIST (as I understand their syntax) won't
> work, because each field in the record will get a different format
> when it is printed. It would be nice to do this:
>
> (dolist (record table)
>   (dolist ((i j k) record)
>     (insert 
>       (concat 
>           "<h3>" i "</h3>"
>           "<p>" j "</p">
>           "<p>" k "</p>"
>       )
>     )
>   )
> )
>
> But you can't, can you?

Not directly as such.

What I'd do, for that, is to make a function to process each line,
thus:

(I'm using FORMAT, rather than insert/concat.  )

(defun showline (a b c)
  (format t "<h3> ~A </h3>  <p> ~A </p> <p> ~A </p> ~%" a b c))

Then I'd do 

(dolist (line big-whack-of-lines)
  (apply #'showline line))

Which (loosely speaking) destructures the contents into function
SHOWLINE.

That works in Common Lisp.  
> (setf a '((1 2 3) (4 5 6) (7 8 9) (10 11 12)))
((1 2 3) (4 5 6) (7 8 9) (10 11 12))
> (defun showline (a b c) (format t "<h3> ~A </h3>  <p> ~A </p> <p> ~A </p> ~%" a b c))
SHOWLINE
> (dolist (s a) (apply #'showline s))
<h3> 1 </h3>  <p> 2 </p> <p> 3 </p> 
<h3> 4 </h3>  <p> 5 </p> <p> 6 </p> 
<h3> 7 </h3>  <p> 8 </p> <p> 9 </p> 
<h3> 10 </h3>  <p> 11 </p> <p> 12 </p> 
NIL

I'm not sure apply works exactly thus in ELisp.  And FORMAT omits the
initial "which stream?" argumetn in Elisp.

You could alternatively embed the function as a lambda function, but
I'd frankly rather have a named function as it might be reusable.

Notice that not a single "CAR/CDR/NTH" occurs in the code.  Code with a
lot of list operators is sometimes characterized as "CADAVEROUS" code,
and it's no fun to read or write it.

I'd not go as far as "CAR Considered Harmful", although that's
probably not too distant from the truth.  GOTO statements suggest
difficult to maintain control structures; lots of CAR/CDRs suggest the
same.

If you _really_ wanted to get sophisticated, and do _exactly_ what you
suggested, you could do the destructuring "manually" using
DESTRUCTURING-BIND, which appears to be included in (require 'cl), but
that's not likely something for Day 1.  (Indeed, I suspect you'd find
it _exactly_ hits the spot.)

-- 
(reverse (concatenate 'string ··········@" "enworbbc"))
http://www.ntlug.org/~cbbrowne/
"Politics  is not a  bad  profession.  If  you succeed there  are many
rewards, if you disgrace yourself you can always write a book."
-- Ronald Reagan