home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #30 / NN_1992_30.iso / spool / comp / lang / lisp / 3117 < prev    next >
Encoding:
Text File  |  1992-12-21  |  8.5 KB  |  220 lines

  1. Path: sparky!uunet!newsflash.concordia.ca!mizar.cc.umanitoba.ca!access.usask.ca!cs.Usask.CA!coulman
  2. From: coulman@cs.Usask.CA (Randy Coulman)
  3. Newsgroups: comp.lang.lisp
  4. Subject: SUMMARY: Functions
  5. Date: 18 Dec 1992 18:50:33 GMT
  6. Organization: University of Saskatchewan
  7. Lines: 206
  8. Sender: coulman@skorpio (Randy Coulman)
  9. Distribution: world
  10. Message-ID: <1gt6hpINNn01@access.usask.ca>
  11. Reply-To: coulman@cs.Usask.CA
  12. NNTP-Posting-Host: skorpio.usask.ca
  13.  
  14. I recently posted a message here asking some questions about lambda
  15. expressions.  I promised a summary, so here it is (along with my
  16. original post).  Thank you to all who responded.  
  17.  
  18. --- Original message:
  19. I'm currently building an application using Allegro CL 4.1 and CLIM 1.1 on 
  20. a Sparc 1+.  One piece of functionality I need to include in my application
  21. is to allow users to specify and edit functions.  These functions would 
  22. ideally be lambda expressions.  Later, the application would use apply or 
  23. funcall to use the lambda expressions.  Unfortunately, the new standard says
  24. that lambda expressions are no longer valid function arguments to funcall
  25. and apply.  Instead, it is necessary to use #'(lambda ... instead of 
  26. '(lambda ...  I can easily make it a requirement that these functions need
  27. to be specified with #'.  However, this takes away the ability to later edit
  28. the function.  
  29.  
  30. As an example, my application uses a class of object called Observers.  Each 
  31. observer knows how to make one binary (i.e., t or nil) observation about the 
  32. real world.  This is accomplished through the use of an observer function 
  33. (ofun).  The application I'm building allows the user to define new
  34. observers, so they need to be able to define the ofun's as well.  E.g.:
  35.  
  36. Defining Observer...
  37. Name: Always
  38. Ofun: '(lambda (c)
  39.          (declare (ignore c))
  40.          t)
  41. ...
  42.  
  43. If I use #'(lambda ... above, then editing would look like this:
  44.  
  45. Editing Observer...
  46. Name: Always
  47. Ofun: #<Interpreted Function (unnamed) @ ...>
  48.  
  49. Am I missing something completely obvious about how to get around this 
  50. problem?  If not, can anyone suggest a reasonable work around?
  51.  
  52. The way I'm doing it now is to define these functions in a source file,
  53. giving them names (strings) and storing them in a hash table.  If the user
  54. wants to define new functions, they have to edit the source file before
  55. loading the system.  This is not acceptable.
  56.  
  57. Thanks in advance for any help.
  58.  
  59. --- Timothy B. Moore replied:
  60. Use eval. That's what funcall and apply did when you could pass lambda
  61. expressions to them.
  62. ---
  63. That's an obvious solution.  I don't know if I thought of it, but I have an
  64. incredible aversion to eval, so I may have just dismissed the idea as soon
  65. as I thought of it.
  66.  
  67. --- Eyvind Ness replied:
  68. I think this is mentioned in the FAQ, but anyway:
  69.  
  70. If you have a lambda list, like '(lambda (c) (declare (ignore c)) t),
  71. and want to funcall or apply it, simply use:
  72.  
  73. (apply/funcall (coerce '(lambda (c) (declare (ignore c)) t) 'function) ...)
  74.  
  75. In CMU CL (the only Lisp I have that is strictly CLtL2 compliant), I
  76. get:
  77.  
  78.    magica(bash)$ lisp
  79.    ;; Loading "/nfs/lilleulv/users/eyvind/init.lisp".
  80.    ;;; Sun 13-Dec-92  2:36:26 PM
  81.    CMU Common Lisp 16e, running on magica
  82.    Send bug reports and questions to your local CMU CL maintainer, or to
  83.    cmucl-bugs@cs.cmu.edu.
  84.    Loaded subsystems:
  85.        Python 1.0, target SPARCstation/Sun 4
  86.        CLOS based on PCL version:  March 92 PCL (2a)
  87.    * (funcall '(lambda (c) (declare (ignore c)) t) nil)
  88.  
  89.    Type-error in "DEFUN FUNCALL":
  90.       (LAMBDA (C) (DECLARE (IGNORE C)) T) is not of type (OR FUNCTION SYMBOL)
  91.  
  92.    Restarts:
  93.      0: [ABORT] Return to Top-Level.
  94.  
  95.    Debug  (type H for help)
  96.  
  97.    ("DEFUN FUNCALL" (LAMBDA (C) (DECLARE #) T) 3670168 1)[:OPTIONAL]
  98.    0] q
  99.  
  100.    * (funcall (coerce '(lambda (c) (declare (ignore c)) t) 'function) nil)
  101.  
  102.    T
  103.    * 
  104.  
  105. as expected.
  106. ---
  107.  
  108. I like this idea.  It is probably the way I'll go.  I never even thought of
  109. coerce, but it makes sense.
  110.  
  111. --- Barry Margolin replied:
  112. In dpANS CL, you can convert a lambda expression to a function with (COERCE
  113. <lambda-exp> 'FUNCTION).  You can also use (COMPILE NIL <lambda-exp>).
  114.  
  115. In CLtL1 CL you can get the equivalent of the COERCE with
  116.  
  117. (eval `#',<lambda-exp>)
  118.  
  119. In order for you to allow users to edit the functions later, you can
  120. remember the original lambda expressions in a table keyed off the function.
  121. ---
  122.  
  123. As above, I like this idea best.
  124.  
  125. --- donc@ISI.EDU replied:
  126. The problem here is that you seem to think that the function to be applied
  127. must be the SAME as its specification.  Why not read in the specifications
  128. as lambda expressions, but then process them a little more (in addition to
  129. what read does) to get functions?  You certainly have to keep the source
  130. form (the lambda expression read as a list, or the characters from which 
  131. read produced the list) in order to allow the user to edit it.  However,
  132. after you read it you can make a functional version for use by apply.
  133. There are two ways to do this.  One is compile.  The other is coerce (to
  134. type function).
  135. ---
  136.  
  137. I did realize that I would have to do something with the lambda expression
  138. that I read in.  The problem was that I didn't know what that something
  139. would be.  Again, I'll likely use the coerce solution.
  140.  
  141. --- John (postmaster@aspen.CS.Berkeley.EDU replied:
  142. Don't use funcall, use eval instead!
  143. I assume you aren't trying to export local variables and so just
  144. say: (eval `(,result ,argument)) where "argument" is the value
  145. you want passed in as "c", and "result" is the list "(lambda (c) ..."
  146. returned after the editing session.
  147.  
  148. John
  149. ---
  150.  
  151. As above, I have this aversion to eval.  But this option would do the trick
  152. as well.
  153.  
  154. --- Bruce Krulwich replied:
  155. Your approach strikes me as dangerous.  What about name overlaps?  What about
  156. the user doing something that would kill the system?
  157.  
  158. If it were me, I would probably write my own small interpreter for the
  159. functions the user is writing.  Actually, there are plenty of small rule
  160. interpreters around -- all you'd have to add were whatever looping constructs
  161. or other high-level constructs you wanted.
  162.  
  163. Once you have a small vocabulary for rules the user is defining, you could in
  164. fact make a small compiler for them, that decomposes the rules the user enters
  165. and constructs actual closures using LAMBDAs.  The value of doing this depends
  166. on how critical speed is and how rich your rule vocabulary is.
  167.  
  168. I hope this was clear and helps.
  169. ---
  170.  
  171. This was a very interesting reply.  I hadn't thought a lot about these kind
  172. of issues.  This is a research system that would only be used by knowledge
  173. engineers, so I think I can assume that there won't be any malicious
  174. intent.  If we decide to distribute this system a little more widely, then
  175. I'll have to reconsider these issues.
  176.  
  177. There are some problems here, though.  In general, any operations that will
  178. be performed in these functions will be (no-side-effect) operations on the
  179. argument to the function.  However, in some cases, there are side effects
  180. that would be desired.  For example, one system we are building with this
  181. environment uses these observers to recognize primitive Lisp things.  There
  182. would have to be observers that can recognize the name of a defined
  183. function and its arguments.  However, there also needs to be observers that
  184. can recognize a recursive call to this function and other calls using the
  185. function's arguments.  In this case, the observers which originally
  186. recognize the function name and argument list must somehow store this
  187. information for the other observers to access.
  188.  
  189. This application is a knowledge-engineering toolkit, and we intend it to be
  190. extensible/customizable for different application domains.  Thus, we don't
  191. want to put any a priori constraints on what these observers can and cannot
  192. do.  For example, in the Lisp domain again, the observer may want to
  193. recognize recursion by tracing the execution of the function to see if it
  194. calls itself somewhere.
  195.  
  196. This response did make me think about these sort of issues, however, and I
  197. appreciate that.
  198.  
  199. --- Richard Lynch replied:
  200.  
  201. I think if you keep the lambda list for editing, and call it with:
  202.  
  203. (funcall (function <lambda-list>) <args?>)
  204.           ^^^^^^^^
  205. this should work.
  206. ---
  207.  
  208. I thought of this as well, but function doesn't evaluate its argument.
  209.  
  210. Thanks again for all of the replies.  I haven't had a chance to implement
  211. the suggestions contained here, but will do so in the near future.
  212.  
  213. Randy
  214.  
  215. -- 
  216. Randy A. Coulman                |       ARIES Laboratory
  217. Research Assistant              |       Department of Computational Science
  218.                                 |       University of Saskatchewan
  219. coulman@cs.Usask.ca             |       Saskatoon, SK   S7N 0W0             
  220.