Поиск…


Гигиенические и ссылочно-прозрачные макросы с синтаксическими правилами

Наибольшее преимущество LISP и Scheme по сравнению с другими основными языками программирования - их макросистема. В отличие от препроцессора C и других языков макросов, макросы Scheme анализируют код как входной и возвращают расширенный код в качестве вывода. Это одно из приложений фразы Scheme «code is data», и именно это делает язык настолько мощным.

Макросы в схеме создаются с помощью define-syntax , который может определять макрос несколькими способами. Самый простой способ - использовать syntax-rules , которые используют сопоставление шаблонов для преобразования входного кода в выходной код.

В этом примере создается простой for item in list а for list as item синтаксис for list as item для циклизации элементов в списке:

(define-syntax for
  (syntax-rules (in as) ; 'in' and 'as' keywords must match in the pattern
    ; When the 'for' macro is called, try matching this pattern
    ((for element in list
          body ...) ; Match one or more body expressions
     ; Transform the input code
     (for-each (lambda (element)
                 body ...)
               list))
    ; Try matching another pattern if the first fails
    ((for list as element
          body ...)
     ; Use the existing macro for the transform
     (for element in list
          body ...))))

Затем эти два макроса можно использовать следующим образом, обеспечивая более императивный стиль:

(let ((names '(Alice Bob Eve)))
  (for name in names
    (display "Hello ")
    (display name)
    (newline))
  (for names as name
    (display "name: ")
    (display name)
    (newline)))

Запуск кода обеспечит ожидаемый результат:

Hello Alice
Hello Bob
Hello Eve
name: Alice
name: Bob
name: Eve

Наиболее распространенной ошибкой для поиска является не перенос правильных значений в макрос, что часто приводит к бесполезному сообщению об ошибке, которое применяется к расширенной форме вместо вызова макроса.

for определения синтаксиса выше не проверяют они передаются ли идентификатор и список, так что прохождение любого другого типа приведет к ошибке , указывая на имеющиеся в наличии for-each вызова , а не из for вызов. Отладка этого приводит к победе над целью макроса, поэтому пользователю нужно помещать туда чеки и сообщать об ошибках использования, которые затем можно поймать во время компиляции.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow