Subject: Re: Creating functions at runtime
From: Erik Naggum <erik@naggum.no>
Date: 06 Oct 2002 01:10:27 +0000
Newsgroups: comp.lang.lisp
Message-ID: <3242855427179406@naggum.no>

* Henrik Motakef
| Trying to learn about the "Code as Data" feature of CL, I'd like to have
| some feedback if I'm on the right track or already misusing things.

  There are at least two different ways to look at this.  The first is to
  realize that a compiler will expect to read code and then examine the
  mechanisms by which the compiler reads code.  Common Lisp has the
  function `read´ which is used by the compiler to read the code.  By
  making this an ordinary part of the language and exporting it to the
  environment that ordinary users can use, too, programs that need to work
  on code can use it to read code and be able to work with it without
  having to duplicate the work the compiler needs to do to read code.  You
  realize that this in sharp contrast to most other programming languages,
  which generally do not contain neither functionality nor the system types
  to deal with source code.  This leads us to the second way to look at
  code is data.  The fundamental data type for source code is the list, and
  this is the same list as user programs work with.  (Some therefore think
  that the only data type in Lisp is the list, but even though we do not
  represent source code with vectors or strings, these types are just as
  fundamental to the programmers as the list.  Just wanted to clear that
  thing up preventatively.)  Since the functions to manipulate the list are
  ordinary parts of the languages and exported to the user environment like
  `read´, there is some functionality waiting to happen like an emergent
  property of the language: functions called by the compiler to operate on
  the code being compiled.  Languages without `read´ invent some complex
  rewriting systems and a lot of theory to go with them, but Common Lisp
  offers the programmer the /macro/, which processes an expression in the
  language as data, but it really is code and momentarily be turned into
  machine code by the compiler.  This leads to yet another way to look at
  "code is data", because functions are also ordinary language objects and
  may be passed around at will.  This is usually referred to as first-order
  functions and not usually as "code is data".  Then there is `eval´, of
  course, but I personally think that this is not the regular meaning of
  "code is data", either.  Common Lisp would have "code is data" even if
  you did not have `eval´ or the compiler available at run-time.

| Pretending *names* might be huge and testing whether an argument is nil
| might be expensive, I don't want to do the test for every name, so the
| general idea is to first build some function based on the passed
| arguments that returns whether a given name matches, and use this to
| filter the list of names, like this:

  Although testing for `nil´ is among the fastest things a Common Lisp
  program can do, it will probably slow things down a bit, so this is not
  an unreasonable plan.  However, actually constructing the code at runtime
  is not a good idea in this particular case.  Much better techniques are
  available.  For instance, while you have seen that you can create a
  /predicate/ according to the parameters, there are other options.

(defun get-matching-name (first-name last-name)
  (cond
   ((and first-name last-name)
    ;; if multiple matches for one full name are possible, use
    ;; (remove (list first-name last-name) *names* :test-not #'equal)
    (find (list first-name last-name) *names* :test #'equal))
   (first-name
    (remove first-name *names* :test #'string/= :key #'first))
   (last-name
    (remove last-name *names* :test #'string/= :key #'second))
   (t
    *names*)))

  It really would be useful to agree on a name for the opposite of
  `remove´/`delete´, like perhaps `collect´/`retain´.

| While this might be not optimal [...], it doesn't look too bad, IMHO.

  I think run-time construction of functions like this should be done when
  you have an input language that is more complex to handle than the code
  that would process it as an interpreted mini-language.

| One thing that still bugs me is the use of EVAL.

  Note that (compile nil '(lambda ...)) produces a compiled function.

| Given that EVAL doesn't seem to have a better reputation among CLers than
| it's equivalents in other languages, I wonder: is there a better way to
| get a function from a list built at runtime?

  `eval´ is perfectly acceptable when the purpose is to evaluate user code
  or expressions from an input language.  As a general principle: If the
  code you evaluate does not come from a run-time source, you should not
  perform run-time evaluation of it, either.

[ If you should dislike the tone or any part or aspect of the contents of
  this message so much that you feel compelled to attack or denounce me
  instead of staying focuesd on the questions you asked and the purpose you
  had when you asked them, please do not post your hostility. ]

-- 
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.