30.11. Additional Fancy Macros and Functions

30.11.1. Macro EXT:ETHE
30.11.2. Macros EXT:LETF & EXT:LETF*
30.11.3. Macro EXT:MEMOIZED
30.11.4. Macro EXT:WITH-COLLECT
30.11.5. Macro EXT:WITH-GENSYMS
30.11.6. Function EXT:REMOVE-PLIST
30.11.7. Macros EXT:WITH-HTML-OUTPUT and EXT:WITH-HTTP-OUTPUT
30.11.8. Function EXT:OPEN-HTTP and macro EXT:WITH-HTTP-INPUT
30.11.9. Function EXT:BROWSE-URL
30.11.10. Variable CUSTOM:*HTTP-PROXY*

CLISP comes with some extension macros, mostly defined in the file macros3.lisp and loaded from the file init.lisp during make:

30.11.1. Macro EXT:ETHE

(EXT:ETHE value-type form) enforces a type check in both interpreted and compiled code.

30.11.2. Macros EXT:LETF & EXT:LETF*

These macros are similar to LET and LET*, respectively, except that they can bind places, even places with multiple values. Example:

(letf (((values a b) form)) ...)

is equivalent to

(multiple-value-bind (a b) form ...)

while

(letf (((first l) 7)) ...)

is approximately equivalent to

 (LET* ((#:g1 l) (#:g2 (first #:g1)))
   (UNWIND-PROTECT (PROGN (SETF (first #:g1) 7) ...)
      (SETF (first #:g1) #:g2)))

30.11.3. Macro EXT:MEMOIZED

(EXT:MEMOIZED form) memoizes the primary value of form from its first evaluation.

30.11.4. Macro EXT:WITH-COLLECT

Similar to the LOOP's collect construct, except that it is looks more "Lispy" and can appear arbitrarily deep. It defines local macros (with MACROLET) which collect objects given to it into lists, which are then returned as multiple values. E.g.,

(ext:with-collect (c0 c1)
  (dotimes (i 10) (if (oddp i) (c0 i) (c1 i))))
⇒ (1 3 5 7 9) ;
⇒ (0 2 4 6 8)

returns two LISTs (1 3 5 7 9) and (0 2 4 6 8) as multiple values.

30.11.5. Macro EXT:WITH-GENSYMS

Similar to its namesake from Paul Graham's book On Lisp, this macro is useful for writing other macros:

(with-gensyms ("FOO-" bar baz zot) ...)

expands to

(let ((bar (gensym "FOO-BAR-"))
      (baz (gensym "FOO-BAZ-"))
      (zot (gensym "FOO-ZOT-")))
  ...)

30.11.6. Function EXT:REMOVE-PLIST

Similar to REMOVE and REMF, this function removes some properties from a property list. It is non-destructive and thus can be used on &REST arguments to remove some keyword parameters, e.g.,

(defmacro with-foo ((&KEY foo1 foo2) &BODY body)
  `(... ,foo1 ... ,foo2 ... ,@body))
(defmacro with-foo-bar ((&REST opts &KEY bar1 bar2
                         &ALLOW-OTHER-KEYS)
                        &BODY body)
  `(with-foo (,@(remove-plist opts :bar1 :bar2)
     ... ,bar1 ... ,bar2 ... ,@body)))
(defun foo-bar ()
  (with-foo-bar (:bar1 1 :foo2 2) ...))

here WITH-FOO does not receive the :BAR1 1 argument from FOO-BAR.

30.11.7. Macros EXT:WITH-HTML-OUTPUT and EXT:WITH-HTTP-OUTPUT

Defined in inspect.lisp, these macros are useful for the rudimentary HTTP server defined there.

30.11.8. Function EXT:OPEN-HTTP and macro EXT:WITH-HTTP-INPUT

Defined in clhs.lisp, they allow downloading data over the Internet using the HTTP protocol. (EXT:OPEN-HTTP url &KEY :IF-DOES-NOT-EXIST) opens a socket connection to the url host, sends the GET request, and returns two values: the SOCKET:SOCKET-STREAM and content length. (EXT:WITH-HTTP-INPUT (variable url) &BODY body) binds variable to the SOCKET:SOCKET-STREAM returned by EXT:OPEN-HTTP and executes the body. (EXT:WITH-HTTP-INPUT ((variable contents) url) &BODY body) additionally binds contents to the content length.

EXT:OPEN-HTTP will check CUSTOM:*HTTP-PROXY* on startup and parse the environment variable HTTP_PROXY if CUSTOM:*HTTP-PROXY* is NIL.

30.11.9. Function EXT:BROWSE-URL

Function (EXT:BROWSE-URL url &KEY :BROWSER :OUT) calls a browser on the URL. browser (defaults to CUSTOM:*BROWSER*) should be a valid keyword in the CUSTOM:*BROWSERS* association list. :OUT specifies the stream where the progress messages are printed (defaults to *STANDARD-OUTPUT*).

30.11.10. Variable CUSTOM:*HTTP-PROXY*

If you are behind a proxy server, you will need to set CUSTOM:*HTTP-PROXY* to a LIST (name:password host port). By default, the environment variable http_proxy is used, the expected format is "name:password@host:port". If no #\@ is present, name and password are NIL. If no #\: is present, password (or port) are NIL.

Use function (EXT:HTTP-PROXY &OPTIONAL (STRING (EXT:GETENV "http_proxy"))) to reset CUSTOM:*HTTP-PROXY*.


These notes document CLISP version 2.41Last modified: 2006-10-13