From: John Connors
Subject: Lookup tables
Date: 
Message-ID: <4468c081$0$97584$ed2619ec@ptn-nntp-reader01.plus.net>
My first experience of Lisp was with a Lisp-1 on an 8 bit micro (please
don't guess how old that makes me), so Lisp-2 Common Lisp is confusing
me a bit.

Recently in a project in a galaxy quite close to home (actually, I was
patching Araneida to parse different content-types), I tried to set up a
lookup table, thusly

( ( "text/xml" . #'(lambda (rbody)  (parse-xml body) )
  ( "text/lisp" . #'(lambda (body) (read body) ) )

Although it was trivial to dig out the correct lambda form with ASSOC, I
just could not execute it, as the usual funcall/apply were complaining
that I was supplying a cons form to them, rather than a function.

The upshot is that I'm not sure how to code this idiom in a Lisp-2 : in
the end I created a package containing the parser functions bound to
|text/xml| and |text/lisp| and used symbol-function to look them up.

What are the other approaches? I'd really like to be able to do this
without having to create the package and symbols. William of Ockham is
muttering in his grave If all else fails guess it would be possible to
write a define-parser-function macro to hide the package and symbol
creation, but..

-- 
+--------------------------------------------------------+
|Cyborg Animation Programmer    |    ·····@yagc.ndo.co.uk|
|http://badbyteblues.blogspot.com -----------------------|
+--------------------------------------------------------+

From: JP Massar
Subject: Re: Lookup tables
Date: 
Message-ID: <5omh62pjusnnsqmu61doovc1fg8fcvrqeq@4ax.com>
On Mon, 15 May 2006 19:55:33 +0100, John Connors
<·····@yagc.ndo.co.uk> wrote:
 
>
>( ( "text/xml" . #'(lambda (rbody)  (parse-xml body) )
>  ( "text/lisp" . #'(lambda (body) (read body) ) )
>
 
(setq *my-table* 
  `( ( "text/xml" .  ,(lambda (rbody)  (parse-xml body)))
   (( "text/lisp" .  , (lambda (body) (read body) ) ) )
From: Kaz Kylheku
Subject: Re: Lookup tables
Date: 
Message-ID: <1147727736.342059.290660@j55g2000cwa.googlegroups.com>
John Connors wrote:
> My first experience of Lisp was with a Lisp-1 on an 8 bit micro (please
> don't guess how old that makes me), so Lisp-2 Common Lisp is confusing
> me a bit.
>
> Recently in a project in a galaxy quite close to home (actually, I was
> patching Araneida to parse different content-types), I tried to set up a
> lookup table, thusly
>
> ( ( "text/xml" . #'(lambda (rbody)  (parse-xml body) )
>   ( "text/lisp" . #'(lambda (body) (read body) ) )
>
> Although it was trivial to dig out the correct lambda form with ASSOC, I
> just could not execute it, as the usual funcall/apply were complaining
> that I was supplying a cons form to them, rather than a function.

That's not a Lisp-2 versus Lisp-1 problem. Function applicators in a
Lisp-1 do not like cons cells either!  Your table literal contains raw
lambda expressions.  FUNCALL needs a function object, not a lambda
expression, which is the source code that specifies a function object.

You solved the Lisp-2 versus Lisp-1 question already by using funcall
and hash-quote.

> The upshot is that I'm not sure how to code this idiom in a Lisp-2 : in

It won't work in a Lisp-1 either:

  (let ((text-xml '(lambda (rbody) (parse-xml body)))
    (text-xml body))

Here, the variable TEXT-XML holds a pointer to a CONS cell, which heads
the (LAMBDA ...) list.

Drop the quote in front of the lambda and you have something, because
now the lambda expression is evaluated to a function object.

> the end I created a package containing the parser functions bound to
> |text/xml| and |text/lisp| and used symbol-function to look them up.
>
> What are the other approaches?

The lambda expressions in your associative list literal have to be
reduced to functions, and that means that the #'(lambda ...)
expressions have to be evaluated. One way to do this is to use
backquote and unquote:

  (defvar *table* `(("text/html" ,#'(lambda (rbody)  (parse-xml body))
...))
From: Rainer Joswig
Subject: Re: Lookup tables
Date: 
Message-ID: <C08E92CD.3C72B%joswig@lisp.de>
Am 15.05.2006 20:55 Uhr schrieb "John Connors" unter <·····@yagc.ndo.co.uk>
in ·························@ptn-nntp-reader01.plus.net:

Do INSPECT the following forms after READing them :

'(#'(lambda (f) f))

(list #'(lambda (f) f))

`(,#'(lambda (f) f))

Maybe that helps answering your question?


> 
> My first experience of Lisp was with a Lisp-1 on an 8 bit micro (please
> don't guess how old that makes me), so Lisp-2 Common Lisp is confusing
> me a bit.
> 
> Recently in a project in a galaxy quite close to home (actually, I was
> patching Araneida to parse different content-types), I tried to set up a
> lookup table, thusly
> 
> ( ( "text/xml" . #'(lambda (rbody)  (parse-xml body) )
>   ( "text/lisp" . #'(lambda (body) (read body) ) )
> 
> Although it was trivial to dig out the correct lambda form with ASSOC, I
> just could not execute it, as the usual funcall/apply were complaining
> that I was supplying a cons form to them, rather than a function.
> 
> The upshot is that I'm not sure how to code this idiom in a Lisp-2 : in
> the end I created a package containing the parser functions bound to
> |text/xml| and |text/lisp| and used symbol-function to look them up.
> 
> What are the other approaches? I'd really like to be able to do this
> without having to create the package and symbols. William of Ockham is
> muttering in his grave If all else fails guess it would be possible to
> write a define-parser-function macro to hide the package and symbol
> creation, but..
From: ···········@gmail.com
Subject: Re: Lookup tables
Date: 
Message-ID: <1147745994.937957.54100@v46g2000cwv.googlegroups.com>
Rainer Joswig wrote:
> Am 15.05.2006 20:55 Uhr schrieb "John Connors" unter <·····@yagc.ndo.co.uk>
> in ·························@ptn-nntp-reader01.plus.net:
>
> Do INSPECT the following forms after READing them :
>
> '(#'(lambda (f) f))
>
> (list #'(lambda (f) f))
>
> `(,#'(lambda (f) f))
>
> Maybe that helps answering your question?

Thank you.  That was very educational.

Cheers
Vijay Lakshminarayanan

> Can we quote you on that?
A long time ago, someone in the Lisp industry told me it was poor form
quote people; it suggests that they lack value.
	-- Kent M Pitman <······@world.std.com> in comp.lang.lisp
From: Alan Crowe
Subject: Re: Lookup tables
Date: 
Message-ID: <86k68nqdmz.fsf@cawtech.freeserve.co.uk>
John Connors <·····@yagc.ndo.co.uk> writes:

> My first experience of Lisp was with a Lisp-1 on an 8 bit micro (please
> don't guess how old that makes me), so Lisp-2 Common Lisp is confusing
> me a bit.
> 
> Recently in a project in a galaxy quite close to home (actually, I was
> patching Araneida to parse different content-types), I tried to set up a
> lookup table, thusly
> 
> ( ( "text/xml" . #'(lambda (rbody)  (parse-xml body) )
>   ( "text/lisp" . #'(lambda (body) (read body) ) )
> 
> Although it was trivial to dig out the correct lambda form with ASSOC, I
> just could not execute it, as the usual funcall/apply were complaining
> that I was supplying a cons form to them, rather than a function.

You are trying to construct a data structure with actual
function objects in it. It usually goes more smoothly if you
construct a data structure containing symbols that name the
functions. For example:

CL-USER> (defun this (x)(format t "~&This ~A." x))
THIS

CL-USER> (defun that (x)(format t "~&That ~A." x))
THAT

CL-USER> (defparameter table '(("foo" . this)
                               ("bar" . that)))
TABLE

CL-USER> (funcall (cdr (assoc "foo" table :test #'string=)) "something")
This something.

The curious point is that the data structure is not typed in as

'(("foo" . 'this)
  ("bar" . 'that))

One quote (the initial one) is enough to quote the symbols
inside the data structure. Assoc finds a cons. Cdr digs out
a symbol. Funcall spots that it is being fobbed off with a
symbol, instead of the function object it really wants, and
copes by looking up the symbol in the global function name
space.

The implication of this is that when you say

(defparameter table '(("text/xml" . #'(lambda(body)(parse-xml body)

the #'(lambda(... is not in a position in which it gets
evaluated. So the evaluation of the defparameter form isn't
doing what you think. It is not building a data structure
with a function object in it. All that happens is that the
implicit read is building

(quote (("text/xml" . (function (lambda (body ....

which is a bit of source code, and the evaluation of the
defparameter form is doing hardly any work at all. It just
stores the source code built by READ in the variable TABLE.

Later all that you dig out with assoc and cdr (all that is
there to be dug out) is a list beginning with the symbol
FUNCTION.

Contrast

CL-USER> (funcall #'(lambda(x y)(+ x y)) 5 7)
12

Watch out for this quote
                  |
                  v
CL-USER> (funcall '#'(lambda(x y)(+ x y)) 5 7)
Type-error in KERNEL::OBJECT-NOT-TYPE-ERROR-HANDLER:
   #'(LAMBDA (X Y) (+ X Y)) is not of type (OR FUNCTION SYMBOL)

Perhaps you want to use backquote and comma

(defparameter table `(("foo" . ,#'(lambda(body)(print 'foo)(parse body)))
                      ("bar" . ,(form that gets evaluated))))
> 
> The upshot is that I'm not sure how to code this idiom in a Lisp-2 : in
> the end I created a package containing the parser functions bound to
> |text/xml| and |text/lisp| and used symbol-function to look them up.

It is not a Lisp-2 issue, you've merely got an extra layer
of quoting getting in the way.

The package approach looks to me like quite a nice idea. A
package is basically a look up table for looking up strings,
which is what you are doing.

CL-USER> (defpackage parsing-functions
           (:nicknames pf))
#<The PARSING-FUNCTIONS package, 0/9 internal, 0/2 external>

CL-USER> (defun pf::|xml| (body) (format t "~&Do xml stuff to ~A." body))
PARSING-FUNCTIONS::|xml|

CL-USER> (funcall (intern "xml" "PF") "<>...<>")
Do xml stuff to <>...<>.

> What are the other approaches? I'd really like to be able to do this
> without having to create the package and symbols.

Perhaps it is less work that you realised.

Alan Crowe
Edinburgh
Scotland