31.11. Additional Fancy Macros and Functions
Prev | Chapter 31. Platform Independent Extensions | Next

## 31.11. Additional Fancy Macros and Functions

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

### 31.11.1. Macro `EXT:ETHE`

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

### 31.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)))

### 31.11.3. Macro `EXT:MEMOIZED`

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

### 31.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 `LIST`s (1 3 5 7 9) and (0 2 4 6 8) as multiple values.

### 31.11.5. Macro `EXT:COMPILE-TIME-VALUE`

Sometimes one may want to call an expensive function at compilation time and write the primary value into the `#P".fas"` file, thus speeding up loading the `#P".fas"` file. E.g., let your file `primes.lisp` be

    (defun primes-list (limit)
      "Return the list of all primes smaller than LIMIT."
      ...)
    (defvar *all-primes* (compile-time-value (primes-list MOST-POSITIVE-FIXNUM)))

Then

`(`LOAD` "primes.lisp")`
  will not call `primes-list` and `*all-primes*` will be `NIL`.
`(`COMPILE-FILE` "primes.lisp")`
  will call `primes-list` (and will probably take a long time) and will write the resulting list into `(`COMPILE-FILE-PATHNAME` "primes.lisp")`
`(`LOAD` (`COMPILE-FILE-PATHNAME` "primes.lisp"))`
  will not call `primes-list` but `*all-primes*` will be the list computed during compilation.

The alternative is to save a memory image, which is faster than `#P".fas"` file but less portable.

### 31.11.6. 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-")))
      ...)

### 31.11.7. 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`.

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

### 31.11.9. 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`.

### 31.11.10. 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*`).

### 31.11.11. 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`) is `NIL`.

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

| These notes document CLISP version 2.45 | Last modified: 2008-05-14

Enter your search termsSubmit search form
Webclisp.cons.orgclisp.podval.orgwww.lisp.org

Prev | Up | Next
31.10. Maximum ANSI CL compliance | Home | 31.12. Customizing CLISP behavior