From: Chris Beggy
Subject: replace helper fn with flet or labels
Date: 
Message-ID: <8765sah2z7.fsf@lackawana.kippona.com>
I want to read a list and return a list of cons pairs:

  (a b c d e f) -> ((a . b) (c . d) (e . f))
  (a b c d e f g) -> ((a . b) (c . d) (e . f) (g . ""))

This function kind of works:

(defun process-form-x (x)
  "create a list of (key . value) pairs from a list"
    (cond ((endp x) nil);; terminate on empty list
	((not (endp (rest x))) ;; recurse if there are at least two left
	       ( cons (cons (first x) (second x)) 
		      (process-form-x (rest (rest x)))))))

but if the list has an odd number of members, I want to pair the
last member with "".  The function above just drops the last
member of a list with an odd number of members.

I can use the helper function to test and fix the input list:

(defun help-form (x)
  (if (oddp (length x))
      (process-form-x (append x '("")))
      (process-form-x x)))

I wanted to try to make the process-form-x function do this, so I
tried flet:

(defun myprocess (formdata)
  (let ((evendat (if (oddp (length formdata))
			   (append formdata '(""))
		   formdata)))
    (flet (flet-url (x)
      (cond ((endp x) nil)
	    ((not (endp (rest x)))
	     (cons (cons (first x) (second x))
		   (flet-url (rest (rest x)))))))
    flet-url evendat)))

and labels:

(defun myprocesslabel (formdata)
  (let ((evendat (if (oddp (length formdata))
		     (append formdata '(""))
		   formdata)))
    (labels ((process-x (x)
	      (if (endp x) nil
		(cons (cons (first x) (second x))
		      (process-x (rest (rest x))))))
  process-x evendat))))

but neither of these works.  Any ideas?  Is using flet and labels
the right approach?  Should I just be happy with the helper
function calling the recursive function and stop there?  Should I
use loop to walk through a list, rather than try recursion?

Thanks.

Chris

From: Erann Gat
Subject: Re: replace helper fn with flet or labels
Date: 
Message-ID: <gat-2701031032480001@k-137-79-50-101.jpl.nasa.gov>
In article <··············@lackawana.kippona.com>, Chris Beggy
<······@kippona.com> wrote:

> I want to read a list and return a list of cons pairs:
> 
>   (a b c d e f) -> ((a . b) (c . d) (e . f))
>   (a b c d e f g) -> ((a . b) (c . d) (e . f) (g . ""))
> 
> This function kind of works:
> 
> (defun process-form-x (x)
>   "create a list of (key . value) pairs from a list"
>     (cond ((endp x) nil);; terminate on empty list
>         ((not (endp (rest x))) ;; recurse if there are at least two left
>                ( cons (cons (first x) (second x)) 
>                       (process-form-x (rest (rest x)))))))

...

> but neither of these works.  Any ideas?  Is using flet and labels
> the right approach?

No.  You're trying too hard.  The problem is that your recursion has two
base cases, but you are only handling one of them:

(defun process-form-x (x)
  "create a list of (key . value) pairs from a list"
  (cond ((endp x) nil);; terminate on empty list

          INSERT AN EXTRA COND CLAUSE HERE TO HANDLE THE CASE WHERE
          (endp (rest x)) IS TRUE.

        ((not (endp (rest x))) ;; recurse if there are at least two left
         ( cons (cons (first x) (second x)) 
                (process-form-x (rest (rest x)))))))

E.
From: JP Massar
Subject: Re: replace helper fn with flet or labels
Date: 
Message-ID: <3e357c90.412240882@netnews.attbi.com>
On Mon, 27 Jan 2003 13:17:16 -0500, Chris Beggy <······@kippona.com>
wrote:

>I want to read a list and return a list of cons pairs:
>
>  (a b c d e f) -> ((a . b) (c . d) (e . f))
>  (a b c d e f g) -> ((a . b) (c . d) (e . f) (g . ""))
>
>This function kind of works:
>
>(defun process-form-x (x)
>  "create a list of (key . value) pairs from a list"
>    (cond ((endp x) nil);; terminate on empty list
>	((not (endp (rest x))) ;; recurse if there are at least two left
>	       ( cons (cons (first x) (second x)) 
>		      (process-form-x (rest (rest x)))))))
>

Anything wrong with
 
(defun foo (x)
  (cond
   ((endp x) nil)
   ((endp (cdr x)) (list (cons (first x) "")))
   (t (cons (cons (first x) (second x)) (foo (cddr x))))
   ))

?
From: Kenny Tilton
Subject: Re: replace helper fn with flet or labels
Date: 
Message-ID: <3E358771.9010808@nyc.rr.com>
JP Massar wrote:
> On Mon, 27 Jan 2003 13:17:16 -0500, Chris Beggy <······@kippona.com>
> wrote:
> 
> 
>>I want to read a list and return a list of cons pairs:
>>
>> (a b c d e f) -> ((a . b) (c . d) (e . f))
>> (a b c d e f g) -> ((a . b) (c . d) (e . f) (g . ""))
>>
>>This function kind of works:
>>
>>(defun process-form-x (x)
>> "create a list of (key . value) pairs from a list"
>>   (cond ((endp x) nil);; terminate on empty list
>>	((not (endp (rest x))) ;; recurse if there are at least two left
>>	       ( cons (cons (first x) (second x)) 
>>		      (process-form-x (rest (rest x)))))))
>>
> 
> 
> Anything wrong with
>  
> (defun foo (x)
>   (cond
>    ((endp x) nil)
>    ((endp (cdr x)) (list (cons (first x) "")))
>    (t (cons (cons (first x) (second x)) (foo (cddr x))))
>    ))
> 
> ?

That can be normalized (one consing up of a new entry instead of two) by 
moving the odd-handling closer to the "" insertion, which I think is a 
whisker more self-documenting as well:

(defun foo (x)
   (cond
    ((endp x) nil)
    ((endp (cdr x)) (list (cons (first x) "")))
    (t (cons (cons (first x)
                   (if (endp (cdr x))
                      "" (second x)))
             (foo (cddr x))))))

...And no one asked for this, but this is what the above looks like in 
Lisp ,g>:

(defun foo (x)
   (when x
    (cons (cons (first x) (or (second x) ""))
     (foo (cddr x)))))


-- 

  kenny tilton
  clinisys, inc
  http://www.tilton-technology.com/
  ---------------------------------------------------------------
"Cells let us walk, talk, think, make love and realize
  the bath water is cold." -- Lorraine Lee Cudmore
From: Kenny Tilton
Subject: Re: replace helper fn with flet or labels
Date: 
Message-ID: <3E3588C4.3060006@nyc.rr.com>
Sorry, I stopped editing half-way (one-third?) thru:

Kenny Tilton wrote:
> 
> 
> JP Massar wrote:
> 
>> On Mon, 27 Jan 2003 13:17:16 -0500, Chris Beggy <······@kippona.com>
>> wrote:
>>
>>
>>> I want to read a list and return a list of cons pairs:
>>>
>>> (a b c d e f) -> ((a . b) (c . d) (e . f))
>>> (a b c d e f g) -> ((a . b) (c . d) (e . f) (g . ""))
>>>
>>> This function kind of works:
>>>
>>> (defun process-form-x (x)
>>> "create a list of (key . value) pairs from a list"
>>>   (cond ((endp x) nil);; terminate on empty list
>>>     ((not (endp (rest x))) ;; recurse if there are at least two left
>>>            ( cons (cons (first x) (second x))               
>>> (process-form-x (rest (rest x)))))))
>>>
>>
>>
>> Anything wrong with
>>  
>> (defun foo (x)
>>   (cond
>>    ((endp x) nil)
>>    ((endp (cdr x)) (list (cons (first x) "")))
>>    (t (cons (cons (first x) (second x)) (foo (cddr x))))
>>    ))
>>
>> ?
> 
> 
> That can be normalized (one consing up of a new entry instead of two) by 
> moving the odd-handling closer to the "" insertion, which I think is a 
> whisker more self-documenting as well:
> 
> (defun foo (x)
>   (cond
>    ((endp x) nil)
>    ((endp (cdr x)) (list (cons (first x) "")))
>    (t (cons (cons (first x)
>                   (if (endp (cdr x))
>                      "" (second x)))
>             (foo (cddr x))))))

Should be (mimicking original as closely as possible):

(defun foo (x)
   (cond
    ((endp x) nil)
    (t (cons (cons (first x)
                   (if (endp (cdr x))
                      "" (second x)))
             (foo (cddr x))))))

Which still becomes:

> 
> ....And no one asked for this, but this is what the above looks like in 
> Lisp ,g>:
> 
> (defun foo (x)
>   (when x
>    (cons (cons (first x) (or (second x) ""))
>     (foo (cddr x)))))
> 
> 


-- 

  kenny tilton
  clinisys, inc
  http://www.tilton-technology.com/
  ---------------------------------------------------------------
"Cells let us walk, talk, think, make love and realize
  the bath water is cold." -- Lorraine Lee Cudmore
From: Peter Seibel
Subject: Re: replace helper fn with flet or labels
Date: 
Message-ID: <m31y2ycsiu.fsf@localhost.localdomain>
Chris Beggy <······@kippona.com> writes:

> I want to read a list and return a list of cons pairs:
> 
>   (a b c d e f) -> ((a . b) (c . d) (e . f))
>   (a b c d e f g) -> ((a . b) (c . d) (e . f) (g . ""))
> 
> This function kind of works:
> 
> (defun process-form-x (x)
>   "create a list of (key . value) pairs from a list"
>     (cond ((endp x) nil);; terminate on empty list
> 	((not (endp (rest x))) ;; recurse if there are at least two left
> 	       ( cons (cons (first x) (second x)) 
> 		      (process-form-x (rest (rest x)))))))
> 
> but if the list has an odd number of members, I want to pair the
> last member with "".  The function above just drops the last
> member of a list with an odd number of members.

[snip]

> Any ideas? Is using flet and labels the right approach? Should I
> just be happy with the helper function calling the recursive
> function and stop there? Should I use loop to walk through a list,
> rather than try recursion?
> 

How about (to answer your last question first):

(defun make-pairs (list)
  (loop while list collect (cons (pop list) (or (pop list) ""))))

Or, if you really want to go with your original approach (which
suffers a bit from having to repeatedly scan the length of the list,
once to determine it's length and once to append the "" on the end
when it's got an odd number of elements) you need to use labels (not
flet) and you need to fix the syntax of your call to process-x in the
last line: you need an opening parenthesis before the call to
process-x.

-Peter

-- 
Peter Seibel
·····@javamonkey.com
From: Tim Daly, Jr.
Subject: Re: replace helper fn with flet or labels
Date: 
Message-ID: <wkd6mhtlij.fsf@tenkan.org>
Peter Seibel <·····@javamonkey.com> writes:

> Chris Beggy <······@kippona.com> writes:
> 
> > I want to read a list and return a list of cons pairs:
> > 
> >   (a b c d e f) -> ((a . b) (c . d) (e . f))
> >   (a b c d e f g) -> ((a . b) (c . d) (e . f) (g . ""))
> > 

[snip]

> How about (to answer your last question first):
> 
> (defun make-pairs (list)
>   (loop while list collect (cons (pop list) (or (pop list) ""))))

That's very concise and nice.  I would normally write something like
this:

(defun zip (ai &optional result)
  (if ai
      (zip (cddr ai) 
           (cons (cons (car ai) (or (cadr ai) "")) result))
    (reverse result)))

I tried out both of them on lispworks, and, interestingly enough,
yours conses about 50% less.  Any idea why?

-Tim
From: Nils Goesche
Subject: Re: replace helper fn with flet or labels
Date: 
Message-ID: <lyadhlibby.fsf@cartan.de>
···@tenkan.org (Tim Daly, Jr.) writes:

> Peter Seibel <·····@javamonkey.com> writes:
> 
> > (defun make-pairs (list)
> >   (loop while list collect (cons (pop list) (or (pop list) ""))))
> 
> That's very concise and nice.  I would normally write something like
> this:
> 
> (defun zip (ai &optional result)
>   (if ai
>       (zip (cddr ai) 
>            (cons (cons (car ai) (or (cadr ai) "")) result))
>     (reverse result)))
> 
> I tried out both of them on lispworks, and, interestingly enough,
> yours conses about 50% less.  Any idea why?

Try NREVERSE...

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x0655CFA0
From: Nils Goesche
Subject: Re: replace helper fn with flet or labels
Date: 
Message-ID: <ly65s9iavn.fsf@cartan.de>
I <······@cartan.de> wrote:

> ···@tenkan.org (Tim Daly, Jr.) writes:
> 
> > Peter Seibel <·····@javamonkey.com> writes:
> > 
> > > (defun make-pairs (list)
> > >   (loop while list collect (cons (pop list) (or (pop list) ""))))
> > 
> > That's very concise and nice.  I would normally write something like
> > this:
> > 
> > (defun zip (ai &optional result)
> >   (if ai
> >       (zip (cddr ai) 
> >            (cons (cons (car ai) (or (cadr ai) "")) result))
> >     (reverse result)))
> > 
> > I tried out both of them on lispworks, and, interestingly enough,
> > yours conses about 50% less.  Any idea why?
> 
> Try NREVERSE...

And it is a bit unclear whether

> (make-pairs '(a b c nil d))
((A . B) (C . "") (D . ""))

is actually the desired result!?

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x0655CFA0
From: Nils Goesche
Subject: Re: replace helper fn with flet or labels
Date: 
Message-ID: <ly1y2yjuu5.fsf@cartan.de>
Chris Beggy <······@kippona.com> writes:

> I want to read a list and return a list of cons pairs:
> 
>   (a b c d e f) -> ((a . b) (c . d) (e . f))
>   (a b c d e f g) -> ((a . b) (c . d) (e . f) (g . ""))
> 
> This function kind of works:
> 
> (defun process-form-x (x)
>   "create a list of (key . value) pairs from a list"
>     (cond ((endp x) nil);; terminate on empty list
> 	((not (endp (rest x))) ;; recurse if there are at least two left
> 	       ( cons (cons (first x) (second x)) 
> 		      (process-form-x (rest (rest x)))))))
> 
> but if the list has an odd number of members, I want to pair the
> last member with "".  The function above just drops the last
> member of a list with an odd number of members.

You could write something like this:

(defun process-form (list)
  (cond ((null list) ...)
        ((null (cdr list)) ...)
        (t ...)))

> Any ideas?  Is using flet and labels the right approach?

Too complicated, I'd say.

> Should I just be happy with the helper function calling the
> recursive function and stop there?  Should I use loop to walk
> through a list, rather than try recursion?

You could also do something like

(loop for (elt . rest) on some-list by #'cddr
      collect (cons elt ...))

which would be much better than recursion in this case.  If you insist
on using recursion, make it at least tail-recursive:

(defun process-form (list)
  (labels ((do-it (list acc)
             (cond ((null list) acc)
                   ((null (cdr list)) (acons (car list) "" acc))
                   (t (do-it ... ...)))))
    (nreverse (do-it list nil))))

Filling the ... is left as an exercise for the reader :-)

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x0655CFA0
From: sv0f
Subject: Re: replace helper fn with flet or labels
Date: 
Message-ID: <none-2801031229080001@129.59.212.53>
In article <··············@lackawana.kippona.com>, Chris Beggy
<······@kippona.com> wrote:

>I want to read a list and return a list of cons pairs:
>
>  (a b c d e f) -> ((a . b) (c . d) (e . f))
>  (a b c d e f g) -> ((a . b) (c . d) (e . f) (g . ""))

How about an iterative solution with DO*:

? (defun consecutive-pairs (lis)
    (do* ((lis1 lis (cddr lis1))
          (item1 (first lis1) (first lis1))
          (lis2 (cdr lis1) (cdr lis1))
          (item2 (first lis2) (first lis2))
          (pairs (list (cons item1 (if lis2 item2 "")))
                 (cons (cons item1 (if lis2 item2 "")) pairs)))
         ((<= (length lis1) 2) (nreverse pairs))))
CONSECUTIVE-PAIRS
? (consecutive-pairs '(1 2 3 4))
((1 . 2) (3 . 4))
? (consecutive-pairs '(1 2 3 4 5))
((1 . 2) (3 . 4) (5 . ""))
? (consecutive-pairs '(1 2 nil 4))
((1 . 2) (NIL . 4))
? (consecutive-pairs '(1 2 nil 4 5))
((1 . 2) (NIL . 4) (5 . ""))
? (consecutive-pairs '(1 2 3 nil))
((1 . 2) (3))
? (consecutive-pairs '(1 2 4 nil 5))
((1 . 2) (4) (5 . ""))
? 

The function could be written a bit more concisely as:

? (defun consecutive-pairs (lis)
    (do* ((lis1 lis (cddr lis1))
          (pairs (list (cons (first lis1) (if (rest lis1) (second lis1) "")))
                 (cons (cons (first lis1) (if (rest lis1) (second lis1)
"")) pairs)))
         ((<= (length lis1) 2) (nreverse pairs))))
CONSECUTIVE-PAIRS
?
From: sv0f
Subject: Re: replace helper fn with flet or labels
Date: 
Message-ID: <none-2801031232120001@129.59.212.53>
In article <·····················@129.59.212.53>, ····@vanderbilt.edu
(sv0f) wrote:

>How about an iterative solution with DO*:
>
>? (defun consecutive-pairs (lis)
>    (do* ((lis1 lis (cddr lis1))
>          (item1 (first lis1) (first lis1))
>          (lis2 (cdr lis1) (cdr lis1))
>          (item2 (first lis2) (first lis2))
>          (pairs (list (cons item1 (if lis2 item2 "")))
>                 (cons (cons item1 (if lis2 item2 "")) pairs)))
>         ((<= (length lis1) 2) (nreverse pairs))))
>CONSECUTIVE-PAIRS
>? (consecutive-pairs '(1 2 3 4))
>((1 . 2) (3 . 4))
>? (consecutive-pairs '(1 2 3 4 5))
>((1 . 2) (3 . 4) (5 . ""))
>? (consecutive-pairs '(1 2 nil 4))
>((1 . 2) (NIL . 4))
>? (consecutive-pairs '(1 2 nil 4 5))
>((1 . 2) (NIL . 4) (5 . ""))
>? (consecutive-pairs '(1 2 3 nil))
>((1 . 2) (3))
>? (consecutive-pairs '(1 2 4 nil 5))
>((1 . 2) (4) (5 . ""))
>? 

It never fails.  My function fails for the simplest input:

?  (consecutive-pairs ())
((NIL . ""))

Fixing it is left as an exercise to the reader ;-)