From: Trent Buck
Subject: cons-pairs in terms of lambda
Date: 
Message-ID: <20050104045401.5c21713a@harpo.marx>
Watching Sussman's 6.001 / SICP video lectures, I saw this and just
*had* to share it:

  ;; Scheme
  (define (cons a b)
    (lambda (c) (if c a b)))
  (define (car x) (x #t))
  (define (cdr x) (x #f))

  ;; Common Lisp
  (defun cons (a b)
    (lambda (c) (if c a b)))
  (defun car (x) (funcall x t))
  (defun cdr (x) (funcall x nil))

Wow.
-- 
-trent
I bought one of those camouflage shirts and put it in my closet. Now I
can't find it.

From: Christopher C. Stacy
Subject: Re: cons-pairs in terms of lambda
Date: 
Message-ID: <uu0pye5zm.fsf@news.dtpq.com>
Trent Buck <·········@tznvy.pbz> writes:

> Watching Sussman's 6.001 / SICP video lectures, I saw this and just
> *had* to share it:
> 
>   ;; Scheme
>   (define (cons a b)
>     (lambda (c) (if c a b)))
>   (define (car x) (x #t))
>   (define (cdr x) (x #f))
> 
>   ;; Common Lisp
>   (defun cons (a b)
>     (lambda (c) (if c a b)))
>   (defun car (x) (funcall x t))
>   (defun cdr (x) (funcall x nil))
> 
> Wow.

In Common Lisp, you're not allowed to redefine CONS 
in the COMMON-LISP package, so you would have to make 
a new CONS symbol in some other package.

But since Common Lisp has seperate namespaces for functions 
and variables, you can (without any new packages) use the
names CAR and CDR for those closed-over variables:

(defun my-cons (car cdr)
  (lambda (car-p) (if car-p car cdr)))
From: Trent Buck
Subject: Re: cons-pairs in terms of lambda
Date: 
Message-ID: <20050104053131.72a8156a@harpo.marx>
Up spake Christopher C. Stacy:
> In Common Lisp, you're not allowed to redefine CONS 
> in the COMMON-LISP package, so you would have to make 
> a new CONS symbol in some other package.

Yeah, I know.  But the ability to define such a fundamental data
structure in terms of a procedure is staggering (at least to me).

-- 
-trent
I thought it was raining outside, but it turned out just to be a cron job.
From: Kaz Kylheku
Subject: Re: cons-pairs in terms of lambda
Date: 
Message-ID: <1104779197.433133.36140@f14g2000cwb.googlegroups.com>
Trent Buck wrote:
> Up spake Christopher C. Stacy:
> > In Common Lisp, you're not allowed to redefine CONS
> > in the COMMON-LISP package, so you would have to make
> > a new CONS symbol in some other package.
>
> Yeah, I know.  But the ability to define such a fundamental data
> structure in terms of a procedure is staggering (at least to me).

The data structure is really just the captured lexical environment.
This will probably compile down to a two-element vector, same as a
cons.
From: Hannah Schroeter
Subject: Re: cons-pairs in terms of lambda
Date: 
Message-ID: <crc7jd$jbk$4@c3po.use.schlund.de>
Hello!

Trent Buck  <·········@tznvy.pbz> wrote:
>Watching Sussman's 6.001 / SICP video lectures, I saw this and just
>*had* to share it:

>  ;; Scheme
>  (define (cons a b)
>    (lambda (c) (if c a b)))
>  (define (car x) (x #t))
>  (define (cdr x) (x #f))

>  ;; Common Lisp
>  (defun cons (a b)
>    (lambda (c) (if c a b)))
>  (defun car (x) (funcall x t))
>  (defun cdr (x) (funcall x nil))

>Wow.

You can even do something like that without using the special form if!

(defun cons (a b)
  (lambda (selector) (funcall selector a b)))

(defun car (cons)
  (funcall cons (lambda (a b) a)))

(defun cdr (cons)
  (funcall cons (lambda (a b) b)))

Kind regards,

Hannah.
From: Steven M. Haflich
Subject: Re: cons-pairs in terms of lambda
Date: 
Message-ID: <cWlCd.6352$5R.296@newssvr21.news.prodigy.com>
Trent Buck wrote:

>   (defun cons (a b)
>     (lambda (c) (if c a b)))
>   (defun car (x) (funcall x t))
>   (defun cdr (x) (funcall x nil))

It is a little-remembered fact (IIRC) that arrays in MACLISP were
also funcallable objects, with a similar theoretical implementation
left as an exercise to the reader.

But I would prefer cons to have been implemented this way:

(defun cons (a b &key documentation)
   (lambda (c)
     (case c
       (car a)
       (cdr b)
       (documentation documentation))))
(defun car (x) (funcall x 'car))
(defun cdr (x) (funcall x 'cdr))
(defmethod documentation ((x cons) (type t))
   (funcall x 'documentation))

That way I could record why I consed a particular cons, and
what I intend to use it for.

As a side issue, I note that Graham's definition (and mine)
don't obey the ANS requirements on signalling errors in safe
code, etc. etc. etc.  Elegance is not necessarily conformant.
From: Kaz Kylheku
Subject: Re: cons-pairs in terms of lambda
Date: 
Message-ID: <1104875399.321919.62080@c13g2000cwb.googlegroups.com>
Steven M. Haflich wrote:
> Trent Buck wrote:
>
> >   (defun cons (a b)
> >     (lambda (c) (if c a b)))
> >   (defun car (x) (funcall x t))
> >   (defun cdr (x) (funcall x nil))
>
> It is a little-remembered fact (IIRC) that arrays in MACLISP were
> also funcallable objects, with a similar theoretical implementation
> left as an exercise to the reader.
>
> But I would prefer cons to have been implemented this way:
>
> (defun cons (a b &key documentation)
>    (lambda (c)
>      (case c
>        (car a)
>        (cdr b)
>        (documentation documentation))))
> (defun car (x) (funcall x 'car))
> (defun cdr (x) (funcall x 'cdr))
> (defmethod documentation ((x cons) (type t))
>    (funcall x 'documentation))
>
> That way I could record why I consed a particular cons, and
> what I intend to use it for.

How about a fourth field: an optional string containing the e-mail
address of the user whom to ask for permission when the cons is about
to be garbage-collected.

:)
From: Steven M. Haflich
Subject: Re: cons-pairs in terms of lambda
Date: 
Message-ID: <HBMCd.7416$yV1.1209@newssvr14.news.prodigy.com>
Kaz Kylheku wrote:

> How about a fourth field: an optional string containing the e-mail
> address of the user whom to ask for permission when the cons is about
> to be garbage-collected.

That's silly!  However, I did briefly consider this function signature

(defun cons (a b &key documentation documentation-car documentation-cdr)
   (lambda (c)
     (case c
       (car a)
       (cdr b)
       (documentation documentation)
       (documentation-car documentation-car)
       (documentation-cdr documentation-cdr)
       )))

which allows not only for the cons to be documented, but also
documentation specific to the content of he car and cdr of the
cons.  This further implies the existence of:

(defun (setf car) (new cons &key (documentation nil documentationp)
   (when documentationp (setf (documentation-car cons) documentation))
   ... ; internal primitive magic to do the actual setf
   )

but eventually, after long recursion, I realized that a proper
anal-retentive programmer would legitimately expect to be able to
document the documntation on the cae of a specific cons.  I'm
still thinking about this issue. and it may take me a long time to
get to the bottom of it.  I'll let you all know when I do...