第拾貳章學習 Lisp 3rd Edition, Winston & Horn

MACROS AND BACKQUOTE
-----------------------------------------
MACROS TRANSLATE AND THEN EVALUATE
 
* (setf pressure -3)
* (when-plusp pressure (print 'alarm))    ;Second argument not evaluated.
NIL                                       ;Value returned.

* (setf pressure 3)
* (when-plusp pressure (print 'alarm))    ;Second argument evaluated.
ALARM                                     ;Value printed.
ALARM                                     ;Value returned.

* (setf pressure -3)
* (when (plusp pressure) (print 'alarm))
NIL

* (setf pressure 3)
* (when (plusp pressure) (print 'alarm))
ALARM
ALARM

(defmacro <macro name>
  (<parameter 1> <parameter 2> ... <parameter m>)
  <form 1> <form 2> ... <form n>)

(defmacro when-plusp-macro (number result)    ;Name and parameters.
  (list 'when                                 ;Body.
        (list 'plusp number)
        result))

* (when-plusp-macro pressure (print 'alarm))    ;如是正。
轉換成
(when (plusp pressure) (print 'alarm))    ;Given form is translated.
ALARM                                     ;New form is evaluated.
ALARM

* (when-plusp-macro pressure (print 'alarm))    ;如是負。
轉換成
(when (plusp pressure) (print 'alarm))    ;Old form is translated.
NIL                                       ;New form is evaluated.
-----------------------------------------------------------------------

THE BACKQUOTE MECHANISM SIMPLIFIES TEMPLATE FILLING

* (setf variable 'test)
TEST

* '(THIS IS A ,VARIABLE)
(THIS IS A TEST)

* (setf variable '(more difficult example))
(MORE DIFFICULT EXAMPLE)

* '(this is a ,variable)
(THIS IS A (MORE DIFFICULT EXAMPLE))

* '(this is a ,@variable)
(THIS IS A MORE DIFFICULT EXAMPLE)
-----------------------------------------------------------------

THE BACKQUOTE MECHANISM SIMPLIFIES MACRO WRITING

(when (plusp <template slot for number>)
  <template slot for result when number is positive>)

'(when (plusp ,number) ,result)

(defmacro when-plusp-with-backquote (number result)
  '(when (plusp ,number) ,result))

(defmacro when-plusp-with-backquote (number result)
  ;;Sample translation:
  ;;(when-plusp-with-backquote p (print 'alarm))
  ;;-> (when (plus p) (print 'alarm))
  '(when (plusp ,number) ,result))
----------------------------------------------------------------

OPTIONAL, REST, AND KEY PARAMETERS ENABLE MORE POWERFUL MACROS

(defmacro when-plusp-with-rest (number &rest rest)
  '(when (plusp ,number) ,@rest))        ;Splice in extra arguements.

題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題題

12-1: Suppose you are an enthusiastic user of GET, but for obscure
historical reasons, you do not like to use SETF when working with
properties.  Create PUT, a macro procedure that takes three
arguments, a symbol, a value, and a property name, such that PUt
translates

(PUT <symbol> <value> <property name>)
into
(SETF (GET <symbol> <property name>) <value>)
-------------------------------------------------------------------
12-2: You decide to create GETQ and PUTQ.  Your GETQ is to translate

(getq <SYMBOL> <PROPERTY>)
into
(get '<SYMBOL> <PROPERTY>)

and PUTQ is to translate
(putq <symbol> <property> <value>)
into
(setf (get '<symbol> property) value)
------------------------------------------------------------------
12-3: Imagine that the designers of LISP had forgotten to include
the UNLESS primitive.  Irritated, you decide to define your own
UNLESS primitive, which you call WHEN-NIL.  Define WHEN-NIL such
that it translates

(when-nil <trigger> <result>)
into
(when (not <trigger>) <result>) 
----------------------------------------------------------------
12-4: Suppose, for some immensely peculiar reason, you want a
form of LET that does not evaluate initial value forms.  Define
LETQ such that LETQ arranges the following translation:

(letq ((<variable1> <value1>)
       (<variable2> <value2>)
      ...)
  <body>)
into
(let ((<variable1> '<value1>)
      (<variable2> '<value2>)
      ...)
  <body>)
--------------------------------------------------------------
12-5: The DEFUN template is somewhat unfortunate.  Some language
designers think it is prettier to combine the procedure name with
the parameters so that the first argument is a list that resembles
a form.  Define DEFINE, a macro that uses DEFUN, but has the
following template:

(define (<procedure name> <parameter 1> ... <parameter n>)
  <body>)
---------------------------------------------------------------
12-6: Define PUNCTUATE, a procedure that takes any number of
arguments.  The first argument must be a list.  All other arguments
are to be gathered up and appended to the end of the first:

* (punctuate '(this is an example) 'so 'to 'speak)
(THIS IS AN EXAMPLE SO TO SPEAK)
--------------------------------------------------------------------
12-7: Define PUNCTUATE-MACRO, a macro procedure that takes
any number of arguments.  The first arguments must be a list.
All other arguments are to be gathered up and appended to the 
end of the first.  The first argument is to be evaluated, but
the rest are not:

* (pnctuate-macro '(this is an example) so to speak)
(THIS IS AN EXAMPLE SO TO SPEAK)

解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解解

12-1:
(defmacro put (symbol value property)
  `(setf (get ,symbol ,value) ,property))
---------------------------------------------------------------
12-2:
(defmacro getq (symbol property)
  `(get ',symbol ,property))

(defmacro putq (symbol property value)
  `(setf (get ',symbol ,property) ,value))
------------------------------------------------------------------
12-3:
(defmacro when-nil (trigger result)
  `(when (not ,trigger) ,result))
----------------------------------------------------------------
12-4:
(defmacro letq (argument-list &rest body)
  `(let ,(mapcar #'(lambda (variable-description)
                     (list (first variable-description)
                           (cons 'quote
                                 (rest variable-description))))
                 argument-list)
        ,@body))
------------------------------------------------------------------
12-5:
(defmacro define (name-and-parameters &rest body)
  `(defun ,(first name-and-parameters) ,(rest name-and-parameters)
    ,@body))
-----------------------------------------------------------------
12-6:
(defun punctuate (l &rest marks)
  (append l marks))
-----------------------------------------------------------------
12-7:
(defmacro punctuate-macro (l &rest marks)
  `(append ,l ',marks))

你可能感兴趣的:(erlang,Scheme,haskell,lisp,clojure)